11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)import posixpath
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from docs_server_utils import StringIdentity
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from file_system import FileSystem
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfrom future import Future
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class ChrootFileSystem(FileSystem):
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  '''ChrootFileSystem(fs, path) exposes a FileSystem whose root is |path| inside
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  |fs|, so ChrootFileSystem(fs, 'hello').Read(['world']) is equivalent to
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fs.Read(['hello/world']) with the 'hello' prefix stripped from the result.
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  '''
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def __init__(self, file_system, root):
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    '''Parameters:
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    |file_system| The FileSystem instance to transpose paths of.
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    |root|        The path to transpose all Read/Stat calls by.
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    '''
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self._file_system = file_system
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self._root = root.strip('/')
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  def Read(self, paths, skip_not_found=False):
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    # Maintain reverse mapping so the result can be mapped to the original
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    # paths given (the result from |file_system| will include |root| in the
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    # result, which would be wrong).
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    prefixed_paths = {}
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    def prefix(path):
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      prefixed = posixpath.join(self._root, path)
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      prefixed_paths[prefixed] = path
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return prefixed
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    def next(results):
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return dict((prefixed_paths[path], content)
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  for path, content in results.iteritems())
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return self._file_system.Read(tuple(prefix(path) for path in paths),
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  skip_not_found-skip_not_found).Then(next)
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def Refresh(self):
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return self._file_system.Refresh()
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def Stat(self, path):
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return self._file_system.Stat(posixpath.join(self._root, path))
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def GetIdentity(self):
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return StringIdentity(
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        '%s/%s' % (self._file_system.GetIdentity(), self._root))
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  def __repr__(self):
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 'ChrootFileSystem(%s, %s)' % (
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            self._root, repr(self._file_system))
54