OLD | NEW |
1 # coding=utf8 | 1 # coding=utf8 |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 """Utility functions to handle patches.""" | 5 """Utility functions to handle patches.""" |
6 | 6 |
7 import posixpath | 7 import posixpath |
8 import os | 8 import os |
9 import re | 9 import re |
10 | 10 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 | 208 |
209 # Cheap check to make sure the file name is at least mentioned in the | 209 # Cheap check to make sure the file name is at least mentioned in the |
210 # 'diff' header. That the only remaining invariant. | 210 # 'diff' header. That the only remaining invariant. |
211 if not self.filename in self.diff_header: | 211 if not self.filename in self.diff_header: |
212 self._fail('Diff seems corrupted.') | 212 self._fail('Diff seems corrupted.') |
213 | 213 |
214 def _verify_git_header_process_line(self, lines, line, last_line, old, new): | 214 def _verify_git_header_process_line(self, lines, line, last_line, old, new): |
215 """Processes a single line of the header. | 215 """Processes a single line of the header. |
216 | 216 |
217 Returns True if it should continue looping. | 217 Returns True if it should continue looping. |
| 218 |
| 219 Format is described to |
| 220 http://www.kernel.org/pub/software/scm/git/docs/git-diff.html |
218 """ | 221 """ |
219 # Handle these: | |
220 # rename from <> | |
221 # copy from <> | |
222 match = re.match(r'^(rename|copy) from (.+)$', line) | 222 match = re.match(r'^(rename|copy) from (.+)$', line) |
223 if match: | 223 if match: |
224 if old != match.group(2): | 224 if old != match.group(2): |
225 self._fail('Unexpected git diff input name for line %s.' % line) | 225 self._fail('Unexpected git diff input name for line %s.' % line) |
226 if not lines or not lines[0].startswith('%s to ' % match.group(1)): | 226 if not lines or not lines[0].startswith('%s to ' % match.group(1)): |
227 self._fail( | 227 self._fail( |
228 'Confused %s from/to git diff for line %s.' % | 228 'Confused %s from/to git diff for line %s.' % |
229 (match.group(1), line)) | 229 (match.group(1), line)) |
230 return | 230 return |
231 | 231 |
232 # Handle these: | |
233 # rename to <> | |
234 # copy to <> | |
235 match = re.match(r'^(rename|copy) to (.+)$', line) | 232 match = re.match(r'^(rename|copy) to (.+)$', line) |
236 if match: | 233 if match: |
237 if new != match.group(2): | 234 if new != match.group(2): |
238 self._fail('Unexpected git diff output name for line %s.' % line) | 235 self._fail('Unexpected git diff output name for line %s.' % line) |
239 if not last_line.startswith('%s from ' % match.group(1)): | 236 if not last_line.startswith('%s from ' % match.group(1)): |
240 self._fail( | 237 self._fail( |
241 'Confused %s from/to git diff for line %s.' % | 238 'Confused %s from/to git diff for line %s.' % |
242 (match.group(1), line)) | 239 (match.group(1), line)) |
243 return | 240 return |
244 | 241 |
245 # Handle "new file mode \d{6}" | 242 match = re.match(r'^new(| file) mode (\d{6})$', line) |
246 match = re.match(r'^new file mode (\d{6})$', line) | |
247 if match: | 243 if match: |
248 mode = match.group(1) | 244 mode = match.group(2) |
249 # Only look at owner ACL for executable. | 245 # Only look at owner ACL for executable. |
| 246 # TODO(maruel): Add support to remove a property. |
250 if bool(int(mode[4]) & 1): | 247 if bool(int(mode[4]) & 1): |
251 self.svn_properties.append(('svn:executable', '*')) | 248 self.svn_properties.append(('svn:executable', '*')) |
252 | 249 |
253 # Handle "--- " | |
254 match = re.match(r'^--- (.*)$', line) | 250 match = re.match(r'^--- (.*)$', line) |
255 if match: | 251 if match: |
256 if last_line[:3] in ('---', '+++'): | 252 if last_line[:3] in ('---', '+++'): |
257 self._fail('--- and +++ are reversed') | 253 self._fail('--- and +++ are reversed') |
258 self.is_new = match.group(1) == '/dev/null' | 254 self.is_new = match.group(1) == '/dev/null' |
259 # TODO(maruel): Use self.source_file. | 255 # TODO(maruel): Use self.source_file. |
260 if old != self.mangle(match.group(1)) and match.group(1) != '/dev/null': | 256 if old != self.mangle(match.group(1)) and match.group(1) != '/dev/null': |
261 self._fail('Unexpected git diff: %s != %s.' % (old, match.group(1))) | 257 self._fail('Unexpected git diff: %s != %s.' % (old, match.group(1))) |
262 if not lines or not lines[0].startswith('+++'): | 258 if not lines or not lines[0].startswith('+++'): |
263 self._fail('Missing git diff output name.') | 259 self._fail('Missing git diff output name.') |
264 return | 260 return |
265 | 261 |
266 # Handle "+++ " | |
267 match = re.match(r'^\+\+\+ (.*)$', line) | 262 match = re.match(r'^\+\+\+ (.*)$', line) |
268 if match: | 263 if match: |
269 if not last_line.startswith('---'): | 264 if not last_line.startswith('---'): |
270 self._fail('Unexpected git diff: --- not following +++.') | 265 self._fail('Unexpected git diff: --- not following +++.') |
271 # TODO(maruel): new == self.filename. | 266 # TODO(maruel): new == self.filename. |
272 if new != self.mangle(match.group(1)) and '/dev/null' != match.group(1): | 267 if new != self.mangle(match.group(1)) and '/dev/null' != match.group(1): |
273 # TODO(maruel): Can +++ be /dev/null? If so, assert self.is_delete == | 268 # TODO(maruel): Can +++ be /dev/null? If so, assert self.is_delete == |
274 # True. | 269 # True. |
275 self._fail('Unexpected git diff: %s != %s.' % (new, match.group(1))) | 270 self._fail('Unexpected git diff: %s != %s.' % (new, match.group(1))) |
276 if lines: | 271 if lines: |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 for patch in self.patches: | 342 for patch in self.patches: |
348 patch.set_relpath(relpath) | 343 patch.set_relpath(relpath) |
349 | 344 |
350 def __iter__(self): | 345 def __iter__(self): |
351 for patch in self.patches: | 346 for patch in self.patches: |
352 yield patch | 347 yield patch |
353 | 348 |
354 @property | 349 @property |
355 def filenames(self): | 350 def filenames(self): |
356 return [p.filename for p in self.patches] | 351 return [p.filename for p in self.patches] |
OLD | NEW |