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
7from docs_server_utils import StringIdentity
8from file_system import FileSystem
9from future import Future
10
11
12class ChrootFileSystem(FileSystem):
13  '''ChrootFileSystem(fs, path) exposes a FileSystem whose root is |path| inside
14  |fs|, so ChrootFileSystem(fs, 'hello').Read(['world']) is equivalent to
15  fs.Read(['hello/world']) with the 'hello' prefix stripped from the result.
16  '''
17
18  def __init__(self, file_system, root):
19    '''Parameters:
20    |file_system| The FileSystem instance to transpose paths of.
21    |root|        The path to transpose all Read/Stat calls by.
22    '''
23    self._file_system = file_system
24    self._root = root.strip('/')
25
26  def Read(self, paths, skip_not_found=False):
27    # Maintain reverse mapping so the result can be mapped to the original
28    # paths given (the result from |file_system| will include |root| in the
29    # result, which would be wrong).
30    prefixed_paths = {}
31    def prefix(path):
32      prefixed = posixpath.join(self._root, path)
33      prefixed_paths[prefixed] = path
34      return prefixed
35    future_result = self._file_system.Read(
36        tuple(prefix(path) for path in paths),
37        skip_not_found=skip_not_found)
38    def resolve():
39      return dict((prefixed_paths[path], content)
40                  for path, content in future_result.Get().iteritems())
41    return Future(callback=resolve)
42
43  def Refresh(self):
44    return self._file_system.Refresh()
45
46  def Stat(self, path):
47    return self._file_system.Stat(posixpath.join(self._root, path))
48
49  def GetIdentity(self):
50    return StringIdentity(
51        '%s/%s' % (self._file_system.GetIdentity(), self._root))
52
53  def __repr__(self):
54    return 'ChrootFileSystem(%s, %s)' % (
55            self._root, repr(self._file_system))
56