remote-hg: use notes to keep track of Hg revisions

Keep track of Mercurial revisions as Git notes under the 'refs/notes/hg' ref. This way, the user can easily see which Mercurial revision corresponds to certain Git commit. Unfortunately, there's no way to efficiently update the notes after doing an export (push), so they'll have to be updated when importing (fetching). Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Felipe Contreras committed Aug 29, 2013 at 17:29 UTC c587d655122a287a6796d493d176128f05374156
1 file changed +34 -1
contrib/remote-helpers/git-remote-hg
+34 -1
@@ -23,7 +23,11 @@ import subprocess
23 import urllib
24 import atexit
25 import urlparse, hashlib
26 +import time as ptime
27
28 +#
29 +# If you want to see Mercurial revisions as Git commit notes:
30 +# git config core.notesRef refs/notes/hg
31 #
32 # If you are not in hg-git-compat mode and want to disable the tracking of
33 # named branches:
@@ -126,6 +130,7 @@ class Marks:
130 self.rev_marks = {}
131 self.last_mark = 0
132 self.version = 0
133 + self.last_note = 0
134
135 def load(self):
136 if not os.path.exists(self.path):
@@ -137,6 +142,7 @@ class Marks:
142 self.marks = tmp['marks']
143 self.last_mark = tmp['last-mark']
144 self.version = tmp.get('version', 1)
145 + self.last_note = tmp.get('last-note', 0)
146
147 for rev, mark in self.marks.iteritems():
148 self.rev_marks[mark] = rev
@@ -150,7 +156,7 @@ class Marks:
156 self.version = 2
157
158 def dict(self):
153 - return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version }
159 + return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version, 'last-note' : self.last_note }
160
161 def store(self):
162 json.dump(self.dict(), open(self.path, 'w'))
@@ -512,6 +518,31 @@ def export_ref(repo, name, kind, head):
518 print "from :%u" % rev_to_mark(head)
519 print
520
521 + pending_revs = set(revs) - notes
522 + if pending_revs:
523 + note_mark = marks.next_mark()
524 + ref = "refs/notes/hg"
525 +
526 + print "commit %s" % ref
527 + print "mark :%d" % (note_mark)
528 + print "committer remote-hg <> %s" % (ptime.strftime('%s %z'))
529 + desc = "Notes for %s\n" % (name)
530 + print "data %d" % (len(desc))
531 + print desc
532 + if marks.last_note:
533 + print "from :%u" % marks.last_note
534 +
535 + for rev in pending_revs:
536 + notes.add(rev)
537 + c = repo[rev]
538 + print "N inline :%u" % rev_to_mark(c)
539 + msg = c.hex()
540 + print "data %d" % (len(msg))
541 + print msg
542 + print
543 +
544 + marks.last_note = note_mark
545 +
546 marks.set_tip(ename, head.hex())
547
548 def export_tag(repo, tag):
@@ -1113,6 +1144,7 @@ def main(args):
1144 global filenodes
1145 global fake_bmark, hg_version
1146 global dry_run
1147 + global notes, alias
1148
1149 alias = args[1]
1150 url = args[2]
@@ -1152,6 +1184,7 @@ def main(args):
1184 except:
1185 hg_version = None
1186 dry_run = False
1187 + notes = set()
1188
1189 repo = get_repo(url, alias)
1190 prefix = 'refs/hg/%s' % alias