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

Unified Diff: gclient_scm.py

Issue 250523004: Added remote 'git' branch awareness to 'gclient' (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 6 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | testing_support/fake_repos.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gclient_scm.py
diff --git a/gclient_scm.py b/gclient_scm.py
index 491345e856920023b7168a89ba8c513727d981e2..fa26ecd14c980a5b7934010ceb4b46ca550fa662 100644
--- a/gclient_scm.py
+++ b/gclient_scm.py
@@ -276,16 +276,98 @@ class GitWrapper(SCMWrapper):
cwd=self.checkout_path,
filter_fn=GitDiffFilterer(self.relpath).Filter, print_func=self.Print)
+ def _ParseRevision(self, revision):
+ """Analyzes a revision string and determines what the repository-local
+ refspec is for that revision.
+
+ This function handles:
+ - Standard local revision paths (refs/heads, refs/remotes)
+ (e.g., refs/heads/master)
+ - Remote-relative mirrored revision paths (e.g., origin/master)
+ - Non-remote revision paths (anything else begining with 'refs/') are
+ assumed to be refs on our remote.
+ - Everything else (branches, commits)
+
+ Params:
+ revision: The revision string, fitting into one of the categories above,
+ to resolve
+
+ Return (dict): Refspec analysis dictionary including:
+ - 'revision' (str): The refspec to use to reference the revision in the
+ local repository (after it's been fetched).
+ - 'type' (str): The type of revision, one of ('branch', 'hash')
+ - 'mapped' (bool): If 'True', the revision is part of the default mapped
+ revision set ('refs/heads/*'); if 'False', it needs to be
+ explicitly fetched before it can be referenced at 'revision'.
+ - 'fetch_refspec' (str): The parameter to use to fetch this revision from
+ its origin.
+ """
+ result = {
+ 'revision': revision,
+ 'type': 'branch',
+ 'mapped': True,
+ 'fetch_refspec': revision,
+ }
+ #
+ # If 'revision' begins with some prefixes, chop them off to reference
+ # local refs.
+ for prefix, replacement in (
+ ('refs/heads/', None),
+ ('refs/remotes/%s/' % (self.remote), None),
+ ('%s/' % (self.remote), 'refs/heads/'),
+ ):
+ if revision.startswith(prefix):
+ local_revision = revision[len(prefix):]
+ if replacement is not None:
+ revision = revision.replace(prefix, replacement)
+
+ # Trim 'prefix' to make 'revision' relative to our standard
+ # 'refs/heads/*' fetch mapping.
+ result['revision'] = revision
+ result['fetch_refspec'] = local_revision
+ return result
+
+ # If 'revision' begins with 'refs/', treat it as an unmapped remote ref
+ if revision.startswith('refs/'):
+ result['fetch_refspec'] = '%s:%s' % (revision, revision)
+ result['mapped'] = False
+ return result
+
+ # Assume 'revision' is either a local branch or a commit
+ result['type'] = 'hash'
+ return result
+
+ def _Fetch(self, options, revision=None):
+ cfg = gclient_utils.DefaultIndexPackConfig()
+ fetch_cmd = cfg + ['fetch', self.remote]
+
+ if revision is not None:
+ refdict = self._ParseRevision(revision)
+ fetch_cmd.append(refdict['fetch_refspec'])
+
+ if not options.verbose:
+ fetch_cmd.append('--quiet')
+ fetch_cmd.append('--prune')
+ self._Run(fetch_cmd, options, retry=True)
+
+ def _FetchIfRemote(self, options, revision):
+ refdict = self._ParseRevision(revision)
+ if not refdict['mapped']:
+ self._Fetch(options, revision)
+
def _FetchAndReset(self, revision, file_list, options):
"""Equivalent to git fetch; git reset."""
- quiet = []
- if not options.verbose:
- quiet = ['--quiet']
self._UpdateBranchHeads(options, fetch=False)
- cfg = gclient_utils.DefaultIndexPackConfig(self.url)
- fetch_cmd = cfg + ['fetch', self.remote, '--prune']
- self._Run(fetch_cmd + quiet, options, retry=True)
+ # Fetch default fetch targets ('master'...)
+ self._Fetch(options)
+ # Fetch our specific revision from the remote, if it's not in the default
+ # fetch set.
+ self._FetchIfRemote(options, revision)
+
+ quiet = []
+ if not options.verbose:
+ quiet.append('--quiet')
self._Run(['reset', '--hard', revision] + quiet, options)
if file_list is not None:
files = self._Capture(['ls-files']).splitlines()
@@ -339,15 +421,9 @@ class GitWrapper(SCMWrapper):
url = self._CreateOrUpdateCache(url, options)
- if revision.startswith('refs/'):
- rev_type = "branch"
- elif revision.startswith(self.remote + '/'):
- # For compatibility with old naming, translate 'origin' to 'refs/heads'
- revision = revision.replace(self.remote + '/', 'refs/heads/')
- rev_type = "branch"
- else:
- # hash is also a tag, only make a distinction at checkout
- rev_type = "hash"
+ refdict = self._ParseRevision(revision)
+ revision = refdict['revision']
+ rev_type = refdict['type']
if (not os.path.exists(self.checkout_path) or
(os.path.isdir(self.checkout_path) and
@@ -786,9 +862,13 @@ class GitWrapper(SCMWrapper):
traceback.print_exc(file=self.out_fh)
raise
finally:
- if os.listdir(tmp_dir):
+ if os.path.exists(tmp_dir) and os.listdir(tmp_dir):
dnj (Google) 2014/04/24 19:30:44 A bit unrelated, but I did hit this case when 'lis
self.Print('_____ removing non-empty tmp dir %s' % tmp_dir)
gclient_utils.rmtree(tmp_dir)
+
+ # Fetch our specific revision
+ self._FetchIfRemote(options, revision)
+
if revision.startswith('refs/heads/'):
self._Run(
['checkout', '--quiet', revision.replace('refs/heads/', '')], options)
@@ -973,11 +1053,7 @@ class GitWrapper(SCMWrapper):
'^\\+refs/branch-heads/\\*:.*$']
self._Run(config_cmd, options)
if fetch:
- cfg = gclient_utils.DefaultIndexPackConfig(self.url)
- fetch_cmd = cfg + ['fetch', self.remote]
- if options.verbose:
- fetch_cmd.append('--verbose')
- self._Run(fetch_cmd, options, retry=True)
+ self._Fetch(options)
def _Run(self, args, options, **kwargs):
cwd = kwargs.setdefault('cwd', self.checkout_path)
« no previous file with comments | « no previous file | testing_support/fake_repos.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698