OLD | NEW |
1 # Copyright (c) 2009, 2010, 2011 Google Inc. All rights reserved. | 1 # Copyright (c) 2009, 2010, 2011 Google Inc. All rights reserved. |
2 # Copyright (c) 2009 Apple Inc. All rights reserved. | 2 # Copyright (c) 2009 Apple Inc. All rights reserved. |
3 # | 3 # |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 return True | 179 return True |
180 | 180 |
181 def display_name(self): | 181 def display_name(self): |
182 return "git" | 182 return "git" |
183 | 183 |
184 def most_recent_log_matching(self, grep_str, path): | 184 def most_recent_log_matching(self, grep_str, path): |
185 # We use '--grep=' + foo rather than '--grep', foo because | 185 # We use '--grep=' + foo rather than '--grep', foo because |
186 # git 1.7.0.4 (and earlier) didn't support the separate arg. | 186 # git 1.7.0.4 (and earlier) didn't support the separate arg. |
187 return self._run_git(['log', '-1', '--grep=' + grep_str, '--date=iso', s
elf.find_checkout_root(path)]) | 187 return self._run_git(['log', '-1', '--grep=' + grep_str, '--date=iso', s
elf.find_checkout_root(path)]) |
188 | 188 |
189 def svn_revision(self, path): | 189 def _commit_position_from_git_log(self, git_log): |
190 git_log = self.most_recent_log_matching('git-svn-id:', path) | 190 match = re.search("^\s*Cr-Commit-Position:.*@\{#(?P<commit_position>\d+)
\}", git_log, re.MULTILINE) |
191 match = re.search("^\s*git-svn-id:.*@(?P<svn_revision>\d+)\ ", git_log,
re.MULTILINE) | |
192 if not match: | 191 if not match: |
193 return "" | 192 return "" |
194 return str(match.group('svn_revision')) | 193 return str(match.group('commit_position')) |
| 194 |
| 195 def commit_position(self, path): |
| 196 git_log = self.most_recent_log_matching('Cr-Commit-Position:', path) |
| 197 return self._commit_position_from_git_log(git_log) |
195 | 198 |
196 def timestamp_of_revision(self, path, revision): | 199 def timestamp_of_revision(self, path, revision): |
197 git_log = self.most_recent_log_matching('git-svn-id:.*@%s' % revision, p
ath) | 200 git_log = self.most_recent_log_matching('Cr-Commit-Position:.*@\{%s\}' %
revision, path) |
198 match = re.search("^Date:\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{
2}) ([+-])(\d{2})(\d{2})$", git_log, re.MULTILINE) | 201 match = re.search("^Date:\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{
2}) ([+-])(\d{2})(\d{2})$", git_log, re.MULTILINE) |
199 if not match: | 202 if not match: |
200 return "" | 203 return "" |
201 | 204 |
202 # Manually modify the timezone since Git doesn't have an option to show
it in UTC. | 205 # Manually modify the timezone since Git doesn't have an option to show
it in UTC. |
203 # Git also truncates milliseconds but we're going to ignore that for now
. | 206 # Git also truncates milliseconds but we're going to ignore that for now
. |
204 time_with_timezone = datetime.datetime(int(match.group(1)), int(match.gr
oup(2)), int(match.group(3)), | 207 time_with_timezone = datetime.datetime(int(match.group(1)), int(match.gr
oup(2)), int(match.group(3)), |
205 int(match.group(4)), int(match.gr
oup(5)), int(match.group(6)), 0) | 208 int(match.group(4)), int(match.gr
oup(5)), int(match.group(6)), 0) |
206 | 209 |
207 sign = 1 if match.group(7) == '+' else -1 | 210 sign = 1 if match.group(7) == '+' else -1 |
208 time_without_timezone = time_with_timezone - datetime.timedelta(hours=si
gn * int(match.group(8)), minutes=int(match.group(9))) | 211 time_without_timezone = time_with_timezone - datetime.timedelta(hours=si
gn * int(match.group(8)), minutes=int(match.group(9))) |
209 return time_without_timezone.strftime('%Y-%m-%dT%H:%M:%SZ') | 212 return time_without_timezone.strftime('%Y-%m-%dT%H:%M:%SZ') |
210 | 213 |
211 def _prepend_svn_revision(self, diff): | |
212 revision = self._head_svn_revision() | |
213 if not revision: | |
214 return diff | |
215 | |
216 return "Subversion Revision: " + revision + '\n' + diff | |
217 | |
218 def create_patch(self, git_commit=None, changed_files=None): | 214 def create_patch(self, git_commit=None, changed_files=None): |
219 """Returns a byte array (str()) representing the patch file. | 215 """Returns a byte array (str()) representing the patch file. |
220 Patch files are effectively binary since they may contain | 216 Patch files are effectively binary since they may contain |
221 files of multiple different encodings.""" | 217 files of multiple different encodings.""" |
222 | 218 |
223 # Put code changes at the top of the patch and layout tests | 219 # Put code changes at the top of the patch and layout tests |
224 # at the bottom, this makes for easier reviewing. | 220 # at the bottom, this makes for easier reviewing. |
225 config_path = self._filesystem.dirname(self._filesystem.path_to_module('
webkitpy.common.config')) | 221 config_path = self._filesystem.dirname(self._filesystem.path_to_module('
webkitpy.common.config')) |
226 order_file = self._filesystem.join(config_path, 'orderfile') | 222 order_file = self._filesystem.join(config_path, 'orderfile') |
227 order = "" | 223 order = "" |
228 if self._filesystem.exists(order_file): | 224 if self._filesystem.exists(order_file): |
229 order = "-O%s" % order_file | 225 order = "-O%s" % order_file |
230 | 226 |
231 command = [self.executable_name, 'diff', '--binary', '--no-color', "--no
-ext-diff", "--full-index", "--no-renames", order, self._merge_base(git_commit),
"--"] | 227 command = [self.executable_name, 'diff', '--binary', '--no-color', "--no
-ext-diff", "--full-index", "--no-renames", order, self._merge_base(git_commit),
"--"] |
232 if changed_files: | 228 if changed_files: |
233 command += changed_files | 229 command += changed_files |
234 return self._prepend_svn_revision(self._run(command, decode_output=False
, cwd=self.checkout_root)) | 230 return self._run(command, decode_output=False, cwd=self.checkout_root) |
235 | 231 |
236 @memoized | 232 @memoized |
237 def svn_revision_from_git_commit(self, git_commit): | 233 def commit_position_from_git_commit(self, git_commit): |
238 # git svn find-rev always exits 0, even when the revision or commit is n
ot found. | 234 git_log = self.git_commit_detail(git_commit) |
239 try: | 235 return self._commit_position_from_git_log(git_log) |
240 return int(self._run_git(['svn', 'find-rev', git_commit]).rstrip()) | |
241 except ValueError, e: | |
242 return None | |
243 | 236 |
244 def checkout_branch(self, name): | 237 def checkout_branch(self, name): |
245 self._run_git(['checkout', '-q', name]) | 238 self._run_git(['checkout', '-q', name]) |
246 | 239 |
247 def create_clean_branch(self, name): | 240 def create_clean_branch(self, name): |
248 self._run_git(['checkout', '-q', '-b', name, self._remote_branch_ref()]) | 241 self._run_git(['checkout', '-q', '-b', name, self._remote_branch_ref()]) |
249 | 242 |
250 def blame(self, path): | 243 def blame(self, path): |
251 return self._run_git(['blame', path]) | 244 return self._run_git(['blame', path]) |
252 | 245 |
253 # Git-specific methods: | 246 # Git-specific methods: |
254 def _branch_ref_exists(self, branch_ref): | 247 def _branch_ref_exists(self, branch_ref): |
255 return self._run_git(['show-ref', '--quiet', '--verify', branch_ref], re
turn_exit_code=True) == 0 | 248 return self._run_git(['show-ref', '--quiet', '--verify', branch_ref], re
turn_exit_code=True) == 0 |
256 | 249 |
257 def delete_branch(self, branch_name): | 250 def delete_branch(self, branch_name): |
258 if self._branch_ref_exists('refs/heads/' + branch_name): | 251 if self._branch_ref_exists('refs/heads/' + branch_name): |
259 self._run_git(['branch', '-D', branch_name]) | 252 self._run_git(['branch', '-D', branch_name]) |
260 | 253 |
261 def _remote_merge_base(self): | 254 def _remote_merge_base(self): |
262 return self._run_git(['merge-base', self._remote_branch_ref(), 'HEAD']).
strip() | 255 return self._run_git(['merge-base', self._remote_branch_ref(), 'HEAD']).
strip() |
263 | 256 |
264 def _remote_branch_ref(self): | 257 def _remote_branch_ref(self): |
265 # Use references so that we can avoid collisions, e.g. we don't want to
operate on refs/heads/trunk if it exists. | 258 # Use references so that we can avoid collisions, e.g. we don't want to
operate on refs/heads/trunk if it exists. |
266 remote_branch_refs = self.read_git_config('svn-remote.svn.fetch', cwd=se
lf.checkout_root, executive=self._executive) | 259 remote_master_ref = 'refs/remotes/origin/master' |
267 if not remote_branch_refs: | 260 if not self._branch_ref_exists(remote_master_ref): |
268 remote_master_ref = 'refs/remotes/origin/master' | 261 raise ScriptError(message="Can't find a branch to diff against. %s d
oes not exist" % remote_master_ref) |
269 if not self._branch_ref_exists(remote_master_ref): | 262 return remote_master_ref |
270 raise ScriptError(message="Can't find a branch to diff against.
svn-remote.svn.fetch is not in the git config and %s does not exist" % remote_ma
ster_ref) | |
271 return remote_master_ref | |
272 | |
273 # FIXME: What's the right behavior when there are multiple svn-remotes l
isted? | |
274 # For now, just use the first one. | |
275 first_remote_branch_ref = remote_branch_refs.split('\n')[0] | |
276 return first_remote_branch_ref.split(':')[1] | |
277 | 263 |
278 def commit_locally_with_message(self, message, commit_all_working_directory_
changes=True): | 264 def commit_locally_with_message(self, message, commit_all_working_directory_
changes=True): |
279 command = ['commit', '-F', '-'] | 265 command = ['commit', '-F', '-'] |
280 if commit_all_working_directory_changes: | 266 if commit_all_working_directory_changes: |
281 command.insert(1, '--all') | 267 command.insert(1, '--all') |
282 self._run_git(command, input=message) | 268 self._run_git(command, input=message) |
283 | 269 |
284 # These methods are git specific and are meant to provide support for the Gi
t oriented workflow | 270 # These methods are git specific and are meant to provide support for the Gi
t oriented workflow |
285 # that Blink is moving towards, hence there are no equivalent methods in the
SVN class. | 271 # that Blink is moving towards, hence there are no equivalent methods in the
SVN class. |
286 | 272 |
(...skipping 30 matching lines...) Expand all Loading... |
317 if self.current_branch() != self._branch_tracking_remote_master(): | 303 if self.current_branch() != self._branch_tracking_remote_master(): |
318 return False | 304 return False |
319 if len(self._local_commits(self._branch_tracking_remote_master())) > 0: | 305 if len(self._local_commits(self._branch_tracking_remote_master())) > 0: |
320 return False | 306 return False |
321 return True | 307 return True |
322 | 308 |
323 def ensure_cleanly_tracking_remote_master(self): | 309 def ensure_cleanly_tracking_remote_master(self): |
324 self._discard_working_directory_changes() | 310 self._discard_working_directory_changes() |
325 self._run_git(['checkout', '-q', self._branch_tracking_remote_master()]) | 311 self._run_git(['checkout', '-q', self._branch_tracking_remote_master()]) |
326 self._discard_local_commits() | 312 self._discard_local_commits() |
OLD | NEW |