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

Side by Side Diff: gclient_scm.py

Issue 26234004: Consolidate subprocess retry logic into gclient_utils. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »
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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 274
275 def _FetchAndReset(self, revision, file_list, options): 275 def _FetchAndReset(self, revision, file_list, options):
276 """Equivalent to git fetch; git reset.""" 276 """Equivalent to git fetch; git reset."""
277 quiet = [] 277 quiet = []
278 if not options.verbose: 278 if not options.verbose:
279 quiet = ['--quiet'] 279 quiet = ['--quiet']
280 self._UpdateBranchHeads(options, fetch=False) 280 self._UpdateBranchHeads(options, fetch=False)
281 281
282 fetch_cmd = [ 282 fetch_cmd = [
283 '-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin', '--prune'] 283 '-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin', '--prune']
284 self._Run(fetch_cmd + quiet, options) 284 self._Run(fetch_cmd + quiet, options, retry=True)
285 self._Run(['reset', '--hard', revision] + quiet, options) 285 self._Run(['reset', '--hard', revision] + quiet, options)
286 self.UpdateSubmoduleConfig() 286 self.UpdateSubmoduleConfig()
287 if file_list is not None: 287 if file_list is not None:
288 files = self._Capture(['ls-files']).splitlines() 288 files = self._Capture(['ls-files']).splitlines()
289 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 289 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
290 290
291 def update(self, options, args, file_list): 291 def update(self, options, args, file_list):
292 """Runs git to update or transparently checkout the working copy. 292 """Runs git to update or transparently checkout the working copy.
293 293
294 All updated files will be appended to file_list. 294 All updated files will be appended to file_list.
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 if not os.path.exists(os.path.join(folder, 'config')): 795 if not os.path.exists(os.path.join(folder, 'config')):
796 gclient_utils.rmtree(folder) 796 gclient_utils.rmtree(folder)
797 cmd = ['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g', 797 cmd = ['clone'] + v + ['-c', 'core.deltaBaseCacheLimit=2g',
798 '--progress', '--mirror'] 798 '--progress', '--mirror']
799 799
800 if use_reference: 800 if use_reference:
801 cmd += ['--reference', os.path.abspath(self.checkout_path)] 801 cmd += ['--reference', os.path.abspath(self.checkout_path)]
802 802
803 self._Run(cmd + [url, folder], 803 self._Run(cmd + [url, folder],
804 options, git_filter=True, filter_fn=filter_fn, 804 options, git_filter=True, filter_fn=filter_fn,
805 cwd=self.cache_dir) 805 cwd=self.cache_dir, retry=True)
806 else: 806 else:
807 # For now, assert that host/path/to/repo.git is identical. We may want 807 # For now, assert that host/path/to/repo.git is identical. We may want
808 # to relax this restriction in the future to allow for smarter cache 808 # to relax this restriction in the future to allow for smarter cache
809 # repo update schemes (such as pulling the same repo, but from a 809 # repo update schemes (such as pulling the same repo, but from a
810 # different host). 810 # different host).
811 existing_url = self._Capture(['config', 'remote.origin.url'], 811 existing_url = self._Capture(['config', 'remote.origin.url'],
812 cwd=folder) 812 cwd=folder)
813 assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url) 813 assert self._NormalizeGitURL(existing_url) == self._NormalizeGitURL(url)
814 814
815 if use_reference: 815 if use_reference:
816 with open(altfile, 'w') as f: 816 with open(altfile, 'w') as f:
817 f.write(os.path.abspath(checkout_objects)) 817 f.write(os.path.abspath(checkout_objects))
818 818
819 # Would normally use `git remote update`, but it doesn't support 819 # Would normally use `git remote update`, but it doesn't support
820 # --progress, so use fetch instead. 820 # --progress, so use fetch instead.
821 self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'], 821 self._Run(['fetch'] + v + ['--multiple', '--progress', '--all'],
822 options, git_filter=True, filter_fn=filter_fn, cwd=folder) 822 options, git_filter=True, filter_fn=filter_fn, cwd=folder,
823 retry=True)
823 824
824 # If the clone has an object dependency on the existing repo, break it 825 # If the clone has an object dependency on the existing repo, break it
825 # with repack and remove the linkage. 826 # with repack and remove the linkage.
826 if os.path.exists(altfile): 827 if os.path.exists(altfile):
827 self._Run(['repack', '-a'], options, cwd=folder) 828 self._Run(['repack', '-a'], options, cwd=folder)
828 os.remove(altfile) 829 os.remove(altfile)
829 return folder 830 return folder
830 831
831 def _Clone(self, revision, url, options): 832 def _Clone(self, revision, url, options):
832 """Clone a git repository from the given URL. 833 """Clone a git repository from the given URL.
(...skipping 18 matching lines...) Expand all
851 clone_cmd.append(url) 852 clone_cmd.append(url)
852 # If the parent directory does not exist, Git clone on Windows will not 853 # If the parent directory does not exist, Git clone on Windows will not
853 # create it, so we need to do it manually. 854 # create it, so we need to do it manually.
854 parent_dir = os.path.dirname(self.checkout_path) 855 parent_dir = os.path.dirname(self.checkout_path)
855 gclient_utils.safe_makedirs(parent_dir) 856 gclient_utils.safe_makedirs(parent_dir)
856 tmp_dir = tempfile.mkdtemp( 857 tmp_dir = tempfile.mkdtemp(
857 prefix='_gclient_%s_' % os.path.basename(self.checkout_path), 858 prefix='_gclient_%s_' % os.path.basename(self.checkout_path),
858 dir=parent_dir) 859 dir=parent_dir)
859 try: 860 try:
860 clone_cmd.append(tmp_dir) 861 clone_cmd.append(tmp_dir)
861 for i in xrange(3): 862 self._Run(clone_cmd, options, cwd=self._root_dir, git_filter=True,
862 try: 863 retry=True)
863 self._Run(clone_cmd, options, cwd=self._root_dir, git_filter=True)
864 break
865 except subprocess2.CalledProcessError as e:
866 gclient_utils.rmtree(os.path.join(tmp_dir, '.git'))
867 if e.returncode != 128 or i == 2:
868 raise
869 print(str(e))
870 print('Retrying...')
871 gclient_utils.safe_makedirs(self.checkout_path) 864 gclient_utils.safe_makedirs(self.checkout_path)
872 gclient_utils.safe_rename(os.path.join(tmp_dir, '.git'), 865 gclient_utils.safe_rename(os.path.join(tmp_dir, '.git'),
873 os.path.join(self.checkout_path, '.git')) 866 os.path.join(self.checkout_path, '.git'))
874 finally: 867 finally:
875 if os.listdir(tmp_dir): 868 if os.listdir(tmp_dir):
876 print('\n_____ removing non-empty tmp dir %s' % tmp_dir) 869 print('\n_____ removing non-empty tmp dir %s' % tmp_dir)
877 gclient_utils.rmtree(tmp_dir) 870 gclient_utils.rmtree(tmp_dir)
878 if revision.startswith('refs/heads/'): 871 if revision.startswith('refs/heads/'):
879 self._Run( 872 self._Run(
880 ['checkout', '--quiet', revision.replace('refs/heads/', '')], options) 873 ['checkout', '--quiet', revision.replace('refs/heads/', '')], options)
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 1020
1028 def _Capture(self, args, cwd=None): 1021 def _Capture(self, args, cwd=None):
1029 return subprocess2.check_output( 1022 return subprocess2.check_output(
1030 ['git'] + args, 1023 ['git'] + args,
1031 stderr=subprocess2.VOID, 1024 stderr=subprocess2.VOID,
1032 cwd=cwd or self.checkout_path).strip() 1025 cwd=cwd or self.checkout_path).strip()
1033 1026
1034 def _UpdateBranchHeads(self, options, fetch=False): 1027 def _UpdateBranchHeads(self, options, fetch=False):
1035 """Adds, and optionally fetches, "branch-heads" refspecs if requested.""" 1028 """Adds, and optionally fetches, "branch-heads" refspecs if requested."""
1036 if hasattr(options, 'with_branch_heads') and options.with_branch_heads: 1029 if hasattr(options, 'with_branch_heads') and options.with_branch_heads:
1037 backoff_time = 5 1030 config_cmd = ['config', 'remote.origin.fetch',
1038 for _ in range(3): 1031 '+refs/branch-heads/*:refs/remotes/branch-heads/*',
1039 try: 1032 '^\\+refs/branch-heads/\\*:.*$']
1040 config_cmd = ['config', 'remote.origin.fetch', 1033 self._Run(config_cmd, options)
1041 '+refs/branch-heads/*:refs/remotes/branch-heads/*', 1034 if fetch:
1042 '^\\+refs/branch-heads/\\*:.*$'] 1035 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin']
1043 self._Run(config_cmd, options) 1036 if options.verbose:
1044 if fetch: 1037 fetch_cmd.append('--verbose')
1045 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin'] 1038 self._Run(fetch_cmd, options, retry=True)
1046 if options.verbose:
1047 fetch_cmd.append('--verbose')
1048 self._Run(fetch_cmd, options)
1049 break
1050 except subprocess2.CalledProcessError, e:
1051 print(str(e))
1052 print('Retrying in %.1f seconds...' % backoff_time)
1053 time.sleep(backoff_time)
1054 backoff_time *= 1.3
1055 1039
1056 def _Run(self, args, _options, git_filter=False, **kwargs): 1040 def _Run(self, args, _options, git_filter=False, **kwargs):
1057 kwargs.setdefault('cwd', self.checkout_path) 1041 kwargs.setdefault('cwd', self.checkout_path)
1058 if git_filter: 1042 if git_filter:
1059 kwargs['filter_fn'] = GitFilter(kwargs.get('filter_fn')) 1043 kwargs['filter_fn'] = GitFilter(kwargs.get('filter_fn'))
1060 kwargs.setdefault('print_stdout', False) 1044 kwargs.setdefault('print_stdout', False)
1061 # Don't prompt for passwords; just fail quickly and noisily. 1045 # Don't prompt for passwords; just fail quickly and noisily.
1062 # By default, git will use an interactive terminal prompt when a username/ 1046 # By default, git will use an interactive terminal prompt when a username/
1063 # password is needed. That shouldn't happen in the chromium workflow, 1047 # password is needed. That shouldn't happen in the chromium workflow,
1064 # and if it does, then gclient may hide the prompt in the midst of a flood 1048 # and if it does, then gclient may hide the prompt in the midst of a flood
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
1468 new_command.append('--force') 1452 new_command.append('--force')
1469 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1453 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1470 new_command.extend(('--accept', 'theirs-conflict')) 1454 new_command.extend(('--accept', 'theirs-conflict'))
1471 elif options.manually_grab_svn_rev: 1455 elif options.manually_grab_svn_rev:
1472 new_command.append('--force') 1456 new_command.append('--force')
1473 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1457 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1474 new_command.extend(('--accept', 'postpone')) 1458 new_command.extend(('--accept', 'postpone'))
1475 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1459 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1476 new_command.extend(('--accept', 'postpone')) 1460 new_command.extend(('--accept', 'postpone'))
1477 return new_command 1461 return new_command
OLDNEW
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698