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

Side by Side Diff: patch.py

Issue 6792028: Move patch.py and rietveld.py from commit-queue. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: fixed remaining issues Created 9 years, 8 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 | « .gitignore ('k') | pylintrc » ('j') | tests/local_rietveld.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # coding=utf8
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
4 # found in the LICENSE file.
5 """Utility functions to handle patches."""
6
7 import re
8
9
10 class UnsupportedPatchFormat(Exception):
11 def __init__(self, filename, status):
12 super(UnsupportedPatchFormat, self).__init__(filename, status)
13 self.filename = filename
14 self.status = status
15
16 def __str__(self):
17 out = 'Can\'t process patch for file %s.' % self.filename
18 if self.status:
19 out += '\n%s' % self.status
20 return out
21
22
23 class FilePatchBase(object):
24 """Defines a single file being modified."""
25 is_delete = False
26 is_binary = False
27
28 def get(self):
29 raise NotImplementedError('Nothing to grab')
30
31
32 class FilePatchDelete(FilePatchBase):
33 """Deletes a file."""
34 is_delete = True
35
36 def __init__(self, filename, is_binary):
37 super(FilePatchDelete, self).__init__()
38 self.filename = filename
39 self.is_binary = is_binary
40
41 def get(self):
42 raise NotImplementedError('Nothing to grab')
43
44
45 class FilePatchBinary(FilePatchBase):
46 """Content of a new binary file."""
47 is_binary = True
48
49 def __init__(self, filename, data, svn_properties):
50 super(FilePatchBinary, self).__init__()
51 self.filename = filename
52 self.data = data
53 self.svn_properties = svn_properties or []
54
55 def get(self):
56 return self.data
57
58
59 class FilePatchDiff(FilePatchBase):
60 """Patch for a single file."""
61
62 def __init__(self, filename, diff, svn_properties):
63 super(FilePatchDiff, self).__init__()
64 self.filename = filename
65 self.diff = diff
66 self.svn_properties = svn_properties or []
67 self.is_git_diff = self._is_git_diff(diff)
68 if self.is_git_diff:
69 self.patchlevel = 1
70 self._verify_git_patch(filename, diff)
71 assert not svn_properties
72 else:
73 self.patchlevel = 0
74 self._verify_svn_patch(filename, diff)
75
76 def get(self):
77 return self.diff
78
79 @staticmethod
80 def _is_git_diff(diff):
81 """Returns True if the diff for a single files was generated with gt.
82
83 Expects the following format:
84
85 Index: <filename>
86 diff --git a/<filename> b/<filename>
87 <filemode changes>
88 <index>
89 --- <filename>
90 +++ <filename>
91 <hunks>
92
93 Index: is a rietveld specific line.
94 """
95 # Delete: http://codereview.chromium.org/download/issue6368055_22_29.diff
96 # Rename partial change:
97 # http://codereview.chromium.org/download/issue6250123_3013_6010.diff
98 # Rename no change:
99 # http://codereview.chromium.org/download/issue6287022_3001_4010.diff
100 return any(l.startswith('diff --git') for l in diff.splitlines()[:3])
101
102 @staticmethod
103 def _verify_git_patch(filename, diff):
104 lines = diff.splitlines()
105 # First fine the git diff header:
106 while lines:
107 line = lines.pop(0)
108 match = re.match(r'^diff \-\-git a\/(.*?) b\/(.*)$', line)
109 if match:
110 a = match.group(1)
111 b = match.group(2)
112 if a != filename and a != 'dev/null':
113 raise UnsupportedPatchFormat(
114 filename, 'Unexpected git diff input name.')
115 if b != filename and b != 'dev/null':
116 raise UnsupportedPatchFormat(
117 filename, 'Unexpected git diff output name.')
118 if a == 'dev/null' and b == 'dev/null':
119 raise UnsupportedPatchFormat(
120 filename, 'Unexpected /dev/null git diff.')
121 break
122 else:
123 raise UnsupportedPatchFormat(
124 filename, 'Unexpected git diff; couldn\'t find git header.')
125
126 while lines:
127 line = lines.pop(0)
128 match = re.match(r'^--- a/(.*)$', line)
129 if match:
130 if a != match.group(1):
131 raise UnsupportedPatchFormat(
132 filename, 'Unexpected git diff: %s != %s.' % (a, match.group(1)))
133 match = re.match(r'^\+\+\+ b/(.*)$', lines.pop(0))
134 if not match:
135 raise UnsupportedPatchFormat(
136 filename, 'Unexpected git diff: --- not following +++.')
137 if b != match.group(1):
138 raise UnsupportedPatchFormat(
139 filename, 'Unexpected git diff: %s != %s.' % (b, match.group(1)))
140 break
141 # Don't fail if the patch header is not found, the diff could be a
142 # file-mode-change-only diff.
143
144 @staticmethod
145 def _verify_svn_patch(filename, diff):
146 lines = diff.splitlines()
147 while lines:
148 line = lines.pop(0)
149 match = re.match(r'^--- ([^\t]+).*$', line)
150 if match:
151 if match.group(1) not in (filename, '/dev/null'):
152 raise UnsupportedPatchFormat(
153 filename,
154 'Unexpected diff: %s != %s.' % (filename, match.group(1)))
155 # Grab next line.
156 line2 = lines.pop(0)
157 match = re.match(r'^\+\+\+ ([^\t]+).*$', line2)
158 if not match:
159 raise UnsupportedPatchFormat(
160 filename,
161 'Unexpected diff: --- not following +++.:\n%s\n%s' % (
162 line, line2))
163 if match.group(1) not in (filename, '/dev/null'):
164 raise UnsupportedPatchFormat(
165 filename,
166 'Unexpected diff: %s != %s.' % (filename, match.group(1)))
167 break
168 # Don't fail if the patch header is not found, the diff could be a
169 # svn-property-change-only diff.
170
171
172 class PatchSet(object):
173 """A list of FilePatch* objects."""
174
175 def __init__(self, patches):
176 self.patches = patches
177
178 def __iter__(self):
179 for patch in self.patches:
180 yield patch
181
182 @property
183 def filenames(self):
184 return [p.filename for p in self.patches]
OLDNEW
« no previous file with comments | « .gitignore ('k') | pylintrc » ('j') | tests/local_rietveld.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698