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]:
126
121
raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
129
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
124
def import_git_objects(repo, mapping, object_iter, pb=None):
130
125
"""Import a set of git objects into a bzr repository.
132
127
:param repo: Bazaar repository
133
128
:param mapping: Mapping to use
134
:param num_objects: Number of objects.
135
129
:param object_iter: Iterator over Git objects.
137
131
# TODO: a more (memory-)efficient implementation of this
139
for i, (o, _) in enumerate(object_iter):
133
for i, o in enumerate(object_iter):
140
134
if pb is not None:
141
pb.update("fetching objects", i, num_objects)
135
pb.update("fetching objects", i)
142
136
objects[o.id] = o
208
202
if mapping is None:
209
203
mapping = self.source.get_mapping()
210
204
def progress(text):
211
pb.update("git: %s" % text.rstrip("\r\n"), 0, 0)
205
pb.note("git: %s", text)
212
206
def determine_wants(heads):
213
207
if revision_id is None:
214
208
ret = heads.values()
216
ret = [mapping.revision_id_bzr_to_foreign(revision_id)[0]]
210
ret = [mapping.revision_id_bzr_to_foreign(revision_id)]
217
211
return [rev for rev in ret if not self.target.has_revision(mapping.revision_id_foreign_to_bzr(rev))]
218
212
graph_walker = BzrFetchGraphWalker(self.target, mapping)
225
219
self.target.start_write_group()
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,
221
import_git_objects(self.target, mapping,
222
iter(self.source.fetch_objects(determine_wants, graph_walker,
233
225
self.target.commit_write_group()
242
234
"""Be compatible with GitRepository."""
243
235
# FIXME: Also check target uses VersionedFile
244
236
return (isinstance(source, GitRepository) and
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))
237
target.supports_rich_root())