| 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 |