1
# Copyright (C) 2007-2008 Canonical Ltd
1
# Copyright (C) 2007 Canonical Ltd
2
# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
3
# Copyright (C) 2008 John Carr
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
17
19
"""Converters, etc for going between Bazaar and Git ids."""
19
from bzrlib import errors, foreign
20
from bzrlib.inventory import ROOT_ID
26
from bzrlib.inventory import (
21
29
from bzrlib.foreign import (
34
from bzrlib.plugins.git.foreign import (
35
escape_commit_message,
27
39
def escape_file_id(file_id):
28
40
return file_id.replace('_', '__').replace(' ', '_s')
55
67
return bzr_rev_id[len(cls.revid_prefix)+1:], cls()
57
69
def generate_file_id(self, path):
70
# Git paths are just bytestrings
71
# We must just hope they are valid UTF-8..
72
assert isinstance(path, str)
60
return escape_file_id(path.encode('utf-8'))
75
return escape_file_id(path)
77
def parse_file_id(self, file_id):
78
if file_id == ROOT_ID:
80
return unescape_file_id(file_id)
62
82
def import_commit(self, commit):
63
83
"""Convert a git commit to a bzr revision.
68
88
raise AssertionError("Commit object can't be None")
69
89
rev = ForeignRevision(commit.id, self, self.revision_id_foreign_to_bzr(commit.id))
70
90
rev.parent_ids = tuple([self.revision_id_foreign_to_bzr(p) for p in commit.parents])
71
rev.message = commit.message.decode("utf-8", "replace")
72
rev.committer = str(commit.committer).decode("utf-8", "replace")
91
rev.message = escape_commit_message(commit.message.decode("utf-8", "replace"))
92
rev.committer = escape_commit_message(str(commit.committer).decode("utf-8", "replace"))
73
93
if commit.committer != commit.author:
74
rev.properties['author'] = str(commit.author).decode("utf-8", "replace")
94
rev.properties['author'] = escape_commit_message(str(commit.author).decode("utf-8", "replace"))
75
95
rev.timestamp = commit.commit_time
79
def export_commit(self, rev, tree_sha):
80
"""Turn a Bazaar revision in to a Git commit
82
:param tree_sha: HACK parameter (until we can retrieve this from the mapping)
83
:return dulwich.objects.Commit represent the revision:
85
from dulwich.objects import Commit
87
commit._tree = tree_sha
88
for p in rev.parent_ids:
89
commit._parents.append(self.revision_id_bzr_to_foreign(p))
90
commit._message = rev.message
91
commit._committer = rev.committer
92
if 'author' in rev.properties:
93
commit._author = rev.properties['author']
95
commit._author = rev.committer
96
commit._commit_time = long(rev.timestamp)
101
100
class BzrGitMappingv1(BzrGitMapping):
102
101
revid_prefix = 'git-v1'
141
140
foreign_git = ForeignGit()
142
141
default_mapping = BzrGitMappingv1()
144
def inventory_to_tree_and_blobs(repo, mapping, revision_id):
145
from dulwich.objects import Tree, Blob
146
from bzrlib.inventory import InventoryDirectory, InventoryFile
152
inv = repo.get_inventory(revision_id)
154
# stack contains the set of trees that we haven't
155
# finished constructing
156
for path, entry in inv.iter_entries():
157
while stack and not path.startswith(cur):
161
t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
162
cur, tree = stack.pop()
165
if type(entry) == InventoryDirectory:
166
stack.append((cur, tree))
170
if type(entry) == InventoryFile:
171
#FIXME: We can make potentially make this Lazy to avoid shaing lots of stuff
172
# and having all these objects in memory at once
174
blob._text = repo.texts.get_record_stream([(entry.file_id, entry.revision)], 'unordered', True).next().get_bytes_as('fulltext')
176
yield sha, blob, path
178
name = urlutils.basename(path).encode("utf-8")
179
mode = stat.S_IFREG | 0644
182
tree.add(mode, name, sha)
184
while len(stack) > 1:
188
t = (stat.S_IFDIR, urlutils.basename(cur).encode('UTF-8'), sha)
189
cur, tree = stack.pop()
193
yield tree.id, tree, cur
196
def revision_to_commit(rev, tree_sha, parent_lookup):
197
"""Turn a Bazaar revision in to a Git commit
199
:param tree_sha: Tree sha for the commit
200
:param parent_lookup: Function for looking up the GIT sha equiv of a bzr revision
201
:return dulwich.objects.Commit represent the revision:
203
from dulwich.objects import Commit
205
commit._tree = tree_sha
206
for p in rev.parent_ids:
207
git_p = parent_lookup(p)
208
if git_p is not None:
209
assert len(git_p) == 40, "unexpected length for %r" % git_p
210
commit._parents.append(git_p)
211
commit._message = rev.message.encode("utf-8")
212
commit._committer = rev.committer.encode("utf-8")
213
commit._author = rev.get_apparent_authors()[0].encode("utf-8")
214
commit._commit_time = long(rev.timestamp)