Skip to content
Snippets Groups Projects
Commit 13a3513f authored by Siddharth Agarwal's avatar Siddharth Agarwal
Browse files

git_handler: support extracting metadata from Git extra fields

Git has a well-hidden notion of extra fields. They aren't accessible from the
CLI, but Dulwich can create them. They're a better place to store Mercurial's
extra metadata than the commit message.

An upcoming patch will switch hg-git to saving the metadata in the Git extra
fields. This commit:
(a) prepares for that
(b) extracts other Git extra fields so that commits from Git with such fields
    roundtrip correctly
parent 0a6e3f9a
No related branches found
No related tags found
No related merge requests found
......@@ -680,7 +680,8 @@
self.ui.debug(_("importing: %s\n") % commit.id)
(strip_message, hg_renames,
hg_branch, extra) = self.extract_hg_metadata(commit.message)
hg_branch, extra) = self.extract_hg_metadata(
commit.message, commit.extra)
gparents = map(self.map_hg_get, commit.parents)
......@@ -1244,7 +1245,7 @@
return convert[mode]
return ''
def extract_hg_metadata(self, message):
def extract_hg_metadata(self, message, git_extra):
split = message.split("\n--HG--\n", 1)
renames = {}
extra = {}
......@@ -1266,8 +1267,27 @@
if command == 'branch':
branch = data
if command == 'extra':
before, after = data.split(" : ", 1)
extra[before] = urllib.unquote(after)
k, v = data.split(" : ", 1)
extra[k] = urllib.unquote(v)
git_fn = 0
for field, data in git_extra:
if field.startswith('HG:'):
command = field[3:]
if command == 'rename':
before, after = data.split(':', 1)
renames[urllib.unquote(after)] = urllib.unquote(before)
elif command == 'extra':
k, v = data.split(':', 1)
extra[urllib.unquote(k)] = urllib.unquote(v)
else:
# preserve ordering in Git by using an incrementing integer for
# each field. Note that extra metadata in Git is an ordered list
# of pairs.
hg_field = 'GIT%d-%s' % (git_fn, field)
git_fn += 1
extra[urllib.quote(hg_field)] = urllib.quote(data)
return (message, renames, branch, extra)
def get_file(self, commit, f):
......
......@@ -66,7 +66,48 @@
extra : aaaaaaa : dataaaa
extra : zzzzzzz : datazzz
$ cd ../gitrepo
$ git checkout b1
Switched to branch 'b1'
$ commit_sha=$(git rev-parse HEAD)
$ tree_sha=$(git rev-parse HEAD^{tree})
There's no way to create a Git repo with extra metadata via the CLI. Dulwich
lets you do that, though.
>>> from dulwich.objects import Commit
>>> from dulwich.porcelain import open_repo
>>> repo = open_repo('.')
>>> c = Commit()
>>> c.author = 'test <test@example.org>'
>>> c.author_time = 0
>>> c.author_timezone = 0
>>> c.committer = c.author
>>> c.commit_time = 0
>>> c.commit_timezone = 0
>>> c.parents = ['$commit_sha']
>>> c.tree = '$tree_sha'
>>> c.message = 'extra commit\n'
>>> c.extra.extend([('zzz:zzz', 'data:zzz'), ('aaa:aaa', 'data:aaa'),
... ('HG:extra', 'hgaaa:dataaaa'),
... ('HG:extra', 'hgzzz:datazzz')])
>>> repo.object_store.add_object(c)
>>> repo.refs.set_if_equals('refs/heads/master', None, c.id)
True
$ git cat-file commit master
tree 1b773a2eb70f29397356f8069c285394835ff85a
parent ca11864bb2a84c3996929d42cf38bae3d0f7aae0
author test <test@example.org> 0 +0000
committer test <test@example.org> 0 +0000
zzz:zzz data:zzz
aaa:aaa data:aaa
HG:extra hgaaa:dataaaa
HG:extra hgzzz:datazzz
extra commit
$ cd ..
$ hg clone -q gitrepo hgrepo2
$ cd hgrepo2
$ hg log --graph --template "{rev} {node} {desc|firstline}\n{join(extras, ' ')}\n\n"
......@@ -69,8 +110,11 @@
$ cd ..
$ hg clone -q gitrepo hgrepo2
$ cd hgrepo2
$ hg log --graph --template "{rev} {node} {desc|firstline}\n{join(extras, ' ')}\n\n"
@ 3 f15e01c73845392d86a5ed10fb0753d09bca13d3
@ 4 f5fddc070b0648a5cddb98b43bbd527e98f4b4d2 extra commit
| GIT0-zzz%3Azzz=data%3Azzz GIT1-aaa%3Aaaa=data%3Aaaa branch=default hgaaa=dataaaa hgzzz=datazzz
|
o 3 f15e01c73845392d86a5ed10fb0753d09bca13d3
| aaaaaaa=dataaaa branch=default zzzzzzz=datazzz
|
o 2 dcec77c6ae3cff594c4435e5820bec4ec9e57440 b
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment