OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import os | 5 import os |
6 import sys | 6 import sys |
7 | 7 |
8 from docs_server_utils import StringIdentity | 8 from docs_server_utils import StringIdentity |
9 from file_system import FileSystem, FileNotFoundError, StatInfo, ToUnicode | 9 from file_system import FileSystem, FileNotFoundError, StatInfo, ToUnicode |
10 from future import Future | 10 from future import Future |
11 | 11 |
12 def _ConvertToFilepath(path): | 12 def _ConvertToFilepath(path): |
13 return path.replace('/', os.sep) | 13 return path.replace('/', os.sep) |
14 | 14 |
| 15 def _ConvertFromFilepath(path): |
| 16 return path.replace(os.sep, '/') |
| 17 |
| 18 def _ReadFile(filename, binary): |
| 19 try: |
| 20 mode = 'rb' if binary else 'r' |
| 21 with open(filename, mode) as f: |
| 22 contents = f.read() |
| 23 if binary: |
| 24 return contents |
| 25 return ToUnicode(contents) |
| 26 except IOError as e: |
| 27 raise FileNotFoundError('Read failed for %s: %s' % (filename, e)) |
| 28 |
| 29 def _ListDir(dir_name): |
| 30 all_files = [] |
| 31 try: |
| 32 files = os.listdir(dir_name) |
| 33 except OSError as e: |
| 34 raise FileNotFoundError('os.listdir failed for %s: %s' % (dir_name, e)) |
| 35 for os_path in files: |
| 36 posix_path = _ConvertFromFilepath(os_path) |
| 37 if os_path.startswith('.'): |
| 38 continue |
| 39 if os.path.isdir(os.path.join(dir_name, os_path)): |
| 40 all_files.append(posix_path + '/') |
| 41 else: |
| 42 all_files.append(posix_path) |
| 43 return all_files |
| 44 |
| 45 def _CreateStatInfo(path): |
| 46 try: |
| 47 path_mtime = os.stat(path).st_mtime |
| 48 if path.endswith('/'): |
| 49 child_versions = dict((_ConvertFromFilepath(filename), |
| 50 os.stat(os.path.join(path, filename)).st_mtime) |
| 51 for filename in os.listdir(path)) |
| 52 # This file system stat mimics subversion, where the stat of directories |
| 53 # is max(file stats). That means we need to recursively check the whole |
| 54 # file system tree :\ so approximate that by just checking this dir. |
| 55 version = max([path_mtime] + child_versions.values()) |
| 56 else: |
| 57 child_versions = None |
| 58 version = path_mtime |
| 59 return StatInfo(version, child_versions) |
| 60 except OSError as e: |
| 61 raise FileNotFoundError('os.stat failed for %s: %s' % (path, e)) |
| 62 |
15 class LocalFileSystem(FileSystem): | 63 class LocalFileSystem(FileSystem): |
16 '''FileSystem implementation which fetches resources from the local | 64 '''FileSystem implementation which fetches resources from the local |
17 filesystem. | 65 filesystem. |
18 ''' | 66 ''' |
19 def __init__(self, base_path): | 67 def __init__(self, base_path): |
20 self._base_path = _ConvertToFilepath(base_path) | 68 self._base_path = _ConvertToFilepath(base_path) |
21 | 69 |
22 @staticmethod | 70 @staticmethod |
23 def Create(): | 71 def Create(): |
24 return LocalFileSystem(os.path.join(sys.path[0], os.pardir, os.pardir)) | 72 return LocalFileSystem(os.path.join(sys.path[0], os.pardir, os.pardir)) |
25 | 73 |
26 def _ReadFile(self, filename, binary): | |
27 try: | |
28 mode = 'rb' if binary else 'r' | |
29 with open(os.path.join(self._base_path, filename), mode) as f: | |
30 contents = f.read() | |
31 if binary: | |
32 return contents | |
33 return ToUnicode(contents) | |
34 except IOError as e: | |
35 raise FileNotFoundError('Read failed for %s: %s' % (filename, e)) | |
36 | |
37 def _ListDir(self, dir_name): | |
38 all_files = [] | |
39 full_path = os.path.join(self._base_path, dir_name) | |
40 try: | |
41 files = os.listdir(full_path) | |
42 except OSError as e: | |
43 raise FileNotFoundError('os.listdir failed for %s: %s' % (dir_name, e)) | |
44 for path in files: | |
45 if path.startswith('.'): | |
46 continue | |
47 if os.path.isdir(os.path.join(full_path, path)): | |
48 all_files.append(path + '/') | |
49 else: | |
50 all_files.append(path) | |
51 return all_files | |
52 | |
53 def Read(self, paths, binary=False): | 74 def Read(self, paths, binary=False): |
54 result = {} | 75 result = {} |
55 for path in paths: | 76 for path in paths: |
| 77 full_path = os.path.join(self._base_path, |
| 78 _ConvertToFilepath(path).lstrip(os.sep)) |
56 if path.endswith('/'): | 79 if path.endswith('/'): |
57 result[path] = self._ListDir(_ConvertToFilepath(path)) | 80 result[path] = _ListDir(full_path) |
58 else: | 81 else: |
59 result[path] = self._ReadFile(_ConvertToFilepath(path), binary) | 82 result[path] = _ReadFile(full_path, binary) |
60 return Future(value=result) | 83 return Future(value=result) |
61 | 84 |
62 def _CreateStatInfo(self, path): | |
63 try: | |
64 path_mtime = os.stat(path).st_mtime | |
65 if path.endswith('/'): | |
66 child_versions = dict( | |
67 (filename, os.stat(os.path.join(path, filename)).st_mtime) | |
68 for filename in os.listdir(path)) | |
69 # This file system stat mimics subversion, where the stat of directories | |
70 # is max(file stats). That means we need to recursively check the whole | |
71 # file system tree :\ so approximate that by just checking this dir. | |
72 version = max([path_mtime] + child_versions.values()) | |
73 else: | |
74 child_versions = None | |
75 version = path_mtime | |
76 return StatInfo(version, child_versions) | |
77 except OSError as e: | |
78 raise FileNotFoundError('os.stat failed for %s: %s' % (path, e)) | |
79 | |
80 def Stat(self, path): | 85 def Stat(self, path): |
81 return self._CreateStatInfo(os.path.join(self._base_path, path)) | 86 full_path = os.path.join(self._base_path, |
| 87 _ConvertToFilepath(path).lstrip(os.sep)) |
| 88 return _CreateStatInfo(full_path) |
82 | 89 |
83 def GetIdentity(self): | 90 def GetIdentity(self): |
84 return '@'.join((self.__class__.__name__, StringIdentity(self._base_path))) | 91 return '@'.join((self.__class__.__name__, StringIdentity(self._base_path))) |
OLD | NEW |