Chromium Code Reviews| Index: chrome/common/extensions/docs/server2/patched_file_system.py |
| =================================================================== |
| --- chrome/common/extensions/docs/server2/patched_file_system.py (revision 0) |
| +++ chrome/common/extensions/docs/server2/patched_file_system.py (revision 0) |
| @@ -0,0 +1,154 @@ |
| +# Copyright 2013 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +from copy import deepcopy |
| +import logging |
| + |
| +from file_system import FileSystem, StatInfo, FileNotFoundError |
| +from future import Future |
| + |
| +class _AsyncFetchFuture(object): |
| + def __init__(self, |
| + svn_files_future, |
| + patched_files_future, |
| + svn_dirs_future, |
| + dir_paths, |
| + patched_file_system, |
| + patcher): |
| + self._svn_files_future = svn_files_future |
| + self._patched_files_future = patched_files_future |
| + self._svn_dirs_future = svn_dirs_future |
| + self._dir_paths = dir_paths |
| + self._patched_file_system = patched_file_system |
| + self._patcher = patcher |
|
not at google - send to devlin
2013/05/03 19:12:22
don't seem to be using this
方觉(Fang Jue)
2013/05/04 02:05:41
Done.
|
| + |
| + def Get(self): |
| + files = self._svn_files_future.Get() |
| + files.update(self._patched_files_future.Get()) |
| + dirs = self._svn_dirs_future.Get() |
| + files.update({path: self._PatchDirectoryListing(path, |
| + dirs[path]) |
|
not at google - send to devlin
2013/05/03 19:12:22
why is this on a line by itself?
方觉(Fang Jue)
2013/05/04 02:05:41
Done.
|
| + for path in self._dir_paths}) |
| + return files |
| + |
| + def _PatchDirectoryListing(self, path, original_listing): |
| + added, deleted, modified = ( |
| + self._patched_file_system._GetDirectoryListingFromPatch(path)) |
| + return list(set(original_listing) | set(added) - set(deleted)) |
| + |
| +class Patcher(object): |
| + def GetPatchedFiles(self): |
| + ''' Returns (added_files, deleted_files, modified_files). |
| + ''' |
| + raise NotImplementedError() |
| + |
| + def GetVersion(self): |
| + ''' Returns patch version. Returns None when nothing is patched by the |
| + pathcer. |
| + ''' |
| + raise NotImplementedError() |
| + |
| + def Apply(self, paths, file_system, binary): |
| + ''' Apply the patch to added/modified files. Returns Future with patched |
| + data. Throws FileNotFoundError if |paths| contains deleted files. |
| + ''' |
| + raise NotImplementedError() |
|
not at google - send to devlin
2013/05/03 19:12:22
pls put this in a different file.
方觉(Fang Jue)
2013/05/04 02:05:41
Done.
|
| + |
| +class PatchedFileSystem(FileSystem): |
| + ''' Class to fetch resources with a patch applied. |
| + ''' |
| + def __init__(self, svn_file_system, patcher): |
|
not at google - send to devlin
2013/05/03 19:12:22
I'm going to start calling svn_file_system 'host_f
方觉(Fang Jue)
2013/05/04 02:05:41
Done.
|
| + self._svn_file_system = svn_file_system |
| + self._patcher = patcher |
| + |
| + def Read(self, paths, binary=False): |
| + patched_files = set() |
| + for files in self._patcher.GetPatchedFiles(): |
| + patched_files |= set(files) |
| + dir_paths = {path for path in paths if path.endswith('/')} |
| + file_paths = set(paths) - dir_paths |
| + patched_paths = file_paths & patched_files |
| + unpatched_paths = file_paths - patched_files |
| + return Future(delegate=_AsyncFetchFuture( |
| + self._svn_file_system.Read(unpatched_paths, binary), |
| + self._patcher.Apply(patched_paths, self._svn_file_system, binary), |
| + self._svn_file_system.Read(dir_paths, binary), |
| + dir_paths, |
| + self, |
| + self._patcher)) |
| + |
| + def _GetDirectoryListingFromPatch(self, path): |
| + assert path.endswith('/') |
| + def _FindChildrenInPath(files, path): |
| + result = [] |
| + for f in files: |
| + if f.startswith(path): |
| + child_path = f[len(path):] |
| + if '/' in child_path: |
| + child_name = child_path[0:child_path.find('/') + 1] |
| + else: |
| + child_name = child_path |
| + result.append(child_name) |
| + return result |
| + |
| + return (tuple(_FindChildrenInPath(files, path) |
| + for files in self._patcher.GetPatchedFiles())) |
| + |
| + def _PatchStat(self, stat_info, version, added, deleted, modified): |
| + assert len(added) + len(deleted) + len(modified) > 0 |
| + |
| + # Deep copy before patching to make sure it doesn't interfere with values |
| + # cached in memory. |
| + stat_info = deepcopy(stat_info) |
|
not at google - send to devlin
2013/05/03 19:12:22
yep, thanks
|
| + |
| + stat_info.version = version |
| + if stat_info.child_versions is not None: |
| + for child in added + modified: |
| + stat_info.child_versions[child] = version |
| + for child in deleted: |
| + if stat_info.child_versions.get(child): |
| + del stat_info.child_versions[child] |
| + |
| + return stat_info |
| + |
| + def Stat(self, path): |
| + version = self._patcher.GetVersion() |
| + if version is None: |
| + return self._svn_file_system.Stat(path) |
| + version = 'patched_%s' % version |
| + |
| + directory, filename = path.rsplit('/', 1) |
| + added, deleted, modified = self._GetDirectoryListingFromPatch( |
| + directory + '/') |
| + |
| + if len(added) > 0: |
| + # There are new files added. It's possible (if |directory| is new) that |
| + # self._svn_file_system.Stat will throw an exception. |
| + try: |
| + stat_info = self._PatchStat(self._svn_file_system.Stat(directory + '/'), |
| + version, |
| + added, |
| + deleted, |
| + modified) |
| + except FileNotFoundError: |
| + stat_info = StatInfo(version, {child: version |
| + for child in added + modified}) |
| + elif len(deleted) + len(modified) > 0: |
| + # No files were added. |
| + stat_info = self._PatchStat(self._svn_file_system.Stat(path), |
| + version, |
| + added, |
| + deleted, |
| + modified) |
| + else: |
| + # No changes are made in this directory. |
| + return self._svn_file_system.Stat(path) |
| + |
| + if stat_info.child_versions is not None: |
| + if filename: |
| + if filename in stat_info.child_versions: |
| + stat_info.version = stat_info.child_versions[filename] |
| + else: |
| + raise FileNotFoundError('%s was not in child versions' % filename) |
| + return stat_info |
| Property changes on: chrome/common/extensions/docs/server2/patched_file_system.py |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |