Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: gclient_scm.py

Issue 180243006: Make gclient_scm.py use cache_dir (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Review fix, also deleted members changed test Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gclient.py ('k') | gclient_utils.py » ('j') | gclient_utils.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 command, self.__class__.__name__)) 140 command, self.__class__.__name__))
141 141
142 return getattr(self, command)(options, args, file_list) 142 return getattr(self, command)(options, args, file_list)
143 143
144 144
145 class GitWrapper(SCMWrapper): 145 class GitWrapper(SCMWrapper):
146 """Wrapper for Git""" 146 """Wrapper for Git"""
147 name = 'git' 147 name = 'git'
148 remote = 'origin' 148 remote = 'origin'
149 149
150 cache_dir = None 150 cache_dir = None
agable 2014/02/28 02:06:32 ...I don't see *any* code in this file that assign
Ryan Tseng 2014/02/28 02:22:50 Well 691 does, since it passes it into git cache p
agable 2014/02/28 02:38:24 No, 691 (thankfully) only uses self.cache_dir if i
151 # If a given cache is used in a solution more than once, prevent multiple 151 # If a given cache is used in a solution more than once, prevent multiple
152 # threads from updating it simultaneously. 152 # threads from updating it simultaneously.
153 cache_locks = collections.defaultdict(threading.Lock) 153 cache_locks = collections.defaultdict(threading.Lock)
agable 2014/02/28 02:06:32 This can go away, I believe.
Ryan Tseng 2014/02/28 02:22:50 Done.
154 154
155 def __init__(self, url=None, root_dir=None, relpath=None): 155 def __init__(self, url=None, root_dir=None, relpath=None):
156 """Removes 'git+' fake prefix from git URL.""" 156 """Removes 'git+' fake prefix from git URL."""
157 if url.startswith('git+http://') or url.startswith('git+https://'): 157 if url.startswith('git+http://') or url.startswith('git+https://'):
158 url = url[4:] 158 url = url[4:]
159 SCMWrapper.__init__(self, url, root_dir, relpath) 159 SCMWrapper.__init__(self, url, root_dir, relpath)
160 160
161 @staticmethod 161 @staticmethod
162 def BinaryExists(): 162 def BinaryExists():
163 """Returns true if the command exists.""" 163 """Returns true if the command exists."""
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 ['git', 'config', 'remote.%s.gclient-auto-fix-url' % self.remote], 345 ['git', 'config', 'remote.%s.gclient-auto-fix-url' % self.remote],
346 cwd=self.checkout_path).strip() != 'False'): 346 cwd=self.checkout_path).strip() != 'False'):
347 print('_____ switching %s to a new upstream' % self.relpath) 347 print('_____ switching %s to a new upstream' % self.relpath)
348 # Make sure it's clean 348 # Make sure it's clean
349 self._CheckClean(rev_str) 349 self._CheckClean(rev_str)
350 # Switch over to the new upstream 350 # Switch over to the new upstream
351 self._Run(['remote', 'set-url', self.remote, url], options) 351 self._Run(['remote', 'set-url', self.remote, url], options)
352 self._FetchAndReset(revision, file_list, options) 352 self._FetchAndReset(revision, file_list, options)
353 return_early = True 353 return_early = True
354 354
355 # Need to do this in the normal path as well as in the post-remote-switch
356 # path.
357 self._PossiblySwitchCache(url, options)
358
359 if return_early: 355 if return_early:
360 return self._Capture(['rev-parse', '--verify', 'HEAD']) 356 return self._Capture(['rev-parse', '--verify', 'HEAD'])
361 357
362 cur_branch = self._GetCurrentBranch() 358 cur_branch = self._GetCurrentBranch()
363 359
364 # Cases: 360 # Cases:
365 # 0) HEAD is detached. Probably from our initial clone. 361 # 0) HEAD is detached. Probably from our initial clone.
366 # - make sure HEAD is contained by a named ref, then update. 362 # - make sure HEAD is contained by a named ref, then update.
367 # Cases 1-4. HEAD is a branch. 363 # Cases 1-4. HEAD is a branch.
368 # 1) current branch is not tracking a remote branch (could be git-svn) 364 # 1) current branch is not tracking a remote branch (could be git-svn)
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 '#Initial_checkout' ) % rev) 670 '#Initial_checkout' ) % rev)
675 671
676 return sha1 672 return sha1
677 673
678 def FullUrlForRelativeUrl(self, url): 674 def FullUrlForRelativeUrl(self, url):
679 # Strip from last '/' 675 # Strip from last '/'
680 # Equivalent to unix basename 676 # Equivalent to unix basename
681 base_url = self.url 677 base_url = self.url
682 return base_url[:base_url.rfind('/')] + url 678 return base_url[:base_url.rfind('/')] + url
683 679
684 @staticmethod
685 def _NormalizeGitURL(url):
686 '''Takes a git url, strips the scheme, and ensures it ends with '.git'.'''
687 idx = url.find('://')
688 if idx != -1:
689 url = url[idx+3:]
690 if not url.endswith('.git'):
691 url += '.git'
692 return url
693
694 def _PossiblySwitchCache(self, url, options):
695 """Handles switching a repo from with-cache to direct, or vice versa.
696
697 When we go from direct to with-cache, the remote url changes from the
698 'real' url to the local file url (in cache_dir). Therefore, this function
699 assumes that |url| points to the correctly-switched-over local file url, if
700 we're in cache_mode.
701
702 When we go from with-cache to direct, assume that the normal url-switching
703 code already flipped the remote over, and we just need to repack and break
704 the dependency to the cache.
705 """
706
707 altfile = os.path.join(
708 self.checkout_path, '.git', 'objects', 'info', 'alternates')
709 if self.cache_dir:
710 if not os.path.exists(altfile):
711 try:
712 with open(altfile, 'w') as f:
713 f.write(os.path.join(url, 'objects'))
714 # pylint: disable=C0301
715 # This dance is necessary according to emperical evidence, also at:
716 # http://lists-archives.com/git/713652-retrospectively-add-alternates- to-a-repository.html
717 self._Run(['repack', '-ad'], options)
718 self._Run(['repack', '-adl'], options)
719 except Exception:
720 # If something goes wrong, try to remove the altfile so we'll go down
721 # this path again next time.
722 try:
723 os.remove(altfile)
724 except OSError as e:
725 print >> sys.stderr, "FAILED: os.remove('%s') -> %s" % (altfile, e)
726 raise
727 else:
728 if os.path.exists(altfile):
729 self._Run(['repack', '-a'], options)
730 os.remove(altfile)
731
732 def _CreateOrUpdateCache(self, url, options): 680 def _CreateOrUpdateCache(self, url, options):
733 """Make a new git mirror or update existing mirror for |url|, and return the 681 """Make a new git mirror or update existing mirror for |url|, and return the
734 mirror URI to clone from. 682 mirror URI to clone from.
735 683
736 If no cache-dir is specified, just return |url| unchanged. 684 If no cache-dir is specified, just return |url| unchanged.
737 """ 685 """
738 if not self.cache_dir: 686 if not self.cache_dir:
739 return url 687 return url
740
741 # Replace - with -- to avoid ambiguity. / with - to flatten folder structure
742 folder = os.path.join(
743 self.cache_dir,
744 self._NormalizeGitURL(url).replace('-', '--').replace('/', '-'))
745 altfile = os.path.join(folder, 'objects', 'info', 'alternates')
746
747 # If we're bringing an old cache up to date or cloning a new cache, and the
748 # existing repo is currently a direct clone, use its objects to help out
749 # the fetch here.
750 checkout_objects = os.path.join(self.checkout_path, '.git', 'objects')
751 checkout_altfile = os.path.join(checkout_objects, 'info', 'alternates')
752 use_reference = (
753 os.path.exists(checkout_objects) and
754 not os.path.exists(checkout_altfile))
755
756 v = ['-v'] if options.verbose else [] 688 v = ['-v'] if options.verbose else []
757 filter_fn = lambda l: '[up to date]' not in l 689 self._Run(['cache', 'populate'] + v +
758 with self.cache_locks[folder]: 690 ['--shallow', '--cache-dir', self.cache_dir, url],
759 gclient_utils.safe_makedirs(self.cache_dir) 691 options, cwd=self._root_dir, retry=True)
760 if not os.path.exists(os.path.join(folder, 'config')): 692 return self._Run(['cache', 'exists', '--cache-dir', self.cache_dir, url],
761 gclient_utils.rmtree(folder) 693 options).strip()
762 cmd = ['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g',
763 '--progress', '--bare']
764
765 if use_reference:
766 cmd += ['--reference', os.path.abspath(self.checkout_path)]
767
768 self._Run(cmd + [url, folder],
769 options, filter_fn=filter_fn, cwd=self.cache_dir, retry=True)
770 else:
771 # For now, assert that host/path/to/repo.git is identical. We may want
772 # to relax this restriction in the future to allow for smarter cache
773 # repo update schemes (such as pulling the same repo, but from a
774 # different host).
775 existing_url = self._Capture(['config', 'remote.%s.url' % self.remote],
776 cwd=folder)
777 assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url)
778
779 if use_reference:
780 with open(altfile, 'w') as f:
781 f.write(os.path.abspath(checkout_objects))
782
783 # Would normally use `git remote update`, but it doesn't support
784 # --progress, so use fetch instead.
785 self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'],
786 options, filter_fn=filter_fn, cwd=folder, retry=True)
787
788 # If the clone has an object dependency on the existing repo, break it
789 # with repack and remove the linkage.
790 if os.path.exists(altfile):
791 self._Run(['repack', '-a'], options, cwd=folder)
792 os.remove(altfile)
793 return folder
794 694
795 def _Clone(self, revision, url, options): 695 def _Clone(self, revision, url, options):
796 """Clone a git repository from the given URL. 696 """Clone a git repository from the given URL.
797 697
798 Once we've cloned the repo, we checkout a working branch if the specified 698 Once we've cloned the repo, we checkout a working branch if the specified
799 revision is a branch head. If it is a tag or a specific commit, then we 699 revision is a branch head. If it is a tag or a specific commit, then we
800 leave HEAD detached as it makes future updates simpler -- in this case the 700 leave HEAD detached as it makes future updates simpler -- in this case the
801 user should first create a new branch or switch to an existing branch before 701 user should first create a new branch or switch to an existing branch before
802 making changes in the repo.""" 702 making changes in the repo."""
803 if not options.verbose: 703 if not options.verbose:
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 # password prompt and simply allow git to fail noisily. The error 937 # password prompt and simply allow git to fail noisily. The error
1038 # message produced by git will be copied to gclient's output. 938 # message produced by git will be copied to gclient's output.
1039 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) 939 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy())
1040 env.setdefault('GIT_ASKPASS', 'true') 940 env.setdefault('GIT_ASKPASS', 'true')
1041 env.setdefault('SSH_ASKPASS', 'true') 941 env.setdefault('SSH_ASKPASS', 'true')
1042 else: 942 else:
1043 kwargs.setdefault('print_stdout', True) 943 kwargs.setdefault('print_stdout', True)
1044 stdout = kwargs.get('stdout', sys.stdout) 944 stdout = kwargs.get('stdout', sys.stdout)
1045 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % ( 945 stdout.write('\n________ running \'git %s\' in \'%s\'\n' % (
1046 ' '.join(args), kwargs['cwd'])) 946 ' '.join(args), kwargs['cwd']))
1047 gclient_utils.CheckCallAndFilter(['git'] + args, **kwargs) 947 return gclient_utils.CheckCallAndFilter(['git'] + args, **kwargs)
1048 948
1049 949
1050 class SVNWrapper(SCMWrapper): 950 class SVNWrapper(SCMWrapper):
1051 """ Wrapper for SVN """ 951 """ Wrapper for SVN """
1052 name = 'svn' 952 name = 'svn'
1053 953
1054 @staticmethod 954 @staticmethod
1055 def BinaryExists(): 955 def BinaryExists():
1056 """Returns true if the command exists.""" 956 """Returns true if the command exists."""
1057 try: 957 try:
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 new_command.append('--force') 1406 new_command.append('--force')
1507 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1407 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1508 new_command.extend(('--accept', 'theirs-conflict')) 1408 new_command.extend(('--accept', 'theirs-conflict'))
1509 elif options.manually_grab_svn_rev: 1409 elif options.manually_grab_svn_rev:
1510 new_command.append('--force') 1410 new_command.append('--force')
1511 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1411 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1512 new_command.extend(('--accept', 'postpone')) 1412 new_command.extend(('--accept', 'postpone'))
1513 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1413 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1514 new_command.extend(('--accept', 'postpone')) 1414 new_command.extend(('--accept', 'postpone'))
1515 return new_command 1415 return new_command
OLDNEW
« no previous file with comments | « gclient.py ('k') | gclient_utils.py » ('j') | gclient_utils.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698