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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 """Returns a PatchSet object containing the details to apply this patch.""" | 118 """Returns a PatchSet object containing the details to apply this patch.""" |
119 props = self.get_patchset_properties(issue, patchset) or {} | 119 props = self.get_patchset_properties(issue, patchset) or {} |
120 out = [] | 120 out = [] |
121 for filename, state in props.get('files', {}).iteritems(): | 121 for filename, state in props.get('files', {}).iteritems(): |
122 logging.debug('%s' % filename) | 122 logging.debug('%s' % filename) |
123 status = state.get('status') | 123 status = state.get('status') |
124 if status is None: | 124 if status is None: |
125 raise patch.UnsupportedPatchFormat( | 125 raise patch.UnsupportedPatchFormat( |
126 filename, 'File\'s status is None, patchset upload is incomplete.') | 126 filename, 'File\'s status is None, patchset upload is incomplete.') |
127 | 127 |
128 # TODO(maruel): That's bad, it confuses property change. | 128 if status[0] == 'D': |
129 status = status.strip() | 129 if status[0] != status.strip(): |
Dirk Pranke
2011/09/06 20:21:48
Nit: wonder if this might be clearer with 'if stat
M-A Ruel
2011/09/06 20:23:59
No because status is a svn status line, which cont
Dirk Pranke
2011/09/06 22:35:36
Ah, right. LGTM, then.
| |
130 | 130 raise patch.UnsupportedPatchFormat( |
131 if status == 'D': | 131 filename, 'Deleted file shouldn\'t have property change.') |
132 # Ignore the diff. | 132 # Ignore the diff. |
133 out.append(patch.FilePatchDelete(filename, state['is_binary'])) | 133 out.append(patch.FilePatchDelete(filename, state['is_binary'])) |
134 elif status in ('A', 'M'): | 134 elif status[0] in ('A', 'M'): |
135 svn_props = self.parse_svn_properties( | 135 svn_props = self.parse_svn_properties( |
136 state.get('property_changes', ''), filename) | 136 state.get('property_changes', ''), filename) |
137 if state['is_binary']: | 137 if state['is_binary']: |
138 out.append(patch.FilePatchBinary( | 138 out.append(patch.FilePatchBinary( |
139 filename, | 139 filename, |
140 self.get_file_content(issue, patchset, state['id']), | 140 self.get_file_content(issue, patchset, state['id']), |
141 svn_props, | 141 svn_props, |
142 is_new=(status[0] == 'A'))) | 142 is_new=(status[0] == 'A'))) |
143 else: | 143 else: |
144 # Ignores num_chunks since it may only contain an header. | 144 # Ignores num_chunks since it may only contain an header. |
145 diff = None | |
145 try: | 146 try: |
146 diff = self.get_file_diff(issue, patchset, state['id']) | 147 diff = self.get_file_diff(issue, patchset, state['id']) |
147 except urllib2.HTTPError, e: | 148 except urllib2.HTTPError, e: |
148 if e.code == 404: | 149 if e.code == 404: |
149 raise patch.UnsupportedPatchFormat( | 150 raise patch.UnsupportedPatchFormat( |
150 filename, 'File doesn\'t have a diff.') | 151 filename, 'File doesn\'t have a diff.') |
152 raise | |
153 # It may happen on property-only change or svn copy without diff. | |
154 if not diff: | |
155 # Support this use case if it ever happen. | |
156 raise patch.UnsupportedPatchFormat( | |
157 filename, 'Empty diff is not supported yet.\n') | |
151 out.append(patch.FilePatchDiff(filename, diff, svn_props)) | 158 out.append(patch.FilePatchDiff(filename, diff, svn_props)) |
152 if status[0] == 'A': | 159 if status[0] == 'A': |
153 # It won't be set for empty file. | 160 # It won't be set for empty file. |
154 out[-1].is_new = True | 161 out[-1].is_new = True |
155 else: | 162 else: |
156 # TODO(maruel): Add support for MM, A+, etc. Rietveld removes the svn | 163 raise patch.UnsupportedPatchFormat( |
157 # properties from the diff. | 164 filename, 'Change with status \'%s\' is not supported.' % status) |
158 raise patch.UnsupportedPatchFormat(filename, status) | 165 |
159 return patch.PatchSet(out) | 166 return patch.PatchSet(out) |
160 | 167 |
161 @staticmethod | 168 @staticmethod |
162 def parse_svn_properties(rietveld_svn_props, filename): | 169 def parse_svn_properties(rietveld_svn_props, filename): |
163 """Returns a list of tuple [('property', 'newvalue')]. | 170 """Returns a list of tuple [('property', 'newvalue')]. |
164 | 171 |
165 rietveld_svn_props is the exact format from 'svn diff'. | 172 rietveld_svn_props is the exact format from 'svn diff'. |
166 """ | 173 """ |
167 rietveld_svn_props = rietveld_svn_props.splitlines() | 174 rietveld_svn_props = rietveld_svn_props.splitlines() |
168 svn_props = [] | 175 svn_props = [] |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 if retry >= (maxtries - 1): | 266 if retry >= (maxtries - 1): |
260 raise | 267 raise |
261 if not 'Name or service not known' in e.reason: | 268 if not 'Name or service not known' in e.reason: |
262 # Usually internal GAE flakiness. | 269 # Usually internal GAE flakiness. |
263 raise | 270 raise |
264 # If reaching this line, loop again. Uses a small backoff. | 271 # If reaching this line, loop again. Uses a small backoff. |
265 time.sleep(1+maxtries*2) | 272 time.sleep(1+maxtries*2) |
266 | 273 |
267 # DEPRECATED. | 274 # DEPRECATED. |
268 Send = get | 275 Send = get |
OLD | NEW |