cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / rietveld_patcher.py
blobaa668f3857528e03b51a5e2901fd4350b14c0272
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.
5 import json
6 import tarfile
7 from StringIO import StringIO
9 from file_system import FileNotFoundError
10 from future import Future
11 from patcher import Patcher
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',
23 class RietveldPatcherError(Exception):
24 def __init__(self, message):
25 self.message = message
28 class RietveldPatcher(Patcher):
29 ''' Class to fetch resources from a patchset in Rietveld.
30 '''
31 def __init__(self,
32 issue,
33 fetcher):
34 self._issue = issue
35 self._fetcher = fetcher
36 self._cache = None
38 # In RietveldPatcher, the version is the latest patchset number.
39 def GetVersion(self):
40 try:
41 issue_json = json.loads(self._fetcher.Fetch(
42 'api/%s' % self._issue).content)
43 except Exception as e:
44 raise RietveldPatcherError(
45 'Failed to fetch information for issue %s.' % self._issue)
47 if issue_json.get('closed'):
48 raise RietveldPatcherError('Issue %s has been closed.' % self._issue)
50 patchsets = issue_json.get('patchsets')
51 if not isinstance(patchsets, list) or len(patchsets) == 0:
52 raise RietveldPatcherError('Cannot parse issue %s.' % self._issue)
54 if not issue_json.get('base_url') in _CHROMIUM_REPO_BASEURLS:
55 raise RietveldPatcherError('Issue %s\'s base url (%s) is unknown.' %
56 (self._issue, issue_json.get('base_url')))
58 return str(patchsets[-1])
60 def GetPatchedFiles(self, version=None):
61 if version is None:
62 patchset = self.GetVersion()
63 else:
64 patchset = version
65 try:
66 patchset_json = json.loads(self._fetcher.Fetch(
67 'api/%s/%s' % (self._issue, patchset)).content)
68 except Exception as e:
69 raise RietveldPatcherError(
70 'Failed to fetch details for issue %s patchset %s.' % (self._issue,
71 patchset))
73 files = patchset_json.get('files')
74 if files is None or not isinstance(files, dict):
75 raise RietveldPatcherError('Failed to parse issue %s patchset %s.' %
76 (self._issue, patchset))
78 added = []
79 deleted = []
80 modified = []
81 for f in files:
82 status = (files[f].get('status') or 'M')
83 # status can be 'A ' or 'A + '
84 if 'A' in status:
85 added.append(f)
86 elif 'D' in status:
87 deleted.append(f)
88 elif 'M' in status:
89 modified.append(f)
90 else:
91 raise RietveldPatcherError('Unknown file status for file %s: "%s."' %
92 (key, status))
94 return (added, deleted, modified)
96 def Apply(self, paths, file_system, version=None):
97 if version is None:
98 version = self.GetVersion()
100 def apply_(tarball_result):
101 if tarball_result.status_code != 200:
102 raise RietveldPatcherError(
103 'Failed to download tarball for issue %s patchset %s. Status: %s' %
104 (self._issue, version, tarball_result.status_code))
106 try:
107 tar = tarfile.open(fileobj=StringIO(tarball_result.content))
108 except tarfile.TarError as e:
109 raise RietveldPatcherError(
110 'Error loading tarball for issue %s patchset %s.' % (self._issue,
111 version))
113 value = {}
114 for path in paths:
115 tar_path = 'b/%s' % path
117 patched_file = None
118 try:
119 patched_file = tar.extractfile(tar_path)
120 data = patched_file.read()
121 except tarfile.TarError as e:
122 # Show appropriate error message in the unlikely case that the tarball
123 # is corrupted.
124 raise RietveldPatcherError(
125 'Error extracting tarball for issue %s patchset %s file %s.' %
126 (self._issue, version, tar_path))
127 except KeyError as e:
128 raise FileNotFoundError(
129 'File %s not found in the tarball for issue %s patchset %s' %
130 (tar_path, self._issue, version))
131 finally:
132 if patched_file:
133 patched_file.close()
135 value[path] = data
137 return value
138 return self._fetcher.FetchAsync('tarball/%s/%s' % (self._issue,
139 version)).Then(apply_)
141 def GetIdentity(self):
142 return self._issue