OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 from copy import deepcopy | 5 from copy import deepcopy |
6 | 6 |
7 from file_system import FileSystem, StatInfo, FileNotFoundError | 7 from file_system import FileSystem, StatInfo, FileNotFoundError |
8 from future import Future | 8 from future import Future |
9 | 9 |
10 | 10 |
11 def _GetAsyncFetchCallback(unpatched_files_future, | |
12 patched_files_future, | |
13 dirs_value, | |
14 patched_file_system): | |
15 def patch_directory_listing(path, original_listing): | |
16 added, deleted, modified = ( | |
17 patched_file_system._GetDirectoryListingFromPatch(path)) | |
18 if original_listing is None: | |
19 if len(added) == 0: | |
20 raise FileNotFoundError('Directory %s not found in the patch.' % path) | |
21 return added | |
22 return list((set(original_listing) | set(added)) - set(deleted)) | |
23 | |
24 def resolve(): | |
25 files = unpatched_files_future.Get() | |
26 files.update(patched_files_future.Get()) | |
27 files.update( | |
28 dict((path, patch_directory_listing(path, dirs_value[path])) | |
29 for path in dirs_value)) | |
30 return files | |
31 | |
32 return resolve | |
33 | |
34 | |
35 class PatchedFileSystem(FileSystem): | 11 class PatchedFileSystem(FileSystem): |
36 ''' Class to fetch resources with a patch applied. | 12 ''' Class to fetch resources with a patch applied. |
37 ''' | 13 ''' |
38 def __init__(self, base_file_system, patcher): | 14 def __init__(self, base_file_system, patcher): |
39 self._base_file_system = base_file_system | 15 self._base_file_system = base_file_system |
40 self._patcher = patcher | 16 self._patcher = patcher |
41 | 17 |
42 def Read(self, paths, skip_not_found=False): | 18 def Read(self, paths, skip_not_found=False): |
43 patched_files = set() | 19 patched_files = set() |
44 added, deleted, modified = self._patcher.GetPatchedFiles() | 20 added, deleted, modified = self._patcher.GetPatchedFiles() |
45 if set(paths) & set(deleted): | 21 if set(paths) & set(deleted): |
46 def raise_file_not_found(): | 22 def raise_file_not_found(): |
47 raise FileNotFoundError('Files are removed from the patch.') | 23 raise FileNotFoundError('Files are removed from the patch.') |
48 return Future(callback=raise_file_not_found) | 24 return Future(callback=raise_file_not_found) |
| 25 |
49 patched_files |= (set(added) | set(modified)) | 26 patched_files |= (set(added) | set(modified)) |
50 dir_paths = set(path for path in paths if path.endswith('/')) | 27 dir_paths = set(path for path in paths if path.endswith('/')) |
51 file_paths = set(paths) - dir_paths | 28 file_paths = set(paths) - dir_paths |
52 patched_paths = file_paths & patched_files | 29 patched_paths = file_paths & patched_files |
53 unpatched_paths = file_paths - patched_files | 30 unpatched_paths = file_paths - patched_files |
54 return Future(callback=_GetAsyncFetchCallback( | 31 |
55 self._base_file_system.Read(unpatched_paths, | 32 def patch_directory_listing(path, original_listing): |
56 skip_not_found=skip_not_found), | 33 added, deleted, modified = ( |
57 self._patcher.Apply(patched_paths, self._base_file_system), | 34 self._GetDirectoryListingFromPatch(path)) |
58 self._TryReadDirectory(dir_paths), | 35 if original_listing is None: |
59 self)) | 36 if len(added) == 0: |
| 37 raise FileNotFoundError('Directory %s not found in the patch.' % path) |
| 38 return added |
| 39 return list((set(original_listing) | set(added)) - set(deleted)) |
| 40 |
| 41 def next(files): |
| 42 dirs_value = self._TryReadDirectory(dir_paths) |
| 43 files.update(self._patcher.Apply(patched_paths, |
| 44 self._base_file_system).Get()) |
| 45 files.update(dict((path, patch_directory_listing(path, dirs_value[path])) |
| 46 for path in dirs_value)) |
| 47 return files |
| 48 return self._base_file_system.Read(unpatched_paths, |
| 49 skip_not_found=skip_not_found).Then(next) |
60 | 50 |
61 def Refresh(self): | 51 def Refresh(self): |
62 return self._base_file_system.Refresh() | 52 return self._base_file_system.Refresh() |
63 | 53 |
64 ''' Given the list of patched files, it's not possible to determine whether | 54 ''' Given the list of patched files, it's not possible to determine whether |
65 a directory to read exists in self._base_file_system. So try reading each one | 55 a directory to read exists in self._base_file_system. So try reading each one |
66 and handle FileNotFoundError. | 56 and handle FileNotFoundError. |
67 ''' | 57 ''' |
68 def _TryReadDirectory(self, paths): | 58 def _TryReadDirectory(self, paths): |
69 value = {} | 59 value = {} |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 if filename in stat_info.child_versions: | 147 if filename in stat_info.child_versions: |
158 stat_info = StatInfo(stat_info.child_versions[filename]) | 148 stat_info = StatInfo(stat_info.child_versions[filename]) |
159 else: | 149 else: |
160 raise FileNotFoundError('%s was not in child versions' % filename) | 150 raise FileNotFoundError('%s was not in child versions' % filename) |
161 return stat_info | 151 return stat_info |
162 | 152 |
163 def GetIdentity(self): | 153 def GetIdentity(self): |
164 return '%s(%s,%s)' % (self.__class__.__name__, | 154 return '%s(%s,%s)' % (self.__class__.__name__, |
165 self._base_file_system.GetIdentity(), | 155 self._base_file_system.GetIdentity(), |
166 self._patcher.GetIdentity()) | 156 self._patcher.GetIdentity()) |
OLD | NEW |