Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / rietveld_patcher.py
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
10 from future import Future
11 from patcher import Patcher
12
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
23 class RietveldPatcherError(Exception):
24   def __init__(self, message):
25     self.message = message
26
27
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
37
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)
46
47     if issue_json.get('closed'):
48       raise RietveldPatcherError('Issue %s has been closed.' % self._issue)
49
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)
53
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')))
57
58     return str(patchsets[-1])
59
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))
72
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))
77
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))
93
94     return (added, deleted, modified)
95
96   def Apply(self, paths, file_system, version=None):
97     if version is None:
98       version = self.GetVersion()
99
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))
105
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))
112
113       value = {}
114       for path in paths:
115         tar_path = 'b/%s' % path
116
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()
134
135         value[path] = data
136
137       return value
138     return self._fetcher.FetchAsync('tarball/%s/%s' % (self._issue,
139                                                        version)).Then(apply_)
140
141   def GetIdentity(self):
142     return self._issue