OLD | NEW |
1 # coding=utf8 | 1 # coding=utf8 |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 """Manages a project checkout. | 5 """Manages a project checkout. |
6 | 6 |
7 Includes support for svn, git-svn and git. | 7 Includes support for svn, git-svn and git. |
8 """ | 8 """ |
9 | 9 |
10 import logging | 10 import logging |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 if self.working_branch in branches: | 258 if self.working_branch in branches: |
259 self._call_git(['branch', '-D', self.working_branch]) | 259 self._call_git(['branch', '-D', self.working_branch]) |
260 | 260 |
261 def apply_patch(self, patch_data): | 261 def apply_patch(self, patch_data): |
262 """Applies a patch on 'working_branch'.""" | 262 """Applies a patch on 'working_branch'.""" |
263 try: | 263 try: |
264 self._check_call_git( | 264 self._check_call_git( |
265 ['checkout', '-b', self.working_branch, | 265 ['checkout', '-b', self.working_branch, |
266 '%s/%s' % (self.remote, self.remote_branch)]) | 266 '%s/%s' % (self.remote, self.remote_branch)]) |
267 self._check_call_git(['apply', '--index', '-p0'], stdin=patch_data) | 267 self._check_call_git(['apply', '--index', '-p0'], stdin=patch_data) |
268 self._check_call_git(['commit', '-m', 'Committed patch']) | 268 cmd = ['commit', '-m', 'Committed patch', '--quiet'] |
| 269 self._check_call_git(cmd) |
| 270 commit_user = getattr(self, 'commit_user', None) |
| 271 if commit_user: |
| 272 try: |
| 273 # Try to patch the author with commit_user since it may differ. |
| 274 self._check_call_git(cmd + ['--author=%s' % commit_user]) |
| 275 except subprocess.CalledProcessError, e: |
| 276 if e.returncode != 128: |
| 277 raise |
269 return self._check_capture_git(['diff', 'master', | 278 return self._check_capture_git(['diff', 'master', |
270 '--name-only']).splitlines(False) | 279 '--name-only']).splitlines(False) |
271 except subprocess.CalledProcessError, e: | 280 except subprocess.CalledProcessError, e: |
272 if e.returncode == 1: | 281 if e.returncode == 1: |
273 return False | 282 return False |
274 raise | 283 raise |
275 | 284 |
276 def commit(self, commit_message, user): | 285 def commit(self, commit_message, user): |
277 """Updates the commit message. | 286 """Updates the commit message and user if possible. |
278 | 287 |
279 Subclass needs to dcommit or push.""" | 288 Subclass needs to dcommit or push. |
280 self._check_call_git(['commit', '--amend', '-m', commit_message]) | 289 """ |
| 290 # Do it in two calls to ease exception management. |
| 291 cmd = ['commit', '--amend', '-m', commit_message, '--quiet'] |
| 292 self._check_call_git(cmd) |
| 293 try: |
| 294 # git-svn will allow faking the author only if the user already exists in |
| 295 # the logs. |
| 296 # Provide -m again otherwise git will start a text editor. |
| 297 self._check_call_git(cmd + ['--author=%s' % user]) |
| 298 except subprocess.CalledProcessError, e: |
| 299 if e.returncode != 128: |
| 300 raise |
281 | 301 |
282 def _check_call_git(self, args, **kwargs): | 302 def _check_call_git(self, args, **kwargs): |
283 kwargs.setdefault('cwd', self.project_path) | 303 kwargs.setdefault('cwd', self.project_path) |
284 return subprocess2.check_call(['git'] + args, **kwargs) | 304 return subprocess2.check_call(['git'] + args, **kwargs) |
285 | 305 |
286 def _call_git(self, args, **kwargs): | 306 def _call_git(self, args, **kwargs): |
287 """Like check_call but doesn't throw on failure.""" | 307 """Like check_call but doesn't throw on failure.""" |
288 kwargs.setdefault('cwd', self.project_path) | 308 kwargs.setdefault('cwd', self.project_path) |
289 return subprocess2.call(['git'] + args, **kwargs) | 309 return subprocess2.call(['git'] + args, **kwargs) |
290 | 310 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 return int(self._git_svn_info('revision')) | 362 return int(self._git_svn_info('revision')) |
343 | 363 |
344 def _git_svn_info(self, key): | 364 def _git_svn_info(self, key): |
345 """Calls git svn info. This doesn't support nor need --config-dir.""" | 365 """Calls git svn info. This doesn't support nor need --config-dir.""" |
346 return self._parse_svn_info( | 366 return self._parse_svn_info( |
347 self._check_capture_git(['svn', 'info']), key) | 367 self._check_capture_git(['svn', 'info']), key) |
348 | 368 |
349 def commit(self, commit_message, user): | 369 def commit(self, commit_message, user): |
350 """Commits a patch.""" | 370 """Commits a patch.""" |
351 logging.info('Committing patch for %s' % user) | 371 logging.info('Committing patch for %s' % user) |
352 # Fix the commit message. | 372 # Fix the commit message and author. |
353 super(GitSvnCheckoutBase, self).commit(commit_message, user) | 373 super(GitSvnCheckoutBase, self).commit(commit_message, user) |
354 # Commit with git svn dcommit, then use svn directly to update the | 374 # Commit with git svn dcommit, then use svn directly to update the |
355 # committer on the revision. | 375 # committer on the revision. |
356 self._check_call_git_svn(['dcommit', '--rmdir', '--find-copies-harder']) | 376 self._check_call_git_svn(['dcommit', '--rmdir', '--find-copies-harder']) |
357 revision = int(self._git_svn_info('revision')) | 377 revision = int(self._git_svn_info('revision')) |
358 # Fix the committer. | 378 # Fix the committer. |
359 self._update_committer(revision, user) | 379 self._update_committer(revision, user) |
360 return revision | 380 return revision |
361 | 381 |
362 def _cache_svn_auth(self): | 382 def _cache_svn_auth(self): |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 user, message)) | 481 user, message)) |
462 return 'FAKE' | 482 return 'FAKE' |
463 | 483 |
464 @property | 484 @property |
465 def project_name(self): | 485 def project_name(self): |
466 return self.checkout.project_name | 486 return self.checkout.project_name |
467 | 487 |
468 @property | 488 @property |
469 def project_path(self): | 489 def project_path(self): |
470 return self.checkout.project_path | 490 return self.checkout.project_path |
OLD | NEW |