| 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 |