OLD | NEW |
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Gclient-specific SCM-specific operations.""" | 5 """Gclient-specific SCM-specific operations.""" |
6 | 6 |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import posixpath | 9 import posixpath |
10 import re | 10 import re |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 121 |
122 @staticmethod | 122 @staticmethod |
123 def cleanup(options, args, file_list): | 123 def cleanup(options, args, file_list): |
124 """'Cleanup' the repo. | 124 """'Cleanup' the repo. |
125 | 125 |
126 There's no real git equivalent for the svn cleanup command, do a no-op. | 126 There's no real git equivalent for the svn cleanup command, do a no-op. |
127 """ | 127 """ |
128 | 128 |
129 def diff(self, options, args, file_list): | 129 def diff(self, options, args, file_list): |
130 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 130 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
131 self._Run(['diff', merge_base]) | 131 self._Run(['diff', merge_base], options) |
132 | 132 |
133 def export(self, options, args, file_list): | 133 def export(self, options, args, file_list): |
134 """Export a clean directory tree into the given path. | 134 """Export a clean directory tree into the given path. |
135 | 135 |
136 Exports into the specified directory, creating the path if it does | 136 Exports into the specified directory, creating the path if it does |
137 already exist. | 137 already exist. |
138 """ | 138 """ |
139 assert len(args) == 1 | 139 assert len(args) == 1 |
140 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 140 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
141 if not os.path.exists(export_path): | 141 if not os.path.exists(export_path): |
142 os.makedirs(export_path) | 142 os.makedirs(export_path) |
143 self._Run(['checkout-index', '-a', '--prefix=%s/' % export_path]) | 143 self._Run(['checkout-index', '-a', '--prefix=%s/' % export_path], |
| 144 options) |
144 | 145 |
145 def pack(self, options, args, file_list): | 146 def pack(self, options, args, file_list): |
146 """Generates a patch file which can be applied to the root of the | 147 """Generates a patch file which can be applied to the root of the |
147 repository. | 148 repository. |
148 | 149 |
149 The patch file is generated from a diff of the merge base of HEAD and | 150 The patch file is generated from a diff of the merge base of HEAD and |
150 its upstream branch. | 151 its upstream branch. |
151 """ | 152 """ |
152 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 153 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
153 gclient_utils.CheckCallAndFilter( | 154 gclient_utils.CheckCallAndFilter( |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 continue | 276 continue |
276 raise | 277 raise |
277 | 278 |
278 if verbose: | 279 if verbose: |
279 options.stdout.write(remote_output.strip() + '\n') | 280 options.stdout.write(remote_output.strip() + '\n') |
280 # git remote update prints to stderr when used with --verbose | 281 # git remote update prints to stderr when used with --verbose |
281 options.stdout.write(remote_err.strip() + '\n') | 282 options.stdout.write(remote_err.strip() + '\n') |
282 | 283 |
283 # This is a big hammer, debatable if it should even be here... | 284 # This is a big hammer, debatable if it should even be here... |
284 if options.force or options.reset: | 285 if options.force or options.reset: |
285 self._Run(['reset', '--hard', 'HEAD']) | 286 self._Run(['reset', '--hard', 'HEAD'], options) |
286 | 287 |
287 if current_type == 'detached': | 288 if current_type == 'detached': |
288 # case 0 | 289 # case 0 |
289 self._CheckClean(rev_str) | 290 self._CheckClean(rev_str) |
290 self._CheckDetachedHead(rev_str, options) | 291 self._CheckDetachedHead(rev_str, options) |
291 self._Capture(['checkout', '--quiet', '%s^0' % revision]) | 292 self._Capture(['checkout', '--quiet', '%s^0' % revision]) |
292 if not printed_path: | 293 if not printed_path: |
293 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str)) | 294 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str)) |
294 elif current_type == 'hash': | 295 elif current_type == 'hash': |
295 # case 1 | 296 # case 1 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 return self.update(options, [], file_list) | 420 return self.update(options, [], file_list) |
420 | 421 |
421 default_rev = "refs/heads/master" | 422 default_rev = "refs/heads/master" |
422 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) | 423 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) |
423 if not deps_revision: | 424 if not deps_revision: |
424 deps_revision = default_rev | 425 deps_revision = default_rev |
425 if deps_revision.startswith('refs/heads/'): | 426 if deps_revision.startswith('refs/heads/'): |
426 deps_revision = deps_revision.replace('refs/heads/', 'origin/') | 427 deps_revision = deps_revision.replace('refs/heads/', 'origin/') |
427 | 428 |
428 files = self._Capture(['diff', deps_revision, '--name-only']).split() | 429 files = self._Capture(['diff', deps_revision, '--name-only']).split() |
429 self._Run(['reset', '--hard', deps_revision]) | 430 self._Run(['reset', '--hard', deps_revision], options) |
430 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 431 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
431 | 432 |
432 def revinfo(self, options, args, file_list): | 433 def revinfo(self, options, args, file_list): |
433 """Returns revision""" | 434 """Returns revision""" |
434 return self._Capture(['rev-parse', 'HEAD']) | 435 return self._Capture(['rev-parse', 'HEAD']) |
435 | 436 |
436 def runhooks(self, options, args, file_list): | 437 def runhooks(self, options, args, file_list): |
437 self.status(options, args, file_list) | 438 self.status(options, args, file_list) |
438 | 439 |
439 def status(self, options, args, file_list): | 440 def status(self, options, args, file_list): |
440 """Display status information.""" | 441 """Display status information.""" |
441 if not os.path.isdir(self.checkout_path): | 442 if not os.path.isdir(self.checkout_path): |
442 options.stdout.write( | 443 options.stdout.write( |
443 ('\n________ couldn\'t run status in %s:\nThe directory ' | 444 ('\n________ couldn\'t run status in %s:\nThe directory ' |
444 'does not exist.\n') % self.checkout_path) | 445 'does not exist.\n') % self.checkout_path) |
445 else: | 446 else: |
446 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 447 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
447 self._Run(['diff', '--name-status', merge_base]) | 448 self._Run(['diff', '--name-status', merge_base], options) |
448 files = self._Capture(['diff', '--name-only', merge_base]).split() | 449 files = self._Capture(['diff', '--name-only', merge_base]).split() |
449 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 450 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
450 | 451 |
451 def FullUrlForRelativeUrl(self, url): | 452 def FullUrlForRelativeUrl(self, url): |
452 # Strip from last '/' | 453 # Strip from last '/' |
453 # Equivalent to unix basename | 454 # Equivalent to unix basename |
454 base_url = self.url | 455 base_url = self.url |
455 return base_url[:base_url.rfind('/')] + url | 456 return base_url[:base_url.rfind('/')] + url |
456 | 457 |
457 def _Clone(self, revision, url, options): | 458 def _Clone(self, revision, url, options): |
(...skipping 15 matching lines...) Expand all Loading... |
473 detach_head = False | 474 detach_head = False |
474 else: | 475 else: |
475 clone_cmd.append('--no-checkout') | 476 clone_cmd.append('--no-checkout') |
476 detach_head = True | 477 detach_head = True |
477 if options.verbose: | 478 if options.verbose: |
478 clone_cmd.append('--verbose') | 479 clone_cmd.append('--verbose') |
479 clone_cmd.extend([url, self.checkout_path]) | 480 clone_cmd.extend([url, self.checkout_path]) |
480 | 481 |
481 for _ in range(3): | 482 for _ in range(3): |
482 try: | 483 try: |
483 self._Run(clone_cmd, cwd=self._root_dir) | 484 self._Run(clone_cmd, options, cwd=self._root_dir) |
484 break | 485 break |
485 except gclient_utils.Error, e: | 486 except gclient_utils.Error, e: |
486 # TODO(maruel): Hackish, should be fixed by moving _Run() to | 487 # TODO(maruel): Hackish, should be fixed by moving _Run() to |
487 # CheckCall(). | 488 # CheckCall(). |
488 # Too bad we don't have access to the actual output. | 489 # Too bad we don't have access to the actual output. |
489 # We should check for "transfer closed with NNN bytes remaining to | 490 # We should check for "transfer closed with NNN bytes remaining to |
490 # read". In the meantime, just make sure .git exists. | 491 # read". In the meantime, just make sure .git exists. |
491 if (e.args[0] == 'git command clone returned 128' and | 492 if (e.args[0] == 'git command clone returned 128' and |
492 os.path.exists(os.path.join(self.checkout_path, '.git'))): | 493 os.path.exists(os.path.join(self.checkout_path, '.git'))): |
493 options.stdout.write(str(e) + '\n') | 494 options.stdout.write(str(e) + '\n') |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 if re.match(r'cannot rebase: you have unstaged changes', e.stderr) or \ | 538 if re.match(r'cannot rebase: you have unstaged changes', e.stderr) or \ |
538 re.match(r'cannot rebase: your index contains uncommitted changes', | 539 re.match(r'cannot rebase: your index contains uncommitted changes', |
539 e.stderr): | 540 e.stderr): |
540 while True: | 541 while True: |
541 rebase_action = str(raw_input("Cannot rebase because of unstaged " | 542 rebase_action = str(raw_input("Cannot rebase because of unstaged " |
542 "changes.\n'git reset --hard HEAD' ?\n" | 543 "changes.\n'git reset --hard HEAD' ?\n" |
543 "WARNING: destroys any uncommitted " | 544 "WARNING: destroys any uncommitted " |
544 "work in your current branch!" | 545 "work in your current branch!" |
545 " (y)es / (q)uit / (s)how : ")) | 546 " (y)es / (q)uit / (s)how : ")) |
546 if re.match(r'yes|y', rebase_action, re.I): | 547 if re.match(r'yes|y', rebase_action, re.I): |
547 self._Run(['reset', '--hard', 'HEAD']) | 548 self._Run(['reset', '--hard', 'HEAD'], options) |
548 # Should this be recursive? | 549 # Should this be recursive? |
549 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, | 550 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, |
550 self.checkout_path) | 551 self.checkout_path) |
551 break | 552 break |
552 elif re.match(r'quit|q', rebase_action, re.I): | 553 elif re.match(r'quit|q', rebase_action, re.I): |
553 raise gclient_utils.Error("Please merge or rebase manually\n" | 554 raise gclient_utils.Error("Please merge or rebase manually\n" |
554 "cd %s && git " % self.checkout_path | 555 "cd %s && git " % self.checkout_path |
555 + "%s" % ' '.join(rebase_cmd)) | 556 + "%s" % ' '.join(rebase_cmd)) |
556 elif re.match(r'show|s', rebase_action, re.I): | 557 elif re.match(r'show|s', rebase_action, re.I): |
557 options.stdout.write('\n%s\n' % e.stderr.strip()) | 558 options.stdout.write('\n%s\n' % e.stderr.strip()) |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 # Returns name of current branch or None for detached HEAD | 649 # Returns name of current branch or None for detached HEAD |
649 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) | 650 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) |
650 if branch == 'HEAD': | 651 if branch == 'HEAD': |
651 return None | 652 return None |
652 return branch | 653 return branch |
653 | 654 |
654 def _Capture(self, args): | 655 def _Capture(self, args): |
655 return gclient_utils.CheckCall(['git'] + args, | 656 return gclient_utils.CheckCall(['git'] + args, |
656 cwd=self.checkout_path)[0].strip() | 657 cwd=self.checkout_path)[0].strip() |
657 | 658 |
658 def _Run(self, args, **kwargs): | 659 def _Run(self, args, options, **kwargs): |
659 kwargs.setdefault('cwd', self.checkout_path) | 660 kwargs.setdefault('cwd', self.checkout_path) |
660 try: | 661 gclient_utils.CheckCallAndFilterAndHeader(['git'] + args, |
661 gclient_utils.Popen(['git'] + args, **kwargs).communicate() | 662 always=options.verbose, stdout=options.stdout, **kwargs) |
662 except OSError: | |
663 raise gclient_utils.Error("git command '%s' failed to run." % | |
664 ' '.join(cmd) + "\nCheck that you have git installed.") | |
665 | 663 |
666 | 664 |
667 class SVNWrapper(SCMWrapper): | 665 class SVNWrapper(SCMWrapper): |
668 """ Wrapper for SVN """ | 666 """ Wrapper for SVN """ |
669 | 667 |
670 def cleanup(self, options, args, file_list): | 668 def cleanup(self, options, args, file_list): |
671 """Cleanup working copy.""" | 669 """Cleanup working copy.""" |
672 self._Run(['cleanup'] + args, options) | 670 self._Run(['cleanup'] + args, options) |
673 | 671 |
674 def diff(self, options, args, file_list): | 672 def diff(self, options, args, file_list): |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 | 960 |
963 This method returns a new list to be used as a command.""" | 961 This method returns a new list to be used as a command.""" |
964 new_command = command[:] | 962 new_command = command[:] |
965 if revision: | 963 if revision: |
966 new_command.extend(['--revision', str(revision).strip()]) | 964 new_command.extend(['--revision', str(revision).strip()]) |
967 # --force was added to 'svn update' in svn 1.5. | 965 # --force was added to 'svn update' in svn 1.5. |
968 if ((options.force or options.manually_grab_svn_rev) and | 966 if ((options.force or options.manually_grab_svn_rev) and |
969 scm.SVN.AssertVersion("1.5")[0]): | 967 scm.SVN.AssertVersion("1.5")[0]): |
970 new_command.append('--force') | 968 new_command.append('--force') |
971 return new_command | 969 return new_command |
OLD | NEW |