parameters: (self, file_path)
return_statement: return _ComponentsToPath(resolved_components)
docstring: Follow a path, resolving symlinks.
  
      ResolvePath traverses the filesystem along the specified file path,
      resolving file names and symbolic links until all elements of the path are
      exhausted, or we reach a file which does not exist.  If all the elements
      are not consumed, they just get appended to the path resolved so far.
      This gives us the path which is as resolved as it can be, even if the file
      does not exist.
  
      This behavior mimics Unix semantics, and is best shown by example.  Given a
      file system that looks like this:
  
            /a/b/
            /a/b/c -> /a/b2          c is a symlink to /a/b2
            /a/b2/x
            /a/c   -> ../d
            /a/x   -> y
       Then:
            /a/b/x      =>  /a/b/x
            /a/c        =>  /a/d
            /a/x        =>  /a/y
            /a/b/c/d/e  =>  /a/b2/d/e
  
      Args:
        file_path:  path to examine
  
      Returns:
        resolved_path (string) or None
  
      Raises:
        TypeError: if file_path is None
        IOError: if file_path is '' or a part of the path doesn't exist
docstring_summary: Follow a path, resolving symlinks.
docstring_tokens: Follow a path resolving symlinks .
function: def ResolvePath(self, file_path):
      """Follow a path, resolving symlinks.
  
      ResolvePath traverses the filesystem along the specified file path,
      resolving file names and symbolic links until all elements of the path are
      exhausted, or we reach a file which does not exist.  If all the elements
      are not consumed, they just get appended to the path resolved so far.
      This gives us the path which is as resolved as it can be, even if the file
      does not exist.
  
      This behavior mimics Unix semantics, and is best shown by example.  Given a
      file system that looks like this:
  
            /a/b/
            /a/b/c -> /a/b2          c is a symlink to /a/b2
            /a/b2/x
            /a/c   -> ../d
            /a/x   -> y
       Then:
            /a/b/x      =>  /a/b/x
            /a/c        =>  /a/d
            /a/x        =>  /a/y
            /a/b/c/d/e  =>  /a/b2/d/e
  
      Args:
        file_path:  path to examine
  
      Returns:
        resolved_path (string) or None
  
      Raises:
        TypeError: if file_path is None
        IOError: if file_path is '' or a part of the path doesn't exist
      """
  
      def _ComponentsToPath(component_folders):
        return '%s%s' % (self.path_separator,
                         self.path_separator.join(component_folders))
  
      def _ValidRelativePath(file_path):
        while file_path and '/..' in file_path:
          file_path = file_path[:file_path.rfind('/..')]
          if not self.Exists(self.NormalizePath(file_path)):
            return False
        return True
  
      def _FollowLink(link_path_components, link):
        """Follow a link w.r.t. a path resolved so far.
  
        The component is either a real file, which is a no-op, or a symlink.
        In the case of a symlink, we have to modify the path as built up so far
          /a/b => ../c   should yield /a/../c (which will normalize to /a/c)
          /a/b => x      should yield /a/x
          /a/b => /x/y/z should yield /x/y/z
        The modified path may land us in a new spot which is itself a
        link, so we may repeat the process.
  
        Args:
          link_path_components: The resolved path built up to the link so far.
          link: The link object itself.
  
        Returns:
          (string) the updated path resolved after following the link.
  
        Raises:
          IOError: if there are too many levels of symbolic link
        """
        link_path = link.contents
        # For links to absolute paths, we want to throw out everything in the
        # path built so far and replace with the link.  For relative links, we
        # have to append the link to what we have so far,
        if not link_path.startswith(self.path_separator):
          # Relative path.  Append remainder of path to what we have processed
          # so far, excluding the name of the link itself.
          # /a/b => ../c   should yield /a/../c (which will normalize to /c)
          # /a/b => d should yield a/d
          components = link_path_components[:-1]
          components.append(link_path)
          link_path = self.path_separator.join(components)
        # Don't call self.NormalizePath(), as we don't want to prepend self.cwd.
        return self.CollapsePath(link_path)
  
      if file_path is None:
        # file.open(None) raises TypeError, so mimic that.
        raise TypeError('Expected file system path string, received None')
      if not file_path or not _ValidRelativePath(file_path):
        # file.open('') raises IOError, so mimic that, and validate that all
        # parts of a relative path exist.
        raise IOError(errno.ENOENT,
                      'No such file or directory: \'%s\'' % file_path)
      file_path = self.NormalizePath(file_path)
      if file_path == self.root.name:
        return file_path
  
      current_dir = self.root
      path_components = self.GetPathComponents(file_path)
  
      resolved_components = []
      link_depth = 0
      while path_components:
        component = path_components.pop(0)
        resolved_components.append(component)
        if component not in current_dir.contents:
          # The component of the path at this point does not actually exist in
          # the folder.   We can't resolve the path any more.  It is legal to link
          # to a file that does not yet exist, so rather than raise an error, we
          # just append the remaining components to what return path we have built
          # so far and return that.
          resolved_components.extend(path_components)
          break
        current_dir = current_dir.contents[component]
  
        # Resolve any possible symlinks in the current path component.
        if stat.S_ISLNK(current_dir.st_mode):
          # This link_depth check is not really meant to be an accurate check.
          # It is just a quick hack to prevent us from looping forever on
          # cycles.
          link_depth += 1
          if link_depth > _MAX_LINK_DEPTH:
            raise IOError(errno.EMLINK,
                          'Too many levels of symbolic links: \'%s\'' %
                          _ComponentsToPath(resolved_components))
          link_path = _FollowLink(resolved_components, current_dir)
  
          # Following the link might result in the complete replacement of the
          # current_dir, so we evaluate the entire resulting path.
          target_components = self.GetPathComponents(link_path)
          path_components = target_components + path_components
          resolved_components = []
          current_dir = self.root
      return _ComponentsToPath(resolved_components)
function_tokens: def ResolvePath ( self , file_path ) : def _ComponentsToPath ( component_folders ) : return '%s%s' % ( self . path_separator , self . path_separator . join ( component_folders ) ) def _ValidRelativePath ( file_path ) : while file_path and '/..' in file_path : file_path = file_path [ : file_path . rfind ( '/..' ) ] if not self . Exists ( self . NormalizePath ( file_path ) ) : return False return True def _FollowLink ( link_path_components , link ) : """Follow a link w.r.t. a path resolved so far.
  
        The component is either a real file, which is a no-op, or a symlink.
        In the case of a symlink, we have to modify the path as built up so far
          /a/b => ../c   should yield /a/../c (which will normalize to /a/c)
          /a/b => x      should yield /a/x
          /a/b => /x/y/z should yield /x/y/z
        The modified path may land us in a new spot which is itself a
        link, so we may repeat the process.
  
        Args:
          link_path_components: The resolved path built up to the link so far.
          link: The link object itself.
  
        Returns:
          (string) the updated path resolved after following the link.
  
        Raises:
          IOError: if there are too many levels of symbolic link
        """ link_path = link . contents # For links to absolute paths, we want to throw out everything in the # path built so far and replace with the link.  For relative links, we # have to append the link to what we have so far, if not link_path . startswith ( self . path_separator ) : # Relative path.  Append remainder of path to what we have processed # so far, excluding the name of the link itself. # /a/b => ../c   should yield /a/../c (which will normalize to /c) # /a/b => d should yield a/d components = link_path_components [ : - 1 ] components . append ( link_path ) link_path = self . path_separator . join ( components ) # Don't call self.NormalizePath(), as we don't want to prepend self.cwd. return self . CollapsePath ( link_path ) if file_path is None : # file.open(None) raises TypeError, so mimic that. raise TypeError ( 'Expected file system path string, received None' ) if not file_path or not _ValidRelativePath ( file_path ) : # file.open('') raises IOError, so mimic that, and validate that all # parts of a relative path exist. raise IOError ( errno . ENOENT , 'No such file or directory: \'%s\'' % file_path ) file_path = self . NormalizePath ( file_path ) if file_path == self . root . name : return file_path current_dir = self . root path_components = self . GetPathComponents ( file_path ) resolved_components = [ ] link_depth = 0 while path_components : component = path_components . pop ( 0 ) resolved_components . append ( component ) if component not in current_dir . contents : # The component of the path at this point does not actually exist in # the folder.   We can't resolve the path any more.  It is legal to link # to a file that does not yet exist, so rather than raise an error, we # just append the remaining components to what return path we have built # so far and return that. resolved_components . extend ( path_components ) break current_dir = current_dir . contents [ component ] # Resolve any possible symlinks in the current path component. if stat . S_ISLNK ( current_dir . st_mode ) : # This link_depth check is not really meant to be an accurate check. # It is just a quick hack to prevent us from looping forever on # cycles. link_depth += 1 if link_depth > _MAX_LINK_DEPTH : raise IOError ( errno . EMLINK , 'Too many levels of symbolic links: \'%s\'' % _ComponentsToPath ( resolved_components ) ) link_path = _FollowLink ( resolved_components , current_dir ) # Following the link might result in the complete replacement of the # current_dir, so we evaluate the entire resulting path. target_components = self . GetPathComponents ( link_path ) path_components = target_components + path_components resolved_components = [ ] current_dir = self . root return _ComponentsToPath ( resolved_components )