| OLD | NEW |
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 """Defines class Rietveld to easily access a rietveld instance. | 4 """Defines class Rietveld to easily access a rietveld instance. |
| 5 | 5 |
| 6 Security implications: | 6 Security implications: |
| 7 | 7 |
| 8 The following hypothesis are made: | 8 The following hypothesis are made: |
| 9 - Rietveld enforces: | 9 - Rietveld enforces: |
| 10 - Nobody else than issue owner can upload a patch set | 10 - Nobody else than issue owner can upload a patch set |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 Returns a useless diff for binary files. | 105 Returns a useless diff for binary files. |
| 106 """ | 106 """ |
| 107 url = '/download/issue%s_%s_%s.diff' % (issue, patchset, item) | 107 url = '/download/issue%s_%s_%s.diff' % (issue, patchset, item) |
| 108 return self.get(url) | 108 return self.get(url) |
| 109 | 109 |
| 110 def get_patch(self, issue, patchset): | 110 def get_patch(self, issue, patchset): |
| 111 """Returns a PatchSet object containing the details to apply this patch.""" | 111 """Returns a PatchSet object containing the details to apply this patch.""" |
| 112 props = self.get_patchset_properties(issue, patchset) or {} | 112 props = self.get_patchset_properties(issue, patchset) or {} |
| 113 out = [] | 113 out = [] |
| 114 for filename, state in props.get('files', {}).iteritems(): | 114 for filename, state in props.get('files', {}).iteritems(): |
| 115 logging.debug('%s' % filename) |
| 115 status = state.get('status') | 116 status = state.get('status') |
| 116 if status is None: | 117 if status is None: |
| 117 raise patch.UnsupportedPatchFormat( | 118 raise patch.UnsupportedPatchFormat( |
| 118 filename, 'File\'s status is None, patchset upload is incomplete') | 119 filename, 'File\'s status is None, patchset upload is incomplete.') |
| 119 | 120 |
| 120 # TODO(maruel): That's bad, it confuses property change. | 121 # TODO(maruel): That's bad, it confuses property change. |
| 121 status = status.strip() | 122 status = status.strip() |
| 122 | 123 |
| 123 if status == 'D': | 124 if status == 'D': |
| 124 # Ignore the diff. | 125 # Ignore the diff. |
| 125 out.append(patch.FilePatchDelete(filename, state['is_binary'])) | 126 out.append(patch.FilePatchDelete(filename, state['is_binary'])) |
| 126 elif status in ('A', 'M'): | 127 elif status in ('A', 'M'): |
| 127 # TODO(maruel): Rietveld support is still weird, add this line once it's | 128 # TODO(maruel): Rietveld support is still weird, add this line once it's |
| 128 # safe to use. | 129 # safe to use. |
| 129 # props = state.get('property_changes', '').splitlines() or [] | 130 # props = state.get('property_changes', '').splitlines() or [] |
| 130 props = [] | 131 props = [] |
| 131 if state['is_binary']: | 132 if state['is_binary']: |
| 132 out.append(patch.FilePatchBinary( | 133 out.append(patch.FilePatchBinary( |
| 133 filename, | 134 filename, |
| 134 self.get_file_content(issue, patchset, state['id']), | 135 self.get_file_content(issue, patchset, state['id']), |
| 135 props)) | 136 props)) |
| 136 else: | 137 else: |
| 137 if state['num_chunks']: | 138 if state['num_chunks']: |
| 138 diff = self.get_file_diff(issue, patchset, state['id']) | 139 diff = self.get_file_diff(issue, patchset, state['id']) |
| 139 else: | 140 else: |
| 140 diff = None | 141 raise patch.UnsupportedPatchFormat( |
| 142 filename, 'File doesn\'t have a diff.') |
| 141 out.append(patch.FilePatchDiff(filename, diff, props)) | 143 out.append(patch.FilePatchDiff(filename, diff, props)) |
| 142 else: | 144 else: |
| 143 # Line too long (N/80) | 145 # Line too long (N/80) |
| 144 # pylint: disable=C0301 | 146 # pylint: disable=C0301 |
| 145 # TODO: Add support for MM, A+, etc. Rietveld removes the svn properties | 147 # TODO: Add support for MM, A+, etc. Rietveld removes the svn properties |
| 146 # from the diff. | 148 # from the diff. |
| 147 # Example of mergeinfo across branches: | 149 # Example of mergeinfo across branches: |
| 148 # http://codereview.chromium.org/202046/diff/1/third_party/libxml/xmlcat
alog_dummy.cc | 150 # http://codereview.chromium.org/202046/diff/1/third_party/libxml/xmlcat
alog_dummy.cc |
| 149 # svn:eol-style property that is lost in the diff | 151 # svn:eol-style property that is lost in the diff |
| 150 # http://codereview.chromium.org/202046/diff/1/third_party/libxml/xmllin
t_dummy.cc | 152 # http://codereview.chromium.org/202046/diff/1/third_party/libxml/xmllin
t_dummy.cc |
| (...skipping 30 matching lines...) Expand all Loading... |
| 181 | 183 |
| 182 def post(self, request_path, data, **kwargs): | 184 def post(self, request_path, data, **kwargs): |
| 183 ctype, body = upload.EncodeMultipartFormData(data, []) | 185 ctype, body = upload.EncodeMultipartFormData(data, []) |
| 184 return self._send(request_path, payload=body, content_type=ctype, **kwargs) | 186 return self._send(request_path, payload=body, content_type=ctype, **kwargs) |
| 185 | 187 |
| 186 def _send(self, request_path, **kwargs): | 188 def _send(self, request_path, **kwargs): |
| 187 """Sends a POST/GET to Rietveld. Returns the response body.""" | 189 """Sends a POST/GET to Rietveld. Returns the response body.""" |
| 188 maxtries = 5 | 190 maxtries = 5 |
| 189 for retry in xrange(maxtries): | 191 for retry in xrange(maxtries): |
| 190 try: | 192 try: |
| 193 logging.debug('%s' % request_path) |
| 191 result = self.rpc_server.Send(request_path, **kwargs) | 194 result = self.rpc_server.Send(request_path, **kwargs) |
| 192 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. How | 195 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. How |
| 193 # nice. | 196 # nice. |
| 194 return result | 197 return result |
| 195 except urllib2.HTTPError, e: | 198 except urllib2.HTTPError, e: |
| 196 if retry >= (maxtries - 1): | 199 if retry >= (maxtries - 1): |
| 197 raise | 200 raise |
| 198 if e.code not in (500, 502, 503): | 201 if e.code not in (500, 502, 503): |
| 199 raise | 202 raise |
| 200 except urllib2.URLError, e: | 203 except urllib2.URLError, e: |
| 201 if retry >= (maxtries - 1): | 204 if retry >= (maxtries - 1): |
| 202 raise | 205 raise |
| 203 if not 'Name or service not known' in e.reason: | 206 if not 'Name or service not known' in e.reason: |
| 204 # Usually internal GAE flakiness. | 207 # Usually internal GAE flakiness. |
| 205 raise | 208 raise |
| 206 # If reaching this line, loop again. Uses a small backoff. | 209 # If reaching this line, loop again. Uses a small backoff. |
| 207 time.sleep(1+maxtries*2) | 210 time.sleep(1+maxtries*2) |
| 208 | 211 |
| 209 # DEPRECATED. | 212 # DEPRECATED. |
| 210 Send = get | 213 Send = get |
| OLD | NEW |