Chromium Code Reviews| 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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 raise gclient_utils.Error('\n____ %s%s\n' | 375 raise gclient_utils.Error('\n____ %s%s\n' |
| 376 '\tPath is not a git repo. No .git dir.\n' | 376 '\tPath is not a git repo. No .git dir.\n' |
| 377 '\tTo resolve:\n' | 377 '\tTo resolve:\n' |
| 378 '\t\trm -rf %s\n' | 378 '\t\trm -rf %s\n' |
| 379 '\tAnd run gclient sync again\n' | 379 '\tAnd run gclient sync again\n' |
| 380 % (self.relpath, rev_str, self.relpath)) | 380 % (self.relpath, rev_str, self.relpath)) |
| 381 | 381 |
| 382 # See if the url has changed (the unittests use git://foo for the url, let | 382 # See if the url has changed (the unittests use git://foo for the url, let |
| 383 # that through). | 383 # that through). |
| 384 current_url = self._Capture(['config', 'remote.origin.url']) | 384 current_url = self._Capture(['config', 'remote.origin.url']) |
| 385 return_early = False | |
| 385 # TODO(maruel): Delete url != 'git://foo' since it's just to make the | 386 # TODO(maruel): Delete url != 'git://foo' since it's just to make the |
| 386 # unit test pass. (and update the comment above) | 387 # unit test pass. (and update the comment above) |
| 387 # Skip url auto-correction if remote.origin.gclient-auto-fix-url is set. | 388 # Skip url auto-correction if remote.origin.gclient-auto-fix-url is set. |
| 388 # This allows devs to use experimental repos which have a different url | 389 # This allows devs to use experimental repos which have a different url |
| 389 # but whose branch(s) are the same as official repos. | 390 # but whose branch(s) are the same as official repos. |
| 390 if (current_url != url and | 391 if (current_url != url and |
| 391 url != 'git://foo' and | 392 url != 'git://foo' and |
| 392 subprocess2.capture( | 393 subprocess2.capture( |
| 393 ['git', 'config', 'remote.origin.gclient-auto-fix-url'], | 394 ['git', 'config', 'remote.origin.gclient-auto-fix-url'], |
| 394 cwd=self.checkout_path).strip() != 'False'): | 395 cwd=self.checkout_path).strip() != 'False'): |
| 395 print('_____ switching %s to a new upstream' % self.relpath) | 396 print('_____ switching %s to a new upstream' % self.relpath) |
| 396 # Make sure it's clean | 397 # Make sure it's clean |
| 397 self._CheckClean(rev_str) | 398 self._CheckClean(rev_str) |
| 398 # Switch over to the new upstream | 399 # Switch over to the new upstream |
| 399 self._Run(['remote', 'set-url', 'origin', url], options) | 400 self._Run(['remote', 'set-url', 'origin', url], options) |
| 400 self._FetchAndReset(revision, file_list, options) | 401 self._FetchAndReset(revision, file_list, options) |
| 402 return_early = True | |
| 403 | |
| 404 # Need to do this in the normal path as well as in the post-remote-switch | |
| 405 # path. | |
| 406 self._PossiblySwitchCache(url, options) | |
| 407 | |
| 408 if return_early: | |
| 401 return | 409 return |
| 402 | 410 |
| 403 if not self._IsValidGitRepo(): | 411 if not self._IsValidGitRepo(): |
| 404 # .git directory is hosed for some reason, set it back up. | 412 # .git directory is hosed for some reason, set it back up. |
| 405 print('_____ %s/.git is corrupted, rebuilding' % self.relpath) | 413 print('_____ %s/.git is corrupted, rebuilding' % self.relpath) |
| 406 self._Run(['init'], options) | 414 self._Run(['init'], options) |
| 407 self._Run(['remote', 'set-url', 'origin', url], options) | 415 self._Run(['remote', 'set-url', 'origin', url], options) |
| 408 | 416 |
| 409 if not self._HasHead(): | 417 if not self._HasHead(): |
| 410 # Previous checkout was aborted before branches could be created in repo, | 418 # Previous checkout was aborted before branches could be created in repo, |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 @staticmethod | 736 @staticmethod |
| 729 def _NormalizeGitURL(url): | 737 def _NormalizeGitURL(url): |
| 730 '''Takes a git url, strips the scheme, and ensures it ends with '.git'.''' | 738 '''Takes a git url, strips the scheme, and ensures it ends with '.git'.''' |
| 731 idx = url.find('://') | 739 idx = url.find('://') |
| 732 if idx != -1: | 740 if idx != -1: |
| 733 url = url[idx+3:] | 741 url = url[idx+3:] |
| 734 if not url.endswith('.git'): | 742 if not url.endswith('.git'): |
| 735 url += '.git' | 743 url += '.git' |
| 736 return url | 744 return url |
| 737 | 745 |
| 746 def _PossiblySwitchCache(self, url, options): | |
| 747 """Handles switching a repo from with-cache to direct, or vice versa. | |
| 748 | |
| 749 When we go from direct to with-cache, the remote url changes from the | |
| 750 'real' url to the local file url (in cache_dir). Therefore, this function | |
| 751 assumes that |url| points to the correctly-switched-over local file url, if | |
| 752 we're in cache_mode. | |
| 753 | |
| 754 When we go from with-cache to direct, assume that the normal url-switching | |
| 755 code already flipped the remote over, and we just need to repack and break | |
| 756 the dependency to the cache. | |
| 757 """ | |
| 758 | |
| 759 altfile = os.path.join( | |
| 760 self.checkout_path, '.git', 'objects', 'info', 'alternates') | |
| 761 if self.cache_dir: | |
| 762 if not os.path.exists(altfile): | |
| 763 try: | |
| 764 with open(altfile, 'wa') as f: | |
| 765 f.write(os.path.join(url, 'objects')) | |
| 766 # pylint: disable=C0301 | |
| 767 # This dance is necessary according to emperical evidence, also at: | |
| 768 # http://lists-archives.com/git/713652-retrospectively-add-alternates- to-a-repository.html | |
| 769 self._Run(['repack', '-ad'], options) | |
| 770 self._Run(['repack', '-adl'], options) | |
| 771 except Exception: | |
| 772 # If something goes wrong, try to remove the altfile so we'll go down | |
| 773 # this path again next time. | |
| 774 try: | |
| 775 os.remove(altfile) | |
| 776 except Exception: | |
| 777 pass | |
| 778 raise | |
| 779 else: | |
| 780 if os.path.exists(altfile): | |
| 781 self._Run(['repack', '-a'], options) | |
| 782 os.remove(altfile) | |
| 783 | |
| 738 def _CreateOrUpdateCache(self, url, options): | 784 def _CreateOrUpdateCache(self, url, options): |
| 739 """Make a new git mirror or update existing mirror for |url|, and return the | 785 """Make a new git mirror or update existing mirror for |url|, and return the |
| 740 mirror URI to clone from. | 786 mirror URI to clone from. |
| 741 | 787 |
| 742 If no cache-dir is specified, just return |url| unchanged. | 788 If no cache-dir is specified, just return |url| unchanged. |
| 743 """ | 789 """ |
| 744 if not self.cache_dir: | 790 if not self.cache_dir: |
| 745 return url | 791 return url |
| 746 | 792 |
| 747 # Replace - with -- to avoid ambiguity. / with - to flatten folder structure | 793 # Replace - with -- to avoid ambiguity. / with - to flatten folder structure |
| 748 folder = os.path.join( | 794 folder = os.path.join( |
| 749 self.cache_dir, | 795 self.cache_dir, |
| 750 self._NormalizeGitURL(url).replace('-', '--').replace('/', '-')) | 796 self._NormalizeGitURL(url).replace('-', '--').replace('/', '-')) |
| 797 altfile = os.path.join(folder, 'objects', 'info', 'alternates') | |
| 798 | |
| 799 # If we're bringing an old cache up to date or cloning a new cache, and the | |
| 800 # existing repo is currently a direct clone, use its objects to help out | |
| 801 # the fetch here. | |
| 802 checkout_objects = os.path.join(self.checkout_path, '.git', 'objects') | |
| 803 checkout_altfile = os.path.join(checkout_objects, 'info', 'alternates') | |
| 804 use_reference = ( | |
| 805 os.path.exists(checkout_objects) and | |
| 806 not os.path.exists(checkout_altfile)) | |
| 751 | 807 |
| 752 v = ['-v'] if options.verbose else [] | 808 v = ['-v'] if options.verbose else [] |
| 753 filter_fn = lambda l: '[up to date]' not in l | 809 filter_fn = lambda l: '[up to date]' not in l |
| 754 with self.cache_locks[folder]: | 810 with self.cache_locks[folder]: |
| 755 gclient_utils.safe_makedirs(self.cache_dir) | 811 gclient_utils.safe_makedirs(self.cache_dir) |
| 756 if not os.path.exists(os.path.join(folder, 'config')): | 812 if not os.path.exists(os.path.join(folder, 'config')): |
| 757 gclient_utils.rmtree(folder) | 813 gclient_utils.rmtree(folder) |
| 758 self._Run(['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g', | 814 cmd = ['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g', |
| 759 '--progress', '--mirror', url, folder], | 815 '--progress', '--mirror'] |
| 816 | |
| 817 if use_reference: | |
| 818 cmd += ['--reference', os.path.abspath(self.checkout_path)] | |
| 819 | |
| 820 self._Run(cmd + [url, folder], | |
| 760 options, git_filter=True, filter_fn=filter_fn, | 821 options, git_filter=True, filter_fn=filter_fn, |
| 761 cwd=self.cache_dir) | 822 cwd=self.cache_dir) |
| 762 else: | 823 else: |
| 763 # For now, assert that host/path/to/repo.git is identical. We may want | 824 # For now, assert that host/path/to/repo.git is identical. We may want |
| 764 # to relax this restriction in the future to allow for smarter cache | 825 # to relax this restriction in the future to allow for smarter cache |
| 765 # repo update schemes (such as pulling the same repo, but from a | 826 # repo update schemes (such as pulling the same repo, but from a |
| 766 # different host). | 827 # different host). |
| 767 existing_url = self._Capture(['config', 'remote.origin.url'], | 828 existing_url = self._Capture(['config', 'remote.origin.url'], |
| 768 cwd=folder) | 829 cwd=folder) |
| 769 assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) | 830 assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) |
| 770 | 831 |
| 832 if use_reference: | |
| 833 with open(altfile) as f: | |
|
szager1
2013/07/17 21:43:06
open(altfile, 'w')
iannucci
2013/07/17 21:52:03
On 2013/07/17 21:43:06, szager1 wrote:
> open(altf
| |
| 834 f.write(os.path.abspath(checkout_objects)) | |
| 835 | |
| 771 # Would normally use `git remote update`, but it doesn't support | 836 # Would normally use `git remote update`, but it doesn't support |
| 772 # --progress, so use fetch instead. | 837 # --progress, so use fetch instead. |
| 773 self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'], | 838 self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'], |
| 774 options, git_filter=True, filter_fn=filter_fn, cwd=folder) | 839 options, git_filter=True, filter_fn=filter_fn, cwd=folder) |
| 840 | |
| 841 # If the clone has an object dependency on the existing repo, break it | |
| 842 # with repack and remove the linkage. | |
| 843 if os.path.exists(altfile): | |
| 844 self._Run(['repack', '-a'], options, cwd=folder) | |
| 845 os.remove(altfile) | |
| 775 return folder | 846 return folder |
| 776 | 847 |
| 777 def _Clone(self, revision, url, options): | 848 def _Clone(self, revision, url, options): |
| 778 """Clone a git repository from the given URL. | 849 """Clone a git repository from the given URL. |
| 779 | 850 |
| 780 Once we've cloned the repo, we checkout a working branch if the specified | 851 Once we've cloned the repo, we checkout a working branch if the specified |
| 781 revision is a branch head. If it is a tag or a specific commit, then we | 852 revision is a branch head. If it is a tag or a specific commit, then we |
| 782 leave HEAD detached as it makes future updates simpler -- in this case the | 853 leave HEAD detached as it makes future updates simpler -- in this case the |
| 783 user should first create a new branch or switch to an existing branch before | 854 user should first create a new branch or switch to an existing branch before |
| 784 making changes in the repo.""" | 855 making changes in the repo.""" |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1435 new_command.append('--force') | 1506 new_command.append('--force') |
| 1436 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1507 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1437 new_command.extend(('--accept', 'theirs-conflict')) | 1508 new_command.extend(('--accept', 'theirs-conflict')) |
| 1438 elif options.manually_grab_svn_rev: | 1509 elif options.manually_grab_svn_rev: |
| 1439 new_command.append('--force') | 1510 new_command.append('--force') |
| 1440 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1511 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1441 new_command.extend(('--accept', 'postpone')) | 1512 new_command.extend(('--accept', 'postpone')) |
| 1442 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1513 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1443 new_command.extend(('--accept', 'postpone')) | 1514 new_command.extend(('--accept', 'postpone')) |
| 1444 return new_command | 1515 return new_command |
| OLD | NEW |