29
30
from bzrlib.plugins.git.remote import RemoteGitRepository
32
from dulwich.client import SimpleFetchGraphWalker
33
32
from dulwich.objects import Commit
35
34
from cStringIO import StringIO
38
37
class BzrFetchGraphWalker(object):
39
"""GraphWalker implementation that uses a Bazaar repository."""
41
39
def __init__(self, repository, mapping):
42
40
self.repository = repository
45
43
self.heads = set(repository.all_revision_ids())
49
return iter(self.next, None)
51
46
def ack(self, sha):
52
47
revid = self.mapping.revision_id_foreign_to_bzr(sha)
55
50
def remove(self, revid):
56
51
self.done.add(revid)
57
if revid in self.heads:
58
53
self.heads.remove(revid)
59
54
if revid in self.parents:
60
55
for p in self.parents[revid]:
134
129
:param object_iter: Iterator over Git objects.
136
131
# TODO: a more (memory-)efficient implementation of this
133
for i, o in enumerate(object_iter):
135
pb.update("fetching objects", i)
140
140
# Find and convert commit objects
141
for o in object_iter.iterobjects():
141
for o in objects.itervalues():
142
142
if isinstance(o, Commit):
143
143
rev = mapping.import_commit(o)
144
root_trees[rev.revision_id] = object_iter[o.tree]
144
root_trees[rev.revision_id] = objects[o.tree]
145
145
revisions[rev.revision_id] = rev
146
146
graph.append((rev.revision_id, rev.parent_ids))
147
147
# Order the revisions
157
157
inv = Inventory()
158
158
inv.revision_id = rev.revision_id
159
159
def lookup_object(sha):
160
if sha in object_iter:
161
return object_iter[sha]
162
162
return reconstruct_git_object(repo, mapping, sha)
163
163
parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
164
import_git_tree(repo, mapping, "", root_tree, inv, parent_invs,
164
import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, lookup_object)
166
165
repo.add_revision(rev.revision_id, rev, inv)
202
201
if mapping is None:
203
202
mapping = self.source.get_mapping()
204
203
def progress(text):
205
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
204
pb.note("git: %s", text)
206
205
def determine_wants(heads):
207
206
if revision_id is None:
208
207
ret = heads.values()
210
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
209
ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
211
210
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
212
211
graph_walker = BzrFetchGraphWalker(self.target, mapping)
219
218
self.target.start_write_group()
221
objects_iter = self.source.fetch_objects(determine_wants,
222
graph_walker, progress)
223
import_git_objects(self.target, mapping, objects_iter, pb)
220
import_git_objects(self.target, mapping,
221
iter(self.source.fetch_objects(determine_wants, graph_walker,
225
224
self.target.commit_write_group()
234
233
"""Be compatible with GitRepository."""
235
234
# FIXME: Also check target uses VersionedFile
236
235
return (isinstance(source, GitRepository) and
237
target.supports_rich_root() and
238
not isinstance(target, GitRepository))
241
class InterGitRepository(InterRepository):
243
_matching_repo_format = GitFormat()
246
def _get_repo_format_to_test():
249
def copy_content(self, revision_id=None, pb=None):
250
"""See InterRepository.copy_content."""
251
self.fetch(revision_id, pb, find_ghosts=False)
253
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
256
mapping = self.source.get_mapping()
258
info("git: %s", text)
260
if revision_id is None:
261
determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
263
args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
264
determine_wants = lambda x: [y for y in args if not y in r.object_store]
266
graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
267
f, commit = r.object_store.add_pack()
269
self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
277
def is_compatible(source, target):
278
"""Be compatible with GitRepository."""
279
return (isinstance(source, GitRepository) and
280
isinstance(target, GitRepository))
236
target.supports_rich_root())