Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1126)

Side by Side Diff: patch.py

Issue 6055005: Add a function to detect patches that can't be safely applied. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/commit-queue
Patch Set: Rebase against trunk Created 9 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pending_manager.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding=utf8
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 # 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
3 # found in the LICENSE file. 4 # found in the LICENSE file.
4 """Utility functions to handle patches.""" 5 """Utility functions to handle patches."""
5 6
7 import logging
6 import re 8 import re
7 import subprocess2 9 import subprocess2
8 10
9 11
10 def auto_mangle_git_patch(patch): 12 def auto_mangle_git_patch(patch):
11 """Mangles a patch and automatically strip out git decoration.""" 13 """Mangles a patch and automatically strip out git decoration."""
12 # Git patches have a/ at the beginning of source paths. We strip that out 14 # Git patches have a/ at the beginning of source paths. We strip that out
13 # with a regexp rather than the -p flag to patch so we can feed either Git 15 # with a regexp rather than the -p flag to patch so we can feed either Git
14 # or svn-style patches into the same apply command. re.sub() should be used 16 # or svn-style patches into the same apply command. re.sub() should be used
15 # but flags=re.MULTILINE is only in python 2.7. 17 # but flags=re.MULTILINE is only in python 2.7.
16 out = [] 18 out = []
17 for line in patch.splitlines(True): 19 for line in patch.splitlines(True):
18 # TODO: It should just process the header lines. 20 # TODO: It should just process the header lines.
19 out.append(re.sub(r'^--- a/', r'--- ', 21 out.append(re.sub(r'^--- a/', r'--- ',
20 re.sub(r'^\+\+\+ b/', r'+++ ', line))) 22 re.sub(r'^\+\+\+ b/', r'+++ ', line)))
21 return ''.join(out) 23 return ''.join(out)
22 24
23 25
24 def apply_patch(location, patch): 26 def apply_patch(location, patch):
25 """Applies a svn patch, manually applying svn meta data.""" 27 """Applies a svn patch, manually applying svn meta data."""
26 # TODO: Do not shell out patch to enable svn cp/mv/ren and friends 28 # TODO: Do not shell out patch to enable svn cp/mv/ren and friends
27 # TODO: Add binary support 29 # TODO: Add binary support
28 # TODO: Reuse some webkit svn-apply stuff? 30 # TODO: Reuse some webkit svn-apply stuff?
29 cmd = ['patch', '-p0', '--forward', '--force'] 31 cmd = ['patch', '-p0', '--forward', '--force']
30 subprocess2.check_call(cmd, stdin=patch, cwd=location) 32 subprocess2.check_call(cmd, stdin=patch, cwd=location)
31 33
34
35 def verify_patch(patch_data):
36 """Verifies if a patch can be applied.
37
38 Returns a string if the patch can't be applied explaining the issue.
39 """
40 lines = patch_data.splitlines(False)
41 svn_separator = (
42 '___________________________________________________________________')
43
44 index = 0
45
46 def next_line(i):
47 if index+i >= len(lines):
48 return ''
49 return lines[index+i]
50
51 for index, line in enumerate(lines):
52 if line == svn_separator:
53 # Look for the next line.
54 # TODO: If we ever hit non English patches, we need to
55 # use something like re.match(ur'^\w+$', u'Modifié', re.UNICODE)
56 m = re.match(r'^(\w+)\s*\:\s*svn\:([\w\-]+)$', next_line(1))
57 if not m:
58 # The patch confused the script;
59 continue
60 prop = m.group(2)
61 if prop in ('mergeinfo', 'executable', 'ignore'):
62 # In practice, executable should be treated like eol-style, assuming we
63 # lookup auto-props.
64 return 'Can\'t apply svn property svn:%s' % prop
65 elif prop in ('eol-style', 'mime-type'):
66 # Silently ignore it, assume that the auto-props are ok.
67 # TODO: Verify the auto-props would trigger.
68 continue
69 else:
70 # Unknown property
71 logging.error('Unknown property %s' % prop)
72 continue
73 m = re.match(r'^Index\:\s*(.+)$', line)
74 if m:
75 # We need to find --- on the next 3 lines otherwise discard the patch.
76 if next_line(1).startswith('--- '):
77 continue
78 if not next_line(1):
79 return 'Can\'t patch empty file (svn)'
80 if next_line(2).startswith('--- '):
81 continue
82 if not next_line(2):
83 return 'Can\'t patch empty file (svn)'
84 if next_line(3).startswith('--- '):
85 continue
86 if not next_line(3):
87 return 'Can\'t patch empty file (svn)'
88 if next_line(4).startswith('--- '):
89 # See testSupported3() for a real-world example.
90 continue
91 return 'Can\'t patch empty file (svn)'
92 m = re.match(r'diff \-\-git (.*)$', line)
93 if m:
94 if not next_line(1):
95 return 'Can\'t patch empty file (git)'
96 if next_line(1).startswith('old mode '):
97 return 'Unsupported git file mode change'
98 return None
OLDNEW
« no previous file with comments | « no previous file | pending_manager.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698