Home | History | Annotate | Download | only in server2
      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 
      5 import posixpath
      6 
      7 
      8 # TODO(kalman): Write a Path class and use that everywhere rather than a
      9 # utility class.
     10 
     11 
     12 def 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 
     20 def 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 
     28 def AssertIsValid(path):
     29   assert IsValid(path), 'Path "%s" is invalid' % path
     30 
     31 
     32 def Join(*paths):
     33   assert all(IsValid(path) for path in paths), paths
     34   return posixpath.join(*paths)
     35 
     36 
     37 def 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 
     48 def 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 
     59 def 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 
     67 def AssertIsDirectory(path):
     68   assert IsDirectory(path), '"%s" is not a directory' % path
     69 
     70 
     71 def AssertIsFile(path):
     72   assert not IsDirectory(path), '"%s" is not a file' % path
     73 
     74 def 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