30
29
from bzrlib.plugins.git.remote import RemoteGitRepository
32
from dulwich.client import SimpleFetchGraphWalker
32
33
from dulwich.objects import Commit
34
35
from cStringIO import StringIO
37
38
class BzrFetchGraphWalker(object):
39
"""GraphWalker implementation that uses a Bazaar repository."""
39
41
def __init__(self, repository, mapping):
40
42
self.repository = repository
43
45
self.heads = set(repository.all_revision_ids())
49
return iter(self.next, None)
46
51
def ack(self, sha):
47
52
revid = self.mapping.revision_id_foreign_to_bzr(sha)
50
55
def remove(self, revid):
51
56
self.done.add(revid)
57
if revid in self.heads:
53
58
self.heads.remove(revid)
54
59
if revid in self.parents:
55
60
for p in self.parents[revid]:
129
134
:param object_iter: Iterator over Git objects.
131
136
# 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 objects.itervalues():
141
for o in object_iter.iterobjects():
142
142
if isinstance(o, Commit):
143
143
rev = mapping.import_commit(o)
144
root_trees[rev.revision_id] = objects[o.tree]
144
root_trees[rev.revision_id] = object_iter[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, lookup_object)
164
import_git_tree(repo, mapping, "", root_tree, inv, parent_invs,
165
166
repo.add_revision(rev.revision_id, rev, inv)
201
202
if mapping is None:
202
203
mapping = self.source.get_mapping()
203
204
def progress(text):
204
pb.note("git: %s", text)
205
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
205
206
def determine_wants(heads):
206
207
if revision_id is None:
207
208
ret = heads.values()
209
ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
210
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
210
211
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
211
212
graph_walker = BzrFetchGraphWalker(self.target, mapping)
218
219
self.target.start_write_group()
220
import_git_objects(self.target, mapping,
221
iter(self.source.fetch_objects(determine_wants, graph_walker,
221
objects_iter = self.source.fetch_objects(determine_wants,
222
graph_walker, progress)
223
import_git_objects(self.target, mapping, objects_iter, pb)
224
225
self.target.commit_write_group()
233
234
"""Be compatible with GitRepository."""
234
235
# FIXME: Also check target uses VersionedFile
235
236
return (isinstance(source, GitRepository) and
236
target.supports_rich_root())
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))