changeset 367:699088d9dd9f

hgrepo: completely rework handing of remote refs marking Previously, we appended to .hg/localtags on every pull. This meant that we never deleted refs that disappeared on the remote server, and the file length grew without bound. Now we use our own file (.hg/git-remote-refs) and we do prune refs that disappear from the remote server.
author Augie Fackler <durin42@gmail.com>
date Mon, 20 Dec 2010 22:37:07 -0600
parents 3627b97e775c
children ae78f94f64fd
files hggit/git_handler.py hggit/hgrepo.py
diffstat 2 files changed, 33 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/hggit/git_handler.py
+++ b/hggit/git_handler.py
@@ -747,26 +747,34 @@
                          ' bookmarks enabled?\n'))
 
     def update_remote_branches(self, remote_name, refs):
-        def _set_hg_tag(head, sha):
-            # refs contains all the refs in the server, not just the ones
-            # we are pulling
-            if sha not in self.git.object_store:
-                return
-            hgsha = bin(self.map_hg_get(sha))
-            tag = '%s/%s' % (remote_name, head)
-            self.repo.tag(tag, hgsha, '', True, None, None)
-
+        tagfile = self.repo.join(os.path.join('git-remote-refs'))
+        tags = self.repo.gitrefs()
+        # since we re-write all refs for this remote each time, prune
+        # all entries matching this remote from our tags list now so
+        # that we avoid any stale refs hanging around forever
+        for t in list(tags):
+            if t.startswith(remote_name + '/'):
+                del tags[t]
+        store = self.git.object_store
         for ref_name, sha in refs.iteritems():
             if ref_name.startswith('refs/heads'):
+                if sha not in store:
+                    continue
+                hgsha = self.map_hg_get(sha)
                 head = ref_name[11:]
-                _set_hg_tag(head, sha)
-
+                tags['/'.join((remote_name, head))] = hgsha
+                # TODO(durin42): what is this doing?
                 new_ref = 'refs/remotes/%s/%s' % (remote_name, head)
                 self.git.refs[new_ref] = sha
             elif (ref_name.startswith('refs/tags')
                   and not ref_name.endswith('^{}')):
                 self.git.refs[ref_name] = sha
 
+        tf = open(tagfile, 'wb')
+        for tag, node in tags.iteritems():
+            tf.write('%s %s\n' % (node, tag))
+        tf.close()
+
 
     ## UTILITY FUNCTIONS
 
--- a/hggit/hgrepo.py
+++ b/hggit/hgrepo.py
@@ -1,3 +1,5 @@
+import os
+
 from mercurial.node import bin
 
 from git_handler import GitHandler
@@ -48,11 +50,21 @@
 
             return (tags, tagtypes)
 
+        def gitrefs(self):
+            tagfile = self.join(os.path.join('git-remote-refs'))
+            if os.path.exists(tagfile):
+                tf = open(tagfile, 'rb')
+                tagdata = tf.read().split('\n')
+                td = [line.split(' ', 1) for line in tagdata if line]
+                return dict([(name, bin(sha)) for sha, name in td])
+            return {}
+
         def tags(self):
             if not hasattr(self, 'tagscache'):
                 # mercurial 1.4
-                return super(hgrepo, self).tags()
-
+                tmp = super(hgrepo, self).tags()
+                tmp.update(self.gitrefs())
+                return tmp
             if self.tagscache:
                 return self.tagscache