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]:
121
126
raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
124
def import_git_objects(repo, mapping, object_iter, pb=None):
129
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
125
130
"""Import a set of git objects into a bzr repository.
127
132
:param repo: Bazaar repository
128
133
:param mapping: Mapping to use
134
:param num_objects: Number of objects.
129
135
:param object_iter: Iterator over Git objects.
131
137
# TODO: a more (memory-)efficient implementation of this
133
for i, o in enumerate(object_iter):
139
for i, (o, _) in enumerate(object_iter):
134
140
if pb is not None:
135
pb.update("fetching objects", i)
141
pb.update("fetching objects", i, num_objects)
136
142
objects[o.id] = o
202
208
if mapping is None:
203
209
mapping = self.source.get_mapping()
204
210
def progress(text):
205
pb.note("git: %s", text)
211
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
206
212
def determine_wants(heads):
207
213
if revision_id is None:
208
214
ret = heads.values()
210
ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
216
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
211
217
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
212
218
graph_walker = BzrFetchGraphWalker(self.target, mapping)
219
225
self.target.start_write_group()
221
import_git_objects(self.target, mapping,
222
iter(self.source.fetch_objects(determine_wants, graph_walker,
227
(num_objects, objects_iter) = \
228
self.source.fetch_objects(determine_wants,
229
graph_walker, progress)
230
import_git_objects(self.target, mapping, num_objects,
225
233
self.target.commit_write_group()
234
242
"""Be compatible with GitRepository."""
235
243
# FIXME: Also check target uses VersionedFile
236
244
return (isinstance(source, GitRepository) and
237
target.supports_rich_root())
245
target.supports_rich_root() and
246
not isinstance(target, GitRepository))
249
class InterGitRepository(InterRepository):
251
_matching_repo_format = GitFormat()
254
def _get_repo_format_to_test():
257
def copy_content(self, revision_id=None, pb=None):
258
"""See InterRepository.copy_content."""
259
self.fetch(revision_id, pb, find_ghosts=False)
261
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
264
mapping = self.source.get_mapping()
266
info("git: %s", text)
268
if revision_id is None:
269
determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
271
args = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
272
determine_wants = lambda x: [y for y in args if not y in r.object_store]
274
graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
275
f, commit = r.object_store.add_pack()
277
self.source._git.fetch_pack(path, determine_wants, graphwalker, f.write, progress)
285
def is_compatible(source, target):
286
"""Be compatible with GitRepository."""
287
return (isinstance(source, GitRepository) and
288
isinstance(target, GitRepository))