| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 collections | 7 import collections |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import posixpath | 10 import posixpath |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 self._root_dir = root_dir | 130 self._root_dir = root_dir |
| 131 if self._root_dir: | 131 if self._root_dir: |
| 132 self._root_dir = self._root_dir.replace('/', os.sep) | 132 self._root_dir = self._root_dir.replace('/', os.sep) |
| 133 self.relpath = relpath | 133 self.relpath = relpath |
| 134 if self.relpath: | 134 if self.relpath: |
| 135 self.relpath = self.relpath.replace('/', os.sep) | 135 self.relpath = self.relpath.replace('/', os.sep) |
| 136 if self.relpath and self._root_dir: | 136 if self.relpath and self._root_dir: |
| 137 self.checkout_path = os.path.join(self._root_dir, self.relpath) | 137 self.checkout_path = os.path.join(self._root_dir, self.relpath) |
| 138 | 138 |
| 139 def RunCommand(self, command, options, args, file_list=None): | 139 def RunCommand(self, command, options, args, file_list=None): |
| 140 # file_list will have all files that are modified appended to it. | |
| 141 if file_list is None: | |
| 142 file_list = [] | |
| 143 | |
| 144 commands = ['cleanup', 'update', 'updatesingle', 'revert', | 140 commands = ['cleanup', 'update', 'updatesingle', 'revert', |
| 145 'revinfo', 'status', 'diff', 'pack', 'runhooks'] | 141 'revinfo', 'status', 'diff', 'pack', 'runhooks'] |
| 146 | 142 |
| 147 if not command in commands: | 143 if not command in commands: |
| 148 raise gclient_utils.Error('Unknown command %s' % command) | 144 raise gclient_utils.Error('Unknown command %s' % command) |
| 149 | 145 |
| 150 if not command in dir(self): | 146 if not command in dir(self): |
| 151 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( | 147 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( |
| 152 command, self.__class__.__name__)) | 148 command, self.__class__.__name__)) |
| 153 | 149 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 result, version = scm.GIT.AssertVersion('1.7') | 209 result, version = scm.GIT.AssertVersion('1.7') |
| 214 if not result: | 210 if not result: |
| 215 raise gclient_utils.Error('Git version is older than 1.7: %s' % version) | 211 raise gclient_utils.Error('Git version is older than 1.7: %s' % version) |
| 216 return result | 212 return result |
| 217 except OSError: | 213 except OSError: |
| 218 return False | 214 return False |
| 219 | 215 |
| 220 def GetCheckoutRoot(self): | 216 def GetCheckoutRoot(self): |
| 221 return scm.GIT.GetCheckoutRoot(self.checkout_path) | 217 return scm.GIT.GetCheckoutRoot(self.checkout_path) |
| 222 | 218 |
| 223 def GetRevisionDate(self, revision): | 219 def GetRevisionDate(self, _revision): |
| 224 """Returns the given revision's date in ISO-8601 format (which contains the | 220 """Returns the given revision's date in ISO-8601 format (which contains the |
| 225 time zone).""" | 221 time zone).""" |
| 226 # TODO(floitsch): get the time-stamp of the given revision and not just the | 222 # TODO(floitsch): get the time-stamp of the given revision and not just the |
| 227 # time-stamp of the currently checked out revision. | 223 # time-stamp of the currently checked out revision. |
| 228 return self._Capture(['log', '-n', '1', '--format=%ai']) | 224 return self._Capture(['log', '-n', '1', '--format=%ai']) |
| 229 | 225 |
| 230 @staticmethod | 226 @staticmethod |
| 231 def cleanup(options, args, file_list): | 227 def cleanup(options, args, file_list): |
| 232 """'Cleanup' the repo. | 228 """'Cleanup' the repo. |
| 233 | 229 |
| 234 There's no real git equivalent for the svn cleanup command, do a no-op. | 230 There's no real git equivalent for the svn cleanup command, do a no-op. |
| 235 """ | 231 """ |
| 236 | 232 |
| 237 def diff(self, options, args, file_list): | 233 def diff(self, options, _args, _file_list): |
| 238 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 234 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
| 239 self._Run(['diff', merge_base], options) | 235 self._Run(['diff', merge_base], options) |
| 240 | 236 |
| 241 def pack(self, options, args, file_list): | 237 def pack(self, _options, _args, _file_list): |
| 242 """Generates a patch file which can be applied to the root of the | 238 """Generates a patch file which can be applied to the root of the |
| 243 repository. | 239 repository. |
| 244 | 240 |
| 245 The patch file is generated from a diff of the merge base of HEAD and | 241 The patch file is generated from a diff of the merge base of HEAD and |
| 246 its upstream branch. | 242 its upstream branch. |
| 247 """ | 243 """ |
| 248 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 244 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
| 249 gclient_utils.CheckCallAndFilter( | 245 gclient_utils.CheckCallAndFilter( |
| 250 ['git', 'diff', merge_base], | 246 ['git', 'diff', merge_base], |
| 251 cwd=self.checkout_path, | 247 cwd=self.checkout_path, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 quiet = [] | 282 quiet = [] |
| 287 if not options.verbose: | 283 if not options.verbose: |
| 288 quiet = ['--quiet'] | 284 quiet = ['--quiet'] |
| 289 self._UpdateBranchHeads(options, fetch=False) | 285 self._UpdateBranchHeads(options, fetch=False) |
| 290 | 286 |
| 291 fetch_cmd = [ | 287 fetch_cmd = [ |
| 292 '-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin', '--prune'] | 288 '-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin', '--prune'] |
| 293 self._Run(fetch_cmd + quiet, options) | 289 self._Run(fetch_cmd + quiet, options) |
| 294 self._Run(['reset', '--hard', revision] + quiet, options) | 290 self._Run(['reset', '--hard', revision] + quiet, options) |
| 295 self.UpdateSubmoduleConfig() | 291 self.UpdateSubmoduleConfig() |
| 296 files = self._Capture(['ls-files']).splitlines() | 292 if file_list is not None: |
| 297 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 293 files = self._Capture(['ls-files']).splitlines() |
| 294 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 298 | 295 |
| 299 def update(self, options, args, file_list): | 296 def update(self, options, args, file_list): |
| 300 """Runs git to update or transparently checkout the working copy. | 297 """Runs git to update or transparently checkout the working copy. |
| 301 | 298 |
| 302 All updated files will be appended to file_list. | 299 All updated files will be appended to file_list. |
| 303 | 300 |
| 304 Raises: | 301 Raises: |
| 305 Error: if can't get URL for relative path. | 302 Error: if can't get URL for relative path. |
| 306 """ | 303 """ |
| 307 if args: | 304 if args: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 325 | 322 |
| 326 if gclient_utils.IsDateRevision(revision): | 323 if gclient_utils.IsDateRevision(revision): |
| 327 # Date-revisions only work on git-repositories if the reflog hasn't | 324 # Date-revisions only work on git-repositories if the reflog hasn't |
| 328 # expired yet. Use rev-list to get the corresponding revision. | 325 # expired yet. Use rev-list to get the corresponding revision. |
| 329 # git rev-list -n 1 --before='time-stamp' branchname | 326 # git rev-list -n 1 --before='time-stamp' branchname |
| 330 if options.transitive: | 327 if options.transitive: |
| 331 print('Warning: --transitive only works for SVN repositories.') | 328 print('Warning: --transitive only works for SVN repositories.') |
| 332 revision = default_rev | 329 revision = default_rev |
| 333 | 330 |
| 334 rev_str = ' at %s' % revision | 331 rev_str = ' at %s' % revision |
| 335 files = [] | 332 files = [] if file_list is not None else None |
| 336 | 333 |
| 337 printed_path = False | 334 printed_path = False |
| 338 verbose = [] | 335 verbose = [] |
| 339 if options.verbose: | 336 if options.verbose: |
| 340 print('\n_____ %s%s' % (self.relpath, rev_str)) | 337 print('\n_____ %s%s' % (self.relpath, rev_str)) |
| 341 verbose = ['--verbose'] | 338 verbose = ['--verbose'] |
| 342 printed_path = True | 339 printed_path = True |
| 343 | 340 |
| 344 url = self._CreateOrUpdateCache(url, options) | 341 url = self._CreateOrUpdateCache(url, options) |
| 345 | 342 |
| 346 if revision.startswith('refs/'): | 343 if revision.startswith('refs/'): |
| 347 rev_type = "branch" | 344 rev_type = "branch" |
| 348 elif revision.startswith('origin/'): | 345 elif revision.startswith('origin/'): |
| 349 # For compatability with old naming, translate 'origin' to 'refs/heads' | 346 # For compatability with old naming, translate 'origin' to 'refs/heads' |
| 350 revision = revision.replace('origin/', 'refs/heads/') | 347 revision = revision.replace('origin/', 'refs/heads/') |
| 351 rev_type = "branch" | 348 rev_type = "branch" |
| 352 else: | 349 else: |
| 353 # hash is also a tag, only make a distinction at checkout | 350 # hash is also a tag, only make a distinction at checkout |
| 354 rev_type = "hash" | 351 rev_type = "hash" |
| 355 | 352 |
| 356 if not os.path.exists(self.checkout_path) or ( | 353 if not os.path.exists(self.checkout_path) or ( |
| 357 os.path.isdir(self.checkout_path) and | 354 os.path.isdir(self.checkout_path) and |
| 358 not os.listdir(self.checkout_path)): | 355 not os.listdir(self.checkout_path)): |
| 359 gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path)) | 356 gclient_utils.safe_makedirs(os.path.dirname(self.checkout_path)) |
| 360 self._Clone(revision, url, options) | 357 self._Clone(revision, url, options) |
| 361 self.UpdateSubmoduleConfig() | 358 self.UpdateSubmoduleConfig() |
| 362 files = self._Capture(['ls-files']).splitlines() | 359 if file_list is not None: |
| 363 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 360 files = self._Capture(['ls-files']).splitlines() |
| 361 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 364 if not verbose: | 362 if not verbose: |
| 365 # Make the output a little prettier. It's nice to have some whitespace | 363 # Make the output a little prettier. It's nice to have some whitespace |
| 366 # between projects when cloning. | 364 # between projects when cloning. |
| 367 print('') | 365 print('') |
| 368 return | 366 return |
| 369 | 367 |
| 370 if not managed: | 368 if not managed: |
| 371 self._UpdateBranchHeads(options, fetch=False) | 369 self._UpdateBranchHeads(options, fetch=False) |
| 372 self.UpdateSubmoduleConfig() | 370 self.UpdateSubmoduleConfig() |
| 373 print ('________ unmanaged solution; skipping %s' % self.relpath) | 371 print ('________ unmanaged solution; skipping %s' % self.relpath) |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 if not printed_path: | 501 if not printed_path: |
| 504 print('\n_____ %s%s' % (self.relpath, rev_str)) | 502 print('\n_____ %s%s' % (self.relpath, rev_str)) |
| 505 switch_error = ("Switching upstream branch from %s to %s\n" | 503 switch_error = ("Switching upstream branch from %s to %s\n" |
| 506 % (upstream_branch, new_base) + | 504 % (upstream_branch, new_base) + |
| 507 "Please merge or rebase manually:\n" + | 505 "Please merge or rebase manually:\n" + |
| 508 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) + | 506 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) + |
| 509 "OR git checkout -b <some new branch> %s" % new_base) | 507 "OR git checkout -b <some new branch> %s" % new_base) |
| 510 raise gclient_utils.Error(switch_error) | 508 raise gclient_utils.Error(switch_error) |
| 511 else: | 509 else: |
| 512 # case 3 - the default case | 510 # case 3 - the default case |
| 513 files = self._Capture(['diff', upstream_branch, '--name-only']).split() | 511 if files is not None: |
| 512 files = self._Capture(['diff', upstream_branch, '--name-only']).split() |
| 514 if verbose: | 513 if verbose: |
| 515 print('Trying fast-forward merge to branch : %s' % upstream_branch) | 514 print('Trying fast-forward merge to branch : %s' % upstream_branch) |
| 516 try: | 515 try: |
| 517 merge_args = ['merge'] | 516 merge_args = ['merge'] |
| 518 if not options.merge: | 517 if not options.merge: |
| 519 merge_args.append('--ff-only') | 518 merge_args.append('--ff-only') |
| 520 merge_args.append(upstream_branch) | 519 merge_args.append(upstream_branch) |
| 521 merge_output = scm.GIT.Capture(merge_args, cwd=self.checkout_path) | 520 merge_output = scm.GIT.Capture(merge_args, cwd=self.checkout_path) |
| 522 except subprocess2.CalledProcessError as e: | 521 except subprocess2.CalledProcessError as e: |
| 523 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr): | 522 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr): |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 if not printed_path: | 564 if not printed_path: |
| 566 print('\n_____ %s%s' % (self.relpath, rev_str)) | 565 print('\n_____ %s%s' % (self.relpath, rev_str)) |
| 567 printed_path = True | 566 printed_path = True |
| 568 print(merge_output.strip()) | 567 print(merge_output.strip()) |
| 569 if not verbose: | 568 if not verbose: |
| 570 # Make the output a little prettier. It's nice to have some | 569 # Make the output a little prettier. It's nice to have some |
| 571 # whitespace between projects when syncing. | 570 # whitespace between projects when syncing. |
| 572 print('') | 571 print('') |
| 573 | 572 |
| 574 self.UpdateSubmoduleConfig() | 573 self.UpdateSubmoduleConfig() |
| 575 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 574 if file_list is not None: |
| 575 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 576 | 576 |
| 577 # If the rebase generated a conflict, abort and ask user to fix | 577 # If the rebase generated a conflict, abort and ask user to fix |
| 578 if self._IsRebasing(): | 578 if self._IsRebasing(): |
| 579 raise gclient_utils.Error('\n____ %s%s\n' | 579 raise gclient_utils.Error('\n____ %s%s\n' |
| 580 '\nConflict while rebasing this branch.\n' | 580 '\nConflict while rebasing this branch.\n' |
| 581 'Fix the conflict and run gclient again.\n' | 581 'Fix the conflict and run gclient again.\n' |
| 582 'See man git-rebase for details.\n' | 582 'See man git-rebase for details.\n' |
| 583 % (self.relpath, rev_str)) | 583 % (self.relpath, rev_str)) |
| 584 | 584 |
| 585 if verbose: | 585 if verbose: |
| 586 print('Checked out revision %s' % self.revinfo(options, (), None)) | 586 print('Checked out revision %s' % self.revinfo(options, (), None)) |
| 587 | 587 |
| 588 # If --reset and --delete_unversioned_trees are specified, remove any | 588 # If --reset and --delete_unversioned_trees are specified, remove any |
| 589 # untracked directories. | 589 # untracked directories. |
| 590 if options.reset and options.delete_unversioned_trees: | 590 if options.reset and options.delete_unversioned_trees: |
| 591 # GIT.CaptureStatus() uses 'dit diff' to compare to a specific SHA1 (the | 591 # GIT.CaptureStatus() uses 'dit diff' to compare to a specific SHA1 (the |
| 592 # merge-base by default), so doesn't include untracked files. So we use | 592 # merge-base by default), so doesn't include untracked files. So we use |
| 593 # 'git ls-files --directory --others --exclude-standard' here directly. | 593 # 'git ls-files --directory --others --exclude-standard' here directly. |
| 594 paths = scm.GIT.Capture( | 594 paths = scm.GIT.Capture( |
| 595 ['ls-files', '--directory', '--others', '--exclude-standard'], | 595 ['ls-files', '--directory', '--others', '--exclude-standard'], |
| 596 self.checkout_path) | 596 self.checkout_path) |
| 597 for path in (p for p in paths.splitlines() if p.endswith('/')): | 597 for path in (p for p in paths.splitlines() if p.endswith('/')): |
| 598 full_path = os.path.join(self.checkout_path, path) | 598 full_path = os.path.join(self.checkout_path, path) |
| 599 if not os.path.islink(full_path): | 599 if not os.path.islink(full_path): |
| 600 print('\n_____ removing unversioned directory %s' % path) | 600 print('\n_____ removing unversioned directory %s' % path) |
| 601 gclient_utils.rmtree(full_path) | 601 gclient_utils.rmtree(full_path) |
| 602 | 602 |
| 603 | 603 |
| 604 def revert(self, options, args, file_list): | 604 def revert(self, options, _args, file_list): |
| 605 """Reverts local modifications. | 605 """Reverts local modifications. |
| 606 | 606 |
| 607 All reverted files will be appended to file_list. | 607 All reverted files will be appended to file_list. |
| 608 """ | 608 """ |
| 609 if not os.path.isdir(self.checkout_path): | 609 if not os.path.isdir(self.checkout_path): |
| 610 # revert won't work if the directory doesn't exist. It needs to | 610 # revert won't work if the directory doesn't exist. It needs to |
| 611 # checkout instead. | 611 # checkout instead. |
| 612 print('\n_____ %s is missing, synching instead' % self.relpath) | 612 print('\n_____ %s is missing, synching instead' % self.relpath) |
| 613 # Don't reuse the args. | 613 # Don't reuse the args. |
| 614 return self.update(options, [], file_list) | 614 return self.update(options, [], file_list) |
| 615 | 615 |
| 616 default_rev = "refs/heads/master" | 616 default_rev = "refs/heads/master" |
| 617 if options.upstream: | 617 if options.upstream: |
| 618 if self._GetCurrentBranch(): | 618 if self._GetCurrentBranch(): |
| 619 upstream_branch = scm.GIT.GetUpstreamBranch(self.checkout_path) | 619 upstream_branch = scm.GIT.GetUpstreamBranch(self.checkout_path) |
| 620 default_rev = upstream_branch or default_rev | 620 default_rev = upstream_branch or default_rev |
| 621 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) | 621 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) |
| 622 if not deps_revision: | 622 if not deps_revision: |
| 623 deps_revision = default_rev | 623 deps_revision = default_rev |
| 624 if deps_revision.startswith('refs/heads/'): | 624 if deps_revision.startswith('refs/heads/'): |
| 625 deps_revision = deps_revision.replace('refs/heads/', 'origin/') | 625 deps_revision = deps_revision.replace('refs/heads/', 'origin/') |
| 626 | 626 |
| 627 files = self._Capture(['diff', deps_revision, '--name-only']).split() | 627 if file_list is not None: |
| 628 files = self._Capture(['diff', deps_revision, '--name-only']).split() |
| 629 |
| 628 self._Run(['reset', '--hard', deps_revision], options) | 630 self._Run(['reset', '--hard', deps_revision], options) |
| 629 self._Run(['clean', '-f', '-d'], options) | 631 self._Run(['clean', '-f', '-d'], options) |
| 630 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | |
| 631 | 632 |
| 632 def revinfo(self, options, args, file_list): | 633 if file_list is not None: |
| 634 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 635 |
| 636 def revinfo(self, _options, _args, _file_list): |
| 633 """Returns revision""" | 637 """Returns revision""" |
| 634 return self._Capture(['rev-parse', 'HEAD']) | 638 return self._Capture(['rev-parse', 'HEAD']) |
| 635 | 639 |
| 636 def runhooks(self, options, args, file_list): | 640 def runhooks(self, options, args, file_list): |
| 637 self.status(options, args, file_list) | 641 self.status(options, args, file_list) |
| 638 | 642 |
| 639 def status(self, options, args, file_list): | 643 def status(self, options, _args, file_list): |
| 640 """Display status information.""" | 644 """Display status information.""" |
| 641 if not os.path.isdir(self.checkout_path): | 645 if not os.path.isdir(self.checkout_path): |
| 642 print(('\n________ couldn\'t run status in %s:\n' | 646 print(('\n________ couldn\'t run status in %s:\n' |
| 643 'The directory does not exist.') % self.checkout_path) | 647 'The directory does not exist.') % self.checkout_path) |
| 644 else: | 648 else: |
| 645 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 649 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
| 646 self._Run(['diff', '--name-status', merge_base], options) | 650 self._Run(['diff', '--name-status', merge_base], options) |
| 647 files = self._Capture(['diff', '--name-only', merge_base]).split() | 651 if file_list is not None: |
| 648 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 652 files = self._Capture(['diff', '--name-only', merge_base]).split() |
| 653 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 649 | 654 |
| 650 def GetUsableRev(self, rev, options): | 655 def GetUsableRev(self, rev, options): |
| 651 """Finds a useful revision for this repository. | 656 """Finds a useful revision for this repository. |
| 652 | 657 |
| 653 If SCM is git-svn and the head revision is less than |rev|, git svn fetch | 658 If SCM is git-svn and the head revision is less than |rev|, git svn fetch |
| 654 will be called on the source.""" | 659 will be called on the source.""" |
| 655 sha1 = None | 660 sha1 = None |
| 656 if not os.path.isdir(self.checkout_path): | 661 if not os.path.isdir(self.checkout_path): |
| 657 raise gclient_utils.Error( | 662 raise gclient_utils.Error( |
| 658 ( 'We could not find a valid hash for safesync_url response "%s".\n' | 663 ( 'We could not find a valid hash for safesync_url response "%s".\n' |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 self._Capture(['checkout', '--quiet', '%s' % revision]) | 828 self._Capture(['checkout', '--quiet', '%s' % revision]) |
| 824 print( | 829 print( |
| 825 ('Checked out %s to a detached HEAD. Before making any commits\n' | 830 ('Checked out %s to a detached HEAD. Before making any commits\n' |
| 826 'in this repo, you should use \'git checkout <branch>\' to switch to\n' | 831 'in this repo, you should use \'git checkout <branch>\' to switch to\n' |
| 827 'an existing branch or use \'git checkout origin -b <branch>\' to\n' | 832 'an existing branch or use \'git checkout origin -b <branch>\' to\n' |
| 828 'create a new branch for your work.') % revision) | 833 'create a new branch for your work.') % revision) |
| 829 | 834 |
| 830 def _AttemptRebase(self, upstream, files, options, newbase=None, | 835 def _AttemptRebase(self, upstream, files, options, newbase=None, |
| 831 branch=None, printed_path=False): | 836 branch=None, printed_path=False): |
| 832 """Attempt to rebase onto either upstream or, if specified, newbase.""" | 837 """Attempt to rebase onto either upstream or, if specified, newbase.""" |
| 833 files.extend(self._Capture(['diff', upstream, '--name-only']).split()) | 838 if files is not None: |
| 839 files.extend(self._Capture(['diff', upstream, '--name-only']).split()) |
| 834 revision = upstream | 840 revision = upstream |
| 835 if newbase: | 841 if newbase: |
| 836 revision = newbase | 842 revision = newbase |
| 837 if not printed_path: | 843 if not printed_path: |
| 838 print('\n_____ %s : Attempting rebase onto %s...' % ( | 844 print('\n_____ %s : Attempting rebase onto %s...' % ( |
| 839 self.relpath, revision)) | 845 self.relpath, revision)) |
| 840 printed_path = True | 846 printed_path = True |
| 841 else: | 847 else: |
| 842 print('Attempting rebase onto %s...' % revision) | 848 print('Attempting rebase onto %s...' % revision) |
| 843 | 849 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 try: | 954 try: |
| 949 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r', | 955 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r', |
| 950 '--ignore-submodules', 'HEAD', '--'], | 956 '--ignore-submodules', 'HEAD', '--'], |
| 951 cwd=self.checkout_path) | 957 cwd=self.checkout_path) |
| 952 except subprocess2.CalledProcessError: | 958 except subprocess2.CalledProcessError: |
| 953 raise gclient_utils.Error('\n____ %s%s\n' | 959 raise gclient_utils.Error('\n____ %s%s\n' |
| 954 '\tYour index contains uncommitted changes\n' | 960 '\tYour index contains uncommitted changes\n' |
| 955 '\tPlease commit, stash, or reset.\n' | 961 '\tPlease commit, stash, or reset.\n' |
| 956 % (self.relpath, rev_str)) | 962 % (self.relpath, rev_str)) |
| 957 | 963 |
| 958 def _CheckDetachedHead(self, rev_str, options): | 964 def _CheckDetachedHead(self, rev_str, _options): |
| 959 # HEAD is detached. Make sure it is safe to move away from (i.e., it is | 965 # HEAD is detached. Make sure it is safe to move away from (i.e., it is |
| 960 # reference by a commit). If not, error out -- most likely a rebase is | 966 # reference by a commit). If not, error out -- most likely a rebase is |
| 961 # in progress, try to detect so we can give a better error. | 967 # in progress, try to detect so we can give a better error. |
| 962 try: | 968 try: |
| 963 scm.GIT.Capture(['name-rev', '--no-undefined', 'HEAD'], | 969 scm.GIT.Capture(['name-rev', '--no-undefined', 'HEAD'], |
| 964 cwd=self.checkout_path) | 970 cwd=self.checkout_path) |
| 965 except subprocess2.CalledProcessError: | 971 except subprocess2.CalledProcessError: |
| 966 # Commit is not contained by any rev. See if the user is rebasing: | 972 # Commit is not contained by any rev. See if the user is rebasing: |
| 967 if self._IsRebasing(): | 973 if self._IsRebasing(): |
| 968 # Punt to the user | 974 # Punt to the user |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 return scm.SVN.GetCheckoutRoot(self.checkout_path) | 1056 return scm.SVN.GetCheckoutRoot(self.checkout_path) |
| 1051 | 1057 |
| 1052 def GetRevisionDate(self, revision): | 1058 def GetRevisionDate(self, revision): |
| 1053 """Returns the given revision's date in ISO-8601 format (which contains the | 1059 """Returns the given revision's date in ISO-8601 format (which contains the |
| 1054 time zone).""" | 1060 time zone).""" |
| 1055 date = scm.SVN.Capture( | 1061 date = scm.SVN.Capture( |
| 1056 ['propget', '--revprop', 'svn:date', '-r', revision], | 1062 ['propget', '--revprop', 'svn:date', '-r', revision], |
| 1057 os.path.join(self.checkout_path, '.')) | 1063 os.path.join(self.checkout_path, '.')) |
| 1058 return date.strip() | 1064 return date.strip() |
| 1059 | 1065 |
| 1060 def cleanup(self, options, args, file_list): | 1066 def cleanup(self, options, args, _file_list): |
| 1061 """Cleanup working copy.""" | 1067 """Cleanup working copy.""" |
| 1062 self._Run(['cleanup'] + args, options) | 1068 self._Run(['cleanup'] + args, options) |
| 1063 | 1069 |
| 1064 def diff(self, options, args, file_list): | 1070 def diff(self, options, args, _file_list): |
| 1065 # NOTE: This function does not currently modify file_list. | 1071 # NOTE: This function does not currently modify file_list. |
| 1066 if not os.path.isdir(self.checkout_path): | 1072 if not os.path.isdir(self.checkout_path): |
| 1067 raise gclient_utils.Error('Directory %s is not present.' % | 1073 raise gclient_utils.Error('Directory %s is not present.' % |
| 1068 self.checkout_path) | 1074 self.checkout_path) |
| 1069 self._Run(['diff'] + args, options) | 1075 self._Run(['diff'] + args, options) |
| 1070 | 1076 |
| 1071 def pack(self, options, args, file_list): | 1077 def pack(self, _options, args, _file_list): |
| 1072 """Generates a patch file which can be applied to the root of the | 1078 """Generates a patch file which can be applied to the root of the |
| 1073 repository.""" | 1079 repository.""" |
| 1074 if not os.path.isdir(self.checkout_path): | 1080 if not os.path.isdir(self.checkout_path): |
| 1075 raise gclient_utils.Error('Directory %s is not present.' % | 1081 raise gclient_utils.Error('Directory %s is not present.' % |
| 1076 self.checkout_path) | 1082 self.checkout_path) |
| 1077 gclient_utils.CheckCallAndFilter( | 1083 gclient_utils.CheckCallAndFilter( |
| 1078 ['svn', 'diff', '-x', '--ignore-eol-style'] + args, | 1084 ['svn', 'diff', '-x', '--ignore-eol-style'] + args, |
| 1079 cwd=self.checkout_path, | 1085 cwd=self.checkout_path, |
| 1080 print_stdout=False, | 1086 print_stdout=False, |
| 1081 nag_timer=self.nag_timer, | 1087 nag_timer=self.nag_timer, |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 # information is not stored next to the file, so we will have to | 1285 # information is not stored next to the file, so we will have to |
| 1280 # re-export the file every time we sync. | 1286 # re-export the file every time we sync. |
| 1281 if not os.path.exists(self.checkout_path): | 1287 if not os.path.exists(self.checkout_path): |
| 1282 gclient_utils.safe_makedirs(self.checkout_path) | 1288 gclient_utils.safe_makedirs(self.checkout_path) |
| 1283 command = ["export", os.path.join(self.url, filename), | 1289 command = ["export", os.path.join(self.url, filename), |
| 1284 os.path.join(self.checkout_path, filename)] | 1290 os.path.join(self.checkout_path, filename)] |
| 1285 command = self._AddAdditionalUpdateFlags(command, options, | 1291 command = self._AddAdditionalUpdateFlags(command, options, |
| 1286 options.revision) | 1292 options.revision) |
| 1287 self._Run(command, options, cwd=self._root_dir) | 1293 self._Run(command, options, cwd=self._root_dir) |
| 1288 | 1294 |
| 1289 def revert(self, options, args, file_list): | 1295 def revert(self, options, _args, file_list): |
| 1290 """Reverts local modifications. Subversion specific. | 1296 """Reverts local modifications. Subversion specific. |
| 1291 | 1297 |
| 1292 All reverted files will be appended to file_list, even if Subversion | 1298 All reverted files will be appended to file_list, even if Subversion |
| 1293 doesn't know about them. | 1299 doesn't know about them. |
| 1294 """ | 1300 """ |
| 1295 if not os.path.isdir(self.checkout_path): | 1301 if not os.path.isdir(self.checkout_path): |
| 1296 if os.path.exists(self.checkout_path): | 1302 if os.path.exists(self.checkout_path): |
| 1297 gclient_utils.rmtree(self.checkout_path) | 1303 gclient_utils.rmtree(self.checkout_path) |
| 1298 # svn revert won't work if the directory doesn't exist. It needs to | 1304 # svn revert won't work if the directory doesn't exist. It needs to |
| 1299 # checkout instead. | 1305 # checkout instead. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1311 if not options.force: | 1317 if not options.force: |
| 1312 raise gclient_utils.Error('Invalid checkout path, aborting') | 1318 raise gclient_utils.Error('Invalid checkout path, aborting') |
| 1313 print( | 1319 print( |
| 1314 '\n_____ %s is not a valid svn checkout, synching instead' % | 1320 '\n_____ %s is not a valid svn checkout, synching instead' % |
| 1315 self.relpath) | 1321 self.relpath) |
| 1316 gclient_utils.rmtree(self.checkout_path) | 1322 gclient_utils.rmtree(self.checkout_path) |
| 1317 # Don't reuse the args. | 1323 # Don't reuse the args. |
| 1318 return self.update(options, [], file_list) | 1324 return self.update(options, [], file_list) |
| 1319 | 1325 |
| 1320 def printcb(file_status): | 1326 def printcb(file_status): |
| 1321 file_list.append(file_status[1]) | 1327 if file_list is not None: |
| 1328 file_list.append(file_status[1]) |
| 1322 if logging.getLogger().isEnabledFor(logging.INFO): | 1329 if logging.getLogger().isEnabledFor(logging.INFO): |
| 1323 logging.info('%s%s' % (file_status[0], file_status[1])) | 1330 logging.info('%s%s' % (file_status[0], file_status[1])) |
| 1324 else: | 1331 else: |
| 1325 print(os.path.join(self.checkout_path, file_status[1])) | 1332 print(os.path.join(self.checkout_path, file_status[1])) |
| 1326 scm.SVN.Revert(self.checkout_path, callback=printcb) | 1333 scm.SVN.Revert(self.checkout_path, callback=printcb) |
| 1327 | 1334 |
| 1328 # Revert() may delete the directory altogether. | 1335 # Revert() may delete the directory altogether. |
| 1329 if not os.path.isdir(self.checkout_path): | 1336 if not os.path.isdir(self.checkout_path): |
| 1330 # Don't reuse the args. | 1337 # Don't reuse the args. |
| 1331 return self.update(options, [], file_list) | 1338 return self.update(options, [], file_list) |
| 1332 | 1339 |
| 1333 try: | 1340 try: |
| 1334 # svn revert is so broken we don't even use it. Using | 1341 # svn revert is so broken we don't even use it. Using |
| 1335 # "svn up --revision BASE" achieve the same effect. | 1342 # "svn up --revision BASE" achieve the same effect. |
| 1336 # file_list will contain duplicates. | 1343 # file_list will contain duplicates. |
| 1337 self._RunAndGetFileList(['update', '--revision', 'BASE'], options, | 1344 self._RunAndGetFileList(['update', '--revision', 'BASE'], options, |
| 1338 file_list) | 1345 file_list) |
| 1339 except OSError, e: | 1346 except OSError, e: |
| 1340 # Maybe the directory disapeared meanwhile. Do not throw an exception. | 1347 # Maybe the directory disapeared meanwhile. Do not throw an exception. |
| 1341 logging.error('Failed to update:\n%s' % str(e)) | 1348 logging.error('Failed to update:\n%s' % str(e)) |
| 1342 | 1349 |
| 1343 def revinfo(self, options, args, file_list): | 1350 def revinfo(self, _options, _args, _file_list): |
| 1344 """Display revision""" | 1351 """Display revision""" |
| 1345 try: | 1352 try: |
| 1346 return scm.SVN.CaptureRevision(self.checkout_path) | 1353 return scm.SVN.CaptureRevision(self.checkout_path) |
| 1347 except (gclient_utils.Error, subprocess2.CalledProcessError): | 1354 except (gclient_utils.Error, subprocess2.CalledProcessError): |
| 1348 return None | 1355 return None |
| 1349 | 1356 |
| 1350 def runhooks(self, options, args, file_list): | 1357 def runhooks(self, options, args, file_list): |
| 1351 self.status(options, args, file_list) | 1358 self.status(options, args, file_list) |
| 1352 | 1359 |
| 1353 def status(self, options, args, file_list): | 1360 def status(self, options, args, file_list): |
| 1354 """Display status information.""" | 1361 """Display status information.""" |
| 1355 command = ['status'] + args | 1362 command = ['status'] + args |
| 1356 if not os.path.isdir(self.checkout_path): | 1363 if not os.path.isdir(self.checkout_path): |
| 1357 # svn status won't work if the directory doesn't exist. | 1364 # svn status won't work if the directory doesn't exist. |
| 1358 print(('\n________ couldn\'t run \'%s\' in \'%s\':\n' | 1365 print(('\n________ couldn\'t run \'%s\' in \'%s\':\n' |
| 1359 'The directory does not exist.') % | 1366 'The directory does not exist.') % |
| 1360 (' '.join(command), self.checkout_path)) | 1367 (' '.join(command), self.checkout_path)) |
| 1361 # There's no file list to retrieve. | 1368 # There's no file list to retrieve. |
| 1362 else: | 1369 else: |
| 1363 self._RunAndGetFileList(command, options, file_list) | 1370 self._RunAndGetFileList(command, options, file_list) |
| 1364 | 1371 |
| 1365 def GetUsableRev(self, rev, options): | 1372 def GetUsableRev(self, rev, _options): |
| 1366 """Verifies the validity of the revision for this repository.""" | 1373 """Verifies the validity of the revision for this repository.""" |
| 1367 if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)): | 1374 if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)): |
| 1368 raise gclient_utils.Error( | 1375 raise gclient_utils.Error( |
| 1369 ( '%s isn\'t a valid revision. Please check that your safesync_url is\n' | 1376 ( '%s isn\'t a valid revision. Please check that your safesync_url is\n' |
| 1370 'correct.') % rev) | 1377 'correct.') % rev) |
| 1371 return rev | 1378 return rev |
| 1372 | 1379 |
| 1373 def FullUrlForRelativeUrl(self, url): | 1380 def FullUrlForRelativeUrl(self, url): |
| 1374 # Find the forth '/' and strip from there. A bit hackish. | 1381 # Find the forth '/' and strip from there. A bit hackish. |
| 1375 return '/'.join(self.url.split('/')[:4]) + url | 1382 return '/'.join(self.url.split('/')[:4]) + url |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 new_command.append('--force') | 1421 new_command.append('--force') |
| 1415 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1422 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1416 new_command.extend(('--accept', 'theirs-conflict')) | 1423 new_command.extend(('--accept', 'theirs-conflict')) |
| 1417 elif options.manually_grab_svn_rev: | 1424 elif options.manually_grab_svn_rev: |
| 1418 new_command.append('--force') | 1425 new_command.append('--force') |
| 1419 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1426 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1420 new_command.extend(('--accept', 'postpone')) | 1427 new_command.extend(('--accept', 'postpone')) |
| 1421 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1428 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1422 new_command.extend(('--accept', 'postpone')) | 1429 new_command.extend(('--accept', 'postpone')) |
| 1423 return new_command | 1430 return new_command |
| OLD | NEW |