summaryrefslogtreecommitdiff
path: root/contrib/remote-helpers/git-remote-hg
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/remote-helpers/git-remote-hg')
-rwxr-xr-xcontrib/remote-helpers/git-remote-hg94
1 files changed, 57 insertions, 37 deletions
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 85abbedb1c..c6026b9bed 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -23,8 +23,12 @@ import subprocess
import urllib
import atexit
import urlparse, hashlib
+import time as ptime
#
+# If you want to see Mercurial revisions as Git commit notes:
+# git config core.notesRef refs/notes/hg
+#
# If you are not in hg-git-compat mode and want to disable the tracking of
# named branches:
# git config --global remote-hg.track-branches false
@@ -126,6 +130,7 @@ class Marks:
self.rev_marks = {}
self.last_mark = 0
self.version = 0
+ self.last_note = 0
def load(self):
if not os.path.exists(self.path):
@@ -137,6 +142,7 @@ class Marks:
self.marks = tmp['marks']
self.last_mark = tmp['last-mark']
self.version = tmp.get('version', 1)
+ self.last_note = tmp.get('last-note', 0)
for rev, mark in self.marks.iteritems():
self.rev_marks[mark] = rev
@@ -150,7 +156,7 @@ class Marks:
self.version = 2
def dict(self):
- return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version }
+ return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version, 'last-note' : self.last_note }
def store(self):
json.dump(self.dict(), open(self.path, 'w'))
@@ -227,8 +233,6 @@ class Parser:
return sys.stdin.read(size)
def get_author(self):
- global bad_mail
-
ex = None
m = RAW_AUTHOR_RE.match(self.line)
if not m:
@@ -261,8 +265,6 @@ def fix_file_path(path):
return os.path.relpath(path, '/')
def export_files(files):
- global marks, filenodes
-
final = []
for f in files:
fid = node.hex(f.filenode())
@@ -344,8 +346,6 @@ def fixup_user_hg(user):
return (name, mail)
def fixup_user(user):
- global mode, bad_mail
-
if mode == 'git':
name, mail = fixup_user_git(user)
else:
@@ -374,7 +374,7 @@ def updatebookmarks(repo, peer):
bookmarks.write(repo)
def get_repo(url, alias):
- global dirname, peer
+ global peer
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
@@ -391,11 +391,24 @@ def get_repo(url, alias):
os.makedirs(dirname)
else:
shared_path = os.path.join(gitdir, 'hg')
- if not os.path.exists(shared_path):
- try:
- hg.clone(myui, {}, url, shared_path, update=False, pull=True)
- except:
- die('Repository error')
+
+ # check and upgrade old organization
+ hg_path = os.path.join(shared_path, '.hg')
+ if os.path.exists(shared_path) and not os.path.exists(hg_path):
+ repos = os.listdir(shared_path)
+ for x in repos:
+ local_hg = os.path.join(shared_path, x, 'clone', '.hg')
+ if not os.path.exists(local_hg):
+ continue
+ if not os.path.exists(hg_path):
+ shutil.move(local_hg, hg_path)
+ shutil.rmtree(os.path.join(shared_path, x, 'clone'))
+
+ # setup shared repo (if not there)
+ try:
+ hg.peer(myui, {}, shared_path, create=True)
+ except error.RepoError:
+ pass
if not os.path.exists(dirname):
os.makedirs(dirname)
@@ -416,16 +429,12 @@ def get_repo(url, alias):
return repo
def rev_to_mark(rev):
- global marks
return marks.from_rev(rev.hex())
def mark_to_rev(mark):
- global marks
return marks.to_rev(mark)
def export_ref(repo, name, kind, head):
- global prefix, marks, mode
-
ename = '%s/%s' % (kind, name)
try:
tip = marks.get_tip(ename)
@@ -522,6 +531,31 @@ def export_ref(repo, name, kind, head):
print "from :%u" % rev_to_mark(head)
print
+ pending_revs = set(revs) - notes
+ if pending_revs:
+ note_mark = marks.next_mark()
+ ref = "refs/notes/hg"
+
+ print "commit %s" % ref
+ print "mark :%d" % (note_mark)
+ print "committer remote-hg <> %s" % (ptime.strftime('%s %z'))
+ desc = "Notes for %s\n" % (name)
+ print "data %d" % (len(desc))
+ print desc
+ if marks.last_note:
+ print "from :%u" % marks.last_note
+
+ for rev in pending_revs:
+ notes.add(rev)
+ c = repo[rev]
+ print "N inline :%u" % rev_to_mark(c)
+ msg = c.hex()
+ print "data %d" % (len(msg))
+ print msg
+ print
+
+ marks.last_note = note_mark
+
marks.set_tip(ename, head.hex())
def export_tag(repo, tag):
@@ -537,12 +571,9 @@ def export_branch(repo, branch):
export_ref(repo, branch, 'branches', head)
def export_head(repo):
- global g_head
export_ref(repo, g_head[0], 'bookmarks', g_head[1])
def do_capabilities(parser):
- global prefix, dirname
-
print "import"
print "export"
print "refspec refs/heads/branches/*:%s/branches/*" % prefix
@@ -562,8 +593,6 @@ def branch_tip(branch):
return branches[branch][-1]
def get_branch_tip(repo, branch):
- global branches
-
heads = branches.get(hgref(branch), None)
if not heads:
return None
@@ -576,7 +605,7 @@ def get_branch_tip(repo, branch):
return heads[0]
def list_head(repo, cur):
- global g_head, bmarks, fake_bmark
+ global g_head, fake_bmark
if 'default' not in branches:
# empty repo
@@ -592,8 +621,6 @@ def list_head(repo, cur):
g_head = (head, node)
def do_list(parser):
- global branches, bmarks, track_branches
-
repo = parser.repo
for bmark, node in bookmarks.listbookmarks(repo).iteritems():
bmarks[bmark] = repo[node]
@@ -661,8 +688,6 @@ def do_import(parser):
print 'done'
def parse_blob(parser):
- global blob_marks
-
parser.next()
mark = parser.get_mark()
parser.next()
@@ -684,9 +709,6 @@ def c_style_unescape(string):
return string
def parse_commit(parser):
- global marks, blob_marks, parsed_refs
- global mode
-
from_mark = merge_mark = None
ref = parser[1]
@@ -725,7 +747,7 @@ def parse_commit(parser):
f = { 'deleted' : True }
else:
die('Unknown file command: %s' % line)
- path = c_style_unescape(path).decode('utf-8')
+ path = c_style_unescape(path)
files[path] = f
# only export the commits if we are on an internal proxy repo
@@ -805,8 +827,6 @@ def parse_commit(parser):
marks.new_mark(node, commit_mark)
def parse_reset(parser):
- global parsed_refs
-
ref = parser[1]
parser.next()
# ugh
@@ -999,8 +1019,6 @@ def check_tip(ref, kind, name, heads):
return tip in heads
def do_export(parser):
- global parsed_refs, bmarks, peer
-
p_bmarks = []
p_revs = {}
@@ -1072,7 +1090,7 @@ def do_export(parser):
author, msg = parsed_tags.get(tag, (None, None))
if mode == 'git':
if not msg:
- msg = 'Added tag %s for changeset %s' % (tag, node[:12]);
+ msg = 'Added tag %s for changeset %s' % (tag, node[:12])
tagnode, branch = write_tag(parser.repo, tag, node, msg, author)
p_revs[tagnode] = 'refs/heads/branches/' + gitref(branch)
else:
@@ -1130,7 +1148,7 @@ def do_option(parser):
def fix_path(alias, repo, orig_url):
url = urlparse.urlparse(orig_url, 'file')
- if url.scheme != 'file' or os.path.isabs(url.path):
+ if url.scheme != 'file' or os.path.isabs(os.path.expanduser(url.path)):
return
abs_url = urlparse.urljoin("%s/" % os.getcwd(), orig_url)
cmd = ['git', 'config', 'remote.%s.url' % alias, "hg::%s" % abs_url]
@@ -1145,6 +1163,7 @@ def main(args):
global filenodes
global fake_bmark, hg_version
global dry_run
+ global notes, alias
alias = args[1]
url = args[2]
@@ -1184,6 +1203,7 @@ def main(args):
except:
hg_version = None
dry_run = False
+ notes = set()
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias