Home | History | Annotate | Download | only in server2
      1 # Copyright (c) 2012 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 class FileNotFoundError(Exception):
      6   def __init__(self, filename):
      7     Exception.__init__(self, filename)
      8 
      9 class StatInfo(object):
     10   '''The result of calling Stat on a FileSystem.
     11   '''
     12   def __init__(self, version, child_versions=None):
     13     self.version = version
     14     self.child_versions = child_versions
     15 
     16   def __eq__(self, other):
     17     return (isinstance(other, StatInfo) and
     18             self.version == other.version and
     19             self.child_versions == other.child_versions)
     20 
     21   def __ne__(self, other):
     22     return not (self == other)
     23 
     24   def __str__(self):
     25     return '{version: %s, child_versions: %s}' % (self.version,
     26                                                   self.child_versions)
     27 
     28   def __repr__(self):
     29     return str(self)
     30 
     31 def ToUnicode(data):
     32   '''Returns the str |data| as a unicode object. It's expected to be utf8, but
     33   there are also latin-1 encodings in there for some reason. Fall back to that.
     34   '''
     35   try:
     36     return unicode(data, 'utf-8')
     37   except:
     38     return unicode(data, 'latin-1')
     39 
     40 class FileSystem(object):
     41   '''A FileSystem interface that can read files and directories.
     42   '''
     43   def Read(self, paths, binary=False):
     44     '''Reads each file in paths and returns a dictionary mapping the path to the
     45     contents. If a path in paths ends with a '/', it is assumed to be a
     46     directory, and a list of files in the directory is mapped to the path.
     47 
     48     If binary=False, the contents of each file will be unicode parsed as utf-8,
     49     and failing that as latin-1 (some extension docs use latin-1). If
     50     binary=True then the contents will be a str.
     51     '''
     52     raise NotImplementedError(self.__class__)
     53 
     54   def ReadSingle(self, path, binary=False):
     55     '''Reads a single file from the FileSystem.
     56     '''
     57     return self.Read([path], binary=binary).Get()[path]
     58 
     59   # TODO(cduvall): Allow Stat to take a list of paths like Read.
     60   def Stat(self, path):
     61     '''Returns a |StatInfo| object containing the version of |path|. If |path|
     62     is a directory, |StatInfo| will have the versions of all the children of
     63     the directory in |StatInfo.child_versions|.
     64     '''
     65     raise NotImplementedError(self.__class__)
     66 
     67   def GetIdentity(self):
     68     '''The identity of the file system, exposed for caching classes to
     69     namespace their caches. this will usually depend on the configuration of
     70     that file system - e.g. a LocalFileSystem with a base path of /var is
     71     different to that of a SubversionFileSystem with a base path of /bar, is
     72     different to a LocalFileSystem with a base path of /usr.
     73     '''
     74     raise NotImplementedError(self.__class__)
     75 
     76   def Walk(self, root):
     77     '''Recursively walk the directories in a file system, starting with root.
     78     Emulates os.walk from the standard os module.
     79     '''
     80     basepath = root.rstrip('/') + '/'
     81 
     82     def walk(root):
     83       if not root.endswith('/'):
     84         root += '/'
     85 
     86       dirs, files = [], []
     87 
     88       for f in self.ReadSingle(root):
     89         if f.endswith('/'):
     90           dirs.append(f)
     91         else:
     92           files.append(f)
     93 
     94       yield root[len(basepath):].rstrip('/'), dirs, files
     95 
     96       for d in dirs:
     97         for walkinfo in walk(root + d):
     98           yield walkinfo
     99 
    100     for walkinfo in walk(root):
    101       yield walkinfo
    102