]> arthur.barton.de Git - bup.git/commitdiff
list_refs: add limit_to_heads and limit_to_tags
authorRob Browning <rlb@defaultvalue.org>
Thu, 3 Apr 2014 06:27:40 +0000 (01:27 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sun, 21 Jun 2015 19:00:26 +0000 (14:00 -0500)
Adjust git.py to use the limits when beneficial.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/git.py
lib/bup/t/tgit.py

index 2fc155f6a49ed8a81ef5b5580d7c19fa231334f4..65892e5b4a5632719860566e62faec64fc5545cb 100644 (file)
@@ -4,6 +4,7 @@ interact with the Git data structures.
 """
 import os, sys, zlib, time, subprocess, struct, stat, re, tempfile, glob
 from collections import namedtuple
+from itertools import islice
 
 from bup.helpers import *
 from bup import _helpers, path, midx, bloom, xstat
@@ -772,11 +773,21 @@ def _gitenv(repo_dir = None):
     return env
 
 
-def list_refs(refname = None, repo_dir = None):
-    """Generate a list of tuples in the form (refname,hash).
-    If a ref name is specified, list only this particular ref.
+def list_refs(refname=None, repo_dir=None,
+              limit_to_heads=False, limit_to_tags=False):
+    """Yield (refname, hash) tuples for all repository refs unless a ref
+    name is specified.  Given a ref name, only include tuples for that
+    particular ref.  The limits restrict the result items to
+    refs/heads or refs/tags.  If both limits are specified, items from
+    both sources will be included.
+
     """
-    argv = ['git', 'show-ref', '--']
+    argv = ['git', 'show-ref']
+    if limit_to_heads:
+        argv.append('--heads')
+    if limit_to_tags:
+        argv.append('--tags')
+    argv.append('--')
     if refname:
         argv += [refname]
     p = subprocess.Popen(argv,
@@ -794,7 +805,8 @@ def list_refs(refname = None, repo_dir = None):
 
 def read_ref(refname, repo_dir = None):
     """Get the commit id of the most recent commit made on a given ref."""
-    l = list(list_refs(refname, repo_dir))
+    refs = list_refs(refname, repo_dir=repo_dir, limit_to_heads=True)
+    l = tuple(islice(refs, 2))
     if l:
         assert(len(l) == 1)
         return l[0][1]
@@ -1153,11 +1165,10 @@ def cp(repo_dir=None):
 def tags(repo_dir = None):
     """Return a dictionary of all tags in the form {hash: [tag_names, ...]}."""
     tags = {}
-    for (n,c) in list_refs(repo_dir = repo_dir):
-        if n.startswith('refs/tags/'):
-            name = n[10:]
-            if not c in tags:
-                tags[c] = []
-
-            tags[c].append(name)  # more than one tag can point at 'c'
+    for n, c in list_refs(repo_dir = repo_dir, limit_to_tags=True):
+        assert(n.startswith('refs/tags/'))
+        name = n[10:]
+        if not c in tags:
+            tags[c] = []
+        tags[c].append(name)  # more than one tag can point at 'c'
     return tags
index 22530784227f62a5934a788422d9c69524340148..1fa1c1c6d3f2d759f9b8cf74e14f1455e4b8fb25 100644 (file)
@@ -1,10 +1,26 @@
 import struct, os, tempfile, time
+from subprocess import check_call
 from bup import git
 from bup.helpers import *
 from wvtest import *
 
-bup_tmp = os.path.realpath('../../../t/tmp')
-mkdirp(bup_tmp)
+
+top_dir = os.path.realpath('../../..')
+bup_exe = top_dir + '/bup'
+bup_tmp = top_dir + '/t/tmp'
+
+
+def exc(*cmd):
+    cmd_str = ' '.join(cmd)
+    print >> sys.stderr, cmd_str
+    check_call(cmd)
+
+
+def exo(*cmd):
+    cmd_str = ' '.join(cmd)
+    print >> sys.stderr, cmd_str
+    return readpipe(cmd)
+
 
 @wvtest
 def testmangle():
@@ -54,7 +70,7 @@ def testencode():
 def testpacks():
     initial_failures = wvfailure_count()
     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
-    os.environ['BUP_MAIN_EXE'] = bupmain = '../../../bup'
+    os.environ['BUP_MAIN_EXE'] = bup_exe
     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
     git.init_repo(bupdir)
     git.verbose = 1
@@ -100,7 +116,7 @@ def testpacks():
 def test_pack_name_lookup():
     initial_failures = wvfailure_count()
     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
-    os.environ['BUP_MAIN_EXE'] = bupmain = '../../../bup'
+    os.environ['BUP_MAIN_EXE'] = bup_exe
     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
     git.init_repo(bupdir)
     git.verbose = 1
@@ -129,7 +145,7 @@ def test_pack_name_lookup():
 def test_long_index():
     initial_failures = wvfailure_count()
     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
-    os.environ['BUP_MAIN_EXE'] = bupmain = '../../../bup'
+    os.environ['BUP_MAIN_EXE'] = bup_exe
     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
     git.init_repo(bupdir)
     w = git.PackWriter()
@@ -266,3 +282,56 @@ def test_commit_parsing():
         restore_env_var('GIT_COMMITTER_EMAIL', orig_committer_email)
     if wvfailure_count() == initial_failures:
         subprocess.call(['rm', '-rf', tmpdir])
+
+
+@wvtest
+def test_list_refs():
+    initial_failures = wvfailure_count()
+    tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
+    os.environ['BUP_MAIN_EXE'] = bup_exe
+    os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
+    src = tmpdir + '/src'
+    mkdirp(src)
+    with open(src + '/1', 'w+') as f:
+        print f, 'something'
+    with open(src + '/2', 'w+') as f:
+        print f, 'something else'
+    git.init_repo(bupdir)
+    emptyset = frozenset()
+    WVPASSEQ(frozenset(git.list_refs()), emptyset)
+    WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
+    WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), emptyset)
+    exc(bup_exe, 'index', src)
+    exc(bup_exe, 'save', '-n', 'src', '--strip', src)
+    src_hash = exo('git', '--git-dir', bupdir,
+                   'rev-parse', 'src').strip().split('\n')
+    assert(len(src_hash) == 1)
+    src_hash = src_hash[0].decode('hex')
+    tree_hash = exo('git', '--git-dir', bupdir,
+                   'rev-parse', 'src:').strip().split('\n')[0].decode('hex')
+    blob_hash = exo('git', '--git-dir', bupdir,
+                   'rev-parse', 'src:1').strip().split('\n')[0].decode('hex')
+    WVPASSEQ(frozenset(git.list_refs()),
+             frozenset([('refs/heads/src', src_hash)]))
+    WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
+    WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
+             frozenset([('refs/heads/src', src_hash)]))
+    exc('git', '--git-dir', bupdir, 'tag', 'commit-tag', 'src')
+    WVPASSEQ(frozenset(git.list_refs()),
+             frozenset([('refs/heads/src', src_hash),
+                        ('refs/tags/commit-tag', src_hash)]))
+    WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)),
+             frozenset([('refs/tags/commit-tag', src_hash)]))
+    WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
+             frozenset([('refs/heads/src', src_hash)]))
+    exc('git', '--git-dir', bupdir, 'tag', 'tree-tag', 'src:')
+    exc('git', '--git-dir', bupdir, 'tag', 'blob-tag', 'src:1')
+    os.unlink(bupdir + '/refs/heads/src')
+    expected_tags = frozenset([('refs/tags/commit-tag', src_hash),
+                               ('refs/tags/tree-tag', tree_hash),
+                               ('refs/tags/blob-tag', blob_hash)])
+    WVPASSEQ(frozenset(git.list_refs()), expected_tags)
+    WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), frozenset([]))
+    WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), expected_tags)
+    if wvfailure_count() == initial_failures:
+        subprocess.call(['rm', '-rf', tmpdir])