From: Junio C Hamano Date: Fri, 1 Nov 2013 14:38:35 +0000 (-0700) Subject: Merge branch 'ap/remote-hg-unquote-cquote' X-Git-Tag: v1.8.5-rc1~19 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/583736c0bcf09adaa5621b142d8e43c22354041b?hp=-c Merge branch 'ap/remote-hg-unquote-cquote' A fast-import stream expresses a pathname with funny characters by quoting them in C style; remote-hg remote helper forgot to unquote such a path. * ap/remote-hg-unquote-cquote: remote-hg: unquote C-style paths when exporting --- 583736c0bcf09adaa5621b142d8e43c22354041b diff --combined contrib/remote-helpers/git-remote-hg index 92d994e470,85abbedb1c..3222afd9da --- a/contrib/remote-helpers/git-remote-hg +++ b/contrib/remote-helpers/git-remote-hg @@@ -23,11 -23,7 +23,11 @@@ import subproces 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: @@@ -130,7 -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): @@@ -142,7 -137,6 +142,7 @@@ 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 @@@ -156,7 -150,7 +156,7 @@@ 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')) @@@ -233,6 -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: @@@ -265,6 -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()) @@@ -346,6 -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 +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,24 -391,11 +391,24 @@@ 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) @@@ -429,12 -416,16 +429,12 @@@ 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) @@@ -531,31 -522,6 +531,31 @@@ 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): @@@ -571,9 -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 @@@ -593,6 -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 @@@ -605,7 -576,7 +605,7 @@@ 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 @@@ -621,6 -592,8 +621,6 @@@ 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] @@@ -688,6 -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() @@@ -703,7 -678,15 +703,12 @@@ def get_merge_files(repo, p1, p2, files f = { 'ctx' : repo[p1][e] } files[e] = f + def c_style_unescape(string): + if string[0] == string[-1] == '"': + return string.decode('string-escape')[1:-1] + return string + def parse_commit(parser): - global marks, blob_marks, parsed_refs - global mode - from_mark = merge_mark = None ref = parser[1] @@@ -742,6 -725,7 +747,7 @@@ f = { 'deleted' : True } else: die('Unknown file command: %s' % line) + path = c_style_unescape(path).decode('utf-8') files[path] = f # only export the commits if we are on an internal proxy repo @@@ -821,6 -805,8 +827,6 @@@ marks.new_mark(node, commit_mark) def parse_reset(parser): - global parsed_refs - ref = parser[1] parser.next() # ugh @@@ -1013,6 -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 = {} @@@ -1084,7 -1072,7 +1090,7 @@@ 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: @@@ -1142,7 -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] @@@ -1157,7 -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] @@@ -1197,7 -1184,6 +1203,7 @@@ except: hg_version = None dry_run = False + notes = set() repo = get_repo(url, alias) prefix = 'refs/hg/%s' % alias