vcssync: helper function to ensure a Git commit present locally (bug 1357597); r?glob draft
authorGregory Szorc <gps@mozilla.com>
Wed, 13 Sep 2017 13:04:09 -0700
changeset 11665 b0d4ede2218c3f5e9a8c4e8f7d1484f9fc46e536
parent 11664 a7db7a031df5bc7f18d66fd31f673eda1d829105
child 11666 3c202d92e09a571f0facb0abbedf3e9fdd3d8f42
push id1785
push usergszorc@mozilla.com
push dateFri, 15 Sep 2017 01:22:24 +0000
reviewersglob
bugs1357597
vcssync: helper function to ensure a Git commit present locally (bug 1357597); r?glob It allows us to perform a fetch without using remotes. This isn't a common practice in Git land and the syntax for `git fetch` is a bit wonky. So it is best to abstract it away. Plus, we can avoid network I/O if the given commit is present locally. MozReview-Commit-ID: 6pn2b5Iao9i
vcssync/mozvcssync/gitutil.py
--- a/vcssync/mozvcssync/gitutil.py
+++ b/vcssync/mozvcssync/gitutil.py
@@ -63,16 +63,41 @@ def setup_local_clone(path, url, git=Non
 
     if not os.path.exists(path):
         if not os.path.exists(os.path.dirname(path)):
             os.makedirs(os.path.dirname(path))
         logger.info('cloning %s to %s' % (url, path))
         git.cmd('clone', url, path)
 
 
+def ensure_revision_present(repo, revision, fetch_url, fetch_ref, local_ref):
+    """Ensure a Git revision is present in a repo.
+
+    Given a ``dulwich.repo.Repo`` and a ``revision``, ensure that revision is
+    present in the local repo.
+
+    If it is, this operation no-ops.
+
+    If the revision isn't present or isn't defined, ``fetch_ref`` will be
+    fetched from ``fetch_url`` and stored in ``local_ref``. After the fetch,
+    we verify that the requested revision is present locally (if defined).
+    """
+    if revision and revision in repo:
+        return
+
+    logger.warn('fetching %s from %s' % (fetch_ref, fetch_url))
+    subprocess.check_call(
+        [b'git', b'fetch', b'--no-tags', fetch_url,
+         b'+refs/heads/%s:%s' % (fetch_ref, local_ref)],
+        cwd=repo.path)
+
+    if revision and revision not in repo:
+        raise Exception('revision %s not found after fetch' % revision)
+
+
 def update_git_refs(repo, reason, *actions):
     """Update Git refs via reflog writes.
 
     Accepts a ``dulwich.repo.Repo``, a bytes ``reason`` describing why this
     was done, and 1 or more tuples describing the update to perform. Tuples
     have the form:
 
     ('update', ref, new_id, old_id)