Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(472)

Side by Side Diff: chrome/common/extensions/docs/server2/patched_file_system.py

Issue 14125010: Docserver: Add support for viewing docs with a codereview patch applied (Closed) Base URL: https://src.chromium.org/svn/trunk/src/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
5 from copy import deepcopy
6 import logging
7
8 from file_system import FileSystem, StatInfo, FileNotFoundError
9 from future import Future
10
11 class _AsyncFetchFuture(object):
12 def __init__(self,
13 unpatched_files_future,
14 patched_files_future,
15 svn_dirs_future,
16 dir_paths,
17 patched_file_system):
18 self._unpatched_files_future = unpatched_files_future
19 self._patched_files_future = patched_files_future
20 self._svn_dirs_future = svn_dirs_future
21 self._dir_paths = dir_paths
22 self._patched_file_system = patched_file_system
23
24 def Get(self):
25 files = self._unpatched_files_future.Get()
26 files.update(self._patched_files_future.Get())
27 dirs = self._svn_dirs_future.Get()
28 files.update({path: self._PatchDirectoryListing(path, dirs[path])
29 for path in self._dir_paths})
30 return files
31
32 def _PatchDirectoryListing(self, path, original_listing):
33 added, deleted, modified = (
34 self._patched_file_system._GetDirectoryListingFromPatch(path))
35 return list(set(original_listing) | set(added) - set(deleted))
36
37 class PatchedFileSystem(FileSystem):
38 ''' Class to fetch resources with a patch applied.
39 '''
40 def __init__(self, host_file_system, patcher):
41 self._host_file_system = host_file_system
42 self._patcher = patcher
43
44 def Read(self, paths, binary=False):
45 patched_files = set()
46 for files in self._patcher.GetPatchedFiles():
47 patched_files |= set(files)
48 dir_paths = {path for path in paths if path.endswith('/')}
49 file_paths = set(paths) - dir_paths
50 patched_paths = file_paths & patched_files
51 unpatched_paths = file_paths - patched_files
52 return Future(delegate=_AsyncFetchFuture(
53 self._host_file_system.Read(unpatched_paths, binary),
54 self._patcher.Apply(patched_paths, self._host_file_system, binary),
55 self._host_file_system.Read(dir_paths, binary),
56 dir_paths,
57 self))
58
59 def _GetDirectoryListingFromPatch(self, path):
60 assert path.endswith('/')
61 def _FindChildrenInPath(files, path):
62 result = []
63 for f in files:
64 if f.startswith(path):
65 child_path = f[len(path):]
66 if '/' in child_path:
67 child_name = child_path[0:child_path.find('/') + 1]
68 else:
69 child_name = child_path
70 result.append(child_name)
71 return result
72
73 return (tuple(_FindChildrenInPath(files, path)
74 for files in self._patcher.GetPatchedFiles()))
75
76 def _PatchStat(self, stat_info, version, added, deleted, modified):
77 assert len(added) + len(deleted) + len(modified) > 0
78
79 # Deep copy before patching to make sure it doesn't interfere with values
80 # cached in memory.
81 stat_info = deepcopy(stat_info)
82
83 stat_info.version = version
84 if stat_info.child_versions is not None:
85 for child in added + modified:
86 stat_info.child_versions[child] = version
87 for child in deleted:
88 if stat_info.child_versions.get(child):
89 del stat_info.child_versions[child]
90
91 return stat_info
92
93 def Stat(self, path):
94 version = self._patcher.GetVersion()
95 if version is None:
96 return self._host_file_system.Stat(path)
97 version = 'patched_%s' % version
98
99 directory, filename = path.rsplit('/', 1)
100 added, deleted, modified = self._GetDirectoryListingFromPatch(
101 directory + '/')
102
103 if len(added) > 0:
104 # There are new files added. It's possible (if |directory| is new) that
105 # self._host_file_system.Stat will throw an exception.
106 try:
107 stat_info = self._PatchStat(
108 self._host_file_system.Stat(directory + '/'),
109 version,
110 added,
111 deleted,
112 modified)
113 except FileNotFoundError:
114 stat_info = StatInfo(version, {child: version
115 for child in added + modified})
116 elif len(deleted) + len(modified) > 0:
117 # No files were added.
118 stat_info = self._PatchStat(self._host_file_system.Stat(path),
119 version,
120 added,
121 deleted,
122 modified)
123 else:
124 # No changes are made in this directory.
125 return self._host_file_system.Stat(path)
126
127 if stat_info.child_versions is not None:
128 if filename:
129 if filename in stat_info.child_versions:
130 stat_info.version = stat_info.child_versions[filename]
131 else:
132 raise FileNotFoundError('%s was not in child versions' % filename)
133 return stat_info
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698