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

Side by Side Diff: chrome/common/extensions/docs/server2/rietveld_patcher.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: add executable bits for tests 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
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 import json
6 import tarfile
7 from StringIO import StringIO
8
9 from file_system import FileNotFoundError, ToUnicode
10 from future import Future
11 from patcher import Patcher
12 import svn_constants
13
14 _CHROMIUM_REPO_BASEURLS = [
15 'https://src.chromium.org/svn/trunk/src/',
16 'http://src.chromium.org/svn/trunk/src/',
17 'svn://svn.chromium.org/chrome/trunk/src',
18 'https://chromium.googlesource.com/chromium/src.git@master',
19 'http://git.chromium.org/chromium/src.git@master',
20 ]
21
22 _DOCS_PATHS = [
23 svn_constants.API_PATH,
24 svn_constants.TEMPLATE_PATH,
25 svn_constants.STATIC_PATH
26 ]
27
28 class RietveldPatcherError(Exception):
29 def __init__(self, message):
30 self.message = message
31
32 class _AsyncFetchFuture(object):
33 def __init__(self,
34 base_path,
35 issue,
36 patchset,
37 files,
38 binary,
39 fetcher):
40 self._base_path = base_path
41 self._issue = issue
42 self._patchset = patchset
43 self._files = files
44 self._binary = binary
45 self._tarball = fetcher.FetchAsync('tarball/%s/%s' % (issue, patchset))
46
47 def Get(self):
48 tarball_result = self._tarball.Get()
49 if tarball_result.status_code != 200:
50 raise RietveldPatcherError(
51 'Failed to download tarball for issue %s patchset %s. Status: %s' %
52 (self._issue, self._patchset, tarball_result.status_code))
53
54 try:
55 tar = tarfile.open(fileobj=StringIO(tarball_result.content))
56 except tarfile.TarError as e:
57 raise RietveldPatcherError(
58 'Error loading tarball for issue %s patchset %s.' % (self._issue,
59 self._patchset))
60
61 self._value = {}
62 for path in self._files:
63 if self._base_path:
64 tar_path = 'b/%s/%s' % (self._base_path, path)
65 else:
66 tar_path = 'b/%s' % path
67
68 patched_file = None
69 try:
70 patched_file = tar.extractfile(tar_path)
71 data = patched_file.read()
72 except tarfile.TarError as e:
73 # Show appropriate error message in the unlikely case that the tarball
74 # is corrupted.
75 raise RietveldPatcherError(
76 'Error extracting tarball for issue %s patchset %s file %s.' %
77 (self._issue, self._patchset, tar_path))
78 except KeyError as e:
79 raise FileNotFoundError(
80 'File %s not found in the tarball for issue %s patchset %s' %
81 (tar_path, self._issue, self._patchset))
82 finally:
83 if patched_file:
84 patched_file.close()
85
86 if self._binary:
87 self._value[path] = data
88 else:
89 self._value[path] = ToUnicode(data)
90
91 return self._value
92
93 class RietveldPatcher(Patcher):
94 ''' Class to fetch resources from a patchset in Rietveld.
95 '''
96 def __init__(self,
97 base_path,
98 issue,
99 fetcher):
100 self._base_path = base_path
101 self._issue = issue
102 self._fetcher = fetcher
103 self._cache = None
104
105 # In RietveldPatcher, the version is the latest patchset number.
106 def GetVersion(self):
107 try:
108 issue_json = json.loads(self._fetcher.Fetch(
109 'api/%s' % self._issue).content)
110 except Exception as e:
111 raise RietveldPatcherError(
112 'Failed to fetch information for issue %s.' % self._issue)
113
114 if issue_json.get('closed'):
115 raise RietveldPatcherError('Issue %s has been closed.' % self._issue)
116
117 patchsets = issue_json.get('patchsets')
118 if not isinstance(patchsets, list) or len(patchsets) == 0:
119 raise RietveldPatcherError('Cannot parse issue %s.' % self._issue)
120
121 if not issue_json.get('base_url') in _CHROMIUM_REPO_BASEURLS:
122 raise RietveldPatcherError('Issue %s\'s base url is unknown.' %
123 self._issue)
124
125 return str(patchsets[-1])
126
127 def GetPatchedFiles(self, version=None):
128 if version is None:
129 patchset = self.GetVersion()
130 else:
131 patchset = version
132 try:
133 patchset_json = json.loads(self._fetcher.Fetch(
134 'api/%s/%s' % (self._issue, patchset)).content)
135 except Exception as e:
136 raise RietveldPatcherError(
137 'Failed to fetch details for issue %s patchset %s.' % (self._issue,
138 patchset))
139
140 files = patchset_json.get('files')
141 if files is None or not isinstance(files, dict):
142 raise RietveldPatcherError('Failed to parse issue %s patchset %s.' %
143 (self._issue, patchset))
144
145 added = []
146 deleted = []
147 modified = []
148 for key in files:
149 if not key.startswith(self._base_path + '/'):
150 continue
151
152 f = key.split(self._base_path + '/', 1)[1]
153 if any(f.startswith(path) for path in _DOCS_PATHS):
154 status = (files[key].get('status') or 'M')
155 # status can be 'A ' or 'A + '
156 if 'A' in status:
157 added.append(f)
158 elif 'D' in status:
159 deleted.append(f)
160 elif 'M' in status:
161 modified.append(f)
162 else:
163 raise RietveldPatcherError('Unknown file status for file %s: "%s."' %
164 (key, status))
165
166 return (added, deleted, modified)
167
168 def Apply(self, paths, file_system, binary, version=None):
169 if version is None:
170 version = self.GetVersion()
171 return Future(delegate=_AsyncFetchFuture(self._base_path,
172 self._issue,
173 version,
174 paths,
175 binary,
176 self._fetcher))
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/server2/patcher.py ('k') | chrome/common/extensions/docs/server2/rietveld_patcher_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698