1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import posixpath
6
7
8# TODO(kalman): Write a Path class and use that everywhere rather than a
9# utility class.
10
11
12def IsDirectory(path):
13  '''Returns whether |path| should be considered a directory.
14  '''
15  # This assertion is sprinkled throughout the code base.
16  AssertIsValid(path)
17  return path in ('', '.', '..') or path.endswith('/') or path.endswith('/..')
18
19
20def IsValid(path):
21  '''Returns whether |path| is a valid path for the purposes of the docserver.
22  Paths may not start with /, must be posix paths, and for sanity shouldn't
23  repeat the path separator //.
24  '''
25  return not path.startswith('/') and not '\\' in path and not '//' in path
26
27
28def AssertIsValid(path):
29  assert IsValid(path), 'Path "%s" is invalid' % path
30
31
32def Join(*paths):
33  assert all(IsValid(path) for path in paths), paths
34  return posixpath.join(*paths)
35
36
37def SplitParent(path):
38  '''Returns the parent directory and base name of |path| in a tuple.
39  Any trailing slash of |path| is preserved, such that the parent of
40  '/hello/world/' is '/hello' and the base is 'world/'.
41  '''
42  parent, base = posixpath.split(path.rstrip('/'))
43  if path.endswith('/'):
44    base += '/'
45  return parent, base
46
47
48def Split(path):
49  '''Returns a list of the directories and filename in a path. 'p1/p2/p3'
50  will return ['p1/', 'p2/', 'p3'].
51  '''
52  AssertIsValid(path)
53  names = [name + '/' for name in path.rstrip('/').split('/')]
54  if names and not path.endswith('/'):
55    names[-1] = names[-1][:-1]
56  return names
57
58
59def ToDirectory(path):
60  '''Returns a string representing |path| as a directory, that is,
61  IsDirectory(result) is True (and does not fail assertions). If |path| is
62  already a directory then this is a no-op.
63  '''
64  return path if IsDirectory(path) else (path + '/')
65
66
67def AssertIsDirectory(path):
68  assert IsDirectory(path), '"%s" is not a directory' % path
69
70
71def AssertIsFile(path):
72  assert not IsDirectory(path), '"%s" is not a file' % path
73
74def Segment(path):
75  '''Yields a tuple (url, file) for directory split pairs.
76  For example, if we split the path 'foo/bar/baz', it will yield:
77  ('', 'foo/bar/baz'), ('foo', "bar/baz'), ('foo/bar', 'baz'),
78  ('foo/bar/baz', '')
79  '''
80  AssertIsValid(path)
81
82  last_path = ''
83  yield (last_path, path)
84
85  for segment in (segment for segment in path.split('/') if segment != ''):
86    last_path = posixpath.join(last_path, segment)
87    rel_path = posixpath.relpath(path, last_path)
88
89    # Don't let relpath say the filename is '.'
90    if rel_path == '.':
91      rel_path = ''
92    else:
93      last_path = ToDirectory(last_path)
94
95    yield (last_path, rel_path)
96