15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import posixpath
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# TODO(kalman): Write a Path class and use that everywhere rather than a
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# utility class.
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def IsDirectory(path):
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''Returns whether |path| should be considered a directory.
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  # This assertion is sprinkled throughout the code base.
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AssertIsValid(path)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return path in ('', '.', '..') or path.endswith('/') or path.endswith('/..')
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def IsValid(path):
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''Returns whether |path| is a valid path for the purposes of the docserver.
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Paths may not start with /, must be posix paths, and for sanity shouldn't
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  repeat the path separator //.
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return not path.startswith('/') and not '\\' in path and not '//' in path
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def AssertIsValid(path):
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert IsValid(path), 'Path "%s" is invalid' % path
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def Join(*paths):
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert all(IsValid(path) for path in paths), paths
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return posixpath.join(*paths)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def SplitParent(path):
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''Returns the parent directory and base name of |path| in a tuple.
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Any trailing slash of |path| is preserved, such that the parent of
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '/hello/world/' is '/hello' and the base is 'world/'.
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parent, base = posixpath.split(path.rstrip('/'))
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if path.endswith('/'):
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base += '/'
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return parent, base
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def ToDirectory(path):
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''Returns a string representing |path| as a directory, that is,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IsDirectory(result) is True (and does not fail assertions). If |path| is
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  already a directory then this is a no-op.
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  '''
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return path if IsDirectory(path) else (path + '/')
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def AssertIsDirectory(path):
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert IsDirectory(path), '"%s" is not a directory' % path
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def AssertIsFile(path):
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert not IsDirectory(path), '"%s" is not a file' % path
62