216
213
stop_revids.append(revid)
218
215
graph = self.source.get_graph()
219
pb = ui.ui_factory.nested_progress_bar()
216
with ui.ui_factory.nested_progress_bar() as pb:
221
217
while stop_revids:
222
218
new_stop_revids = []
223
219
for revid in stop_revids:
228
224
new_stop_revids.append(revid)
229
225
stop_revids = set()
230
226
parent_map = graph.get_parent_map(new_stop_revids)
231
for parent_revids in viewvalues(parent_map):
227
for parent_revids in parent_map.values():
232
228
stop_revids.update(parent_revids)
233
229
pb.update("determining revisions to fetch", len(missing))
236
230
return graph.iter_topo_order(missing)
238
232
def _get_target_bzr_refs(self):
273
267
for (git_sha, bzr_revid) in new_refs.values()
274
268
if git_sha is None or not git_sha.startswith(SYMREF)],
276
for name, (gitid, revid) in viewitems(new_refs):
270
for name, (gitid, revid) in new_refs.items():
277
271
if gitid is None:
279
273
gitid = revidmap[revid][0]
302
296
with self.source_store.lock_read():
303
297
todo = list(self.missing_revisions(revs))[:limit]
305
pb = ui.ui_factory.nested_progress_bar()
299
with ui.ui_factory.nested_progress_bar() as pb:
307
300
object_generator = MissingObjectsIterator(
308
301
self.source_store, self.source, pb)
309
302
for (old_revid, git_sha) in object_generator.import_revisions(
317
310
self.mapping.revision_id_bzr_to_foreign(old_revid)
318
311
except InvalidRevisionId:
319
refname = self.mapping.revid_as_refname(old_revid)
320
self.target_refs[refname] = git_sha
321
313
revidmap[old_revid] = (git_sha, new_revid)
322
314
self.target_store.add_objects(object_generator)
327
317
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
328
fetch_spec=None, mapped_refs=None):
318
fetch_spec=None, mapped_refs=None, lossy=False):
329
319
if mapped_refs is not None:
330
320
stop_revisions = mapped_refs
331
321
elif revision_id is not None:
342
332
for revid in self.source.all_revision_ids()]
343
333
self._warn_slow()
345
self.fetch_objects(stop_revisions, lossy=False)
335
revidmap = self.fetch_objects(stop_revisions, lossy=lossy)
346
336
except NoPushSupport:
347
337
raise NoRoundtrippingSupport(self.source, self.target)
338
return FetchResult(revidmap)
350
341
def is_compatible(source, target):
365
356
def git_update_refs(old_refs):
367
358
self.old_refs = {
368
k: (v, None) for (k, v) in viewitems(old_refs)}
359
k: (v, None) for (k, v) in old_refs.items()}
369
360
new_refs = update_refs(self.old_refs)
370
for name, (gitid, revid) in viewitems(new_refs):
361
for name, (gitid, revid) in new_refs.items():
371
362
if gitid is None:
372
363
git_sha = self.source_store._lookup_revision_sha1(revid)
373
364
gitid = unpeel_map.re_unpeel_tag(
381
372
self._warn_slow()
382
373
with self.source_store.lock_read():
383
new_refs = self.target.send_pack(
374
result = self.target.send_pack(
384
375
git_update_refs, self.source_store.generate_lossy_pack_data)
376
if result is not None and not isinstance(result, dict):
377
for ref, error in result.ref_status.items():
379
raise RemoteGitError(
380
'unable to update ref %r: %s' % (ref, error))
381
new_refs = result.refs
382
else: # dulwich < 0.20.3
385
384
# FIXME: revidmap?
386
385
return revidmap, self.old_refs, new_refs
413
412
def _target_has_shas(self, shas):
414
413
raise NotImplementedError(self._target_has_shas)
416
def get_determine_wants_heads(self, wants, include_tags=False):
415
def get_determine_wants_heads(self, wants, include_tags=False, tag_selector=None):
417
416
wants = set(wants)
419
418
def determine_wants(refs):
420
419
unpeel_lookup = {}
421
for k, v in viewitems(refs):
420
for k, v in refs.items():
422
421
if k.endswith(ANNOTATED_TAG_SUFFIX):
423
422
unpeel_lookup[v] = refs[k[:-len(ANNOTATED_TAG_SUFFIX)]]
424
423
potential = set([unpeel_lookup.get(w, w) for w in wants])
426
for k, sha in viewitems(refs):
425
for k, sha in refs.items():
427
426
if k.endswith(ANNOTATED_TAG_SUFFIX):
429
tag_name = ref_to_tag_name(k)
432
if tag_selector and not tag_selector(tag_name):
431
434
if sha == ZERO_SHA:
462
465
if if_present_ids is not None:
463
466
todo.update(if_present_ids)
464
467
result_set = todo.difference(self.target.all_revision_ids())
465
result_parents = set(itertools.chain.from_iterable(viewvalues(
466
self.source.get_graph().get_parent_map(result_set))))
468
result_parents = set(itertools.chain.from_iterable(
469
self.source.get_graph().get_parent_map(result_set).values()))
467
470
included_keys = result_set.intersection(result_parents)
468
471
start_keys = result_set.difference(included_keys)
469
472
exclude_keys = result_parents.difference(result_set)
489
492
def determine_wants_all(self, refs):
490
493
potential = set()
491
for k, v in viewitems(refs):
494
for k, v in refs.items():
492
495
# For non-git target repositories, only worry about peeled
493
496
if v == ZERO_SHA:
513
516
raise NotImplementedError(self.fetch_objects)
515
def get_determine_wants_revids(self, revids, include_tags=False):
518
def get_determine_wants_revids(self, revids, include_tags=False, tag_selector=None):
517
520
for revid in set(revids):
518
521
if self.target.has_revision(revid):
520
523
git_sha, mapping = self.source.lookup_bzr_revision_id(revid)
521
524
wants.add(git_sha)
522
return self.get_determine_wants_heads(wants, include_tags=include_tags)
525
return self.get_determine_wants_heads(
526
wants, include_tags=include_tags, tag_selector=tag_selector)
524
528
def fetch(self, revision_id=None, find_ghosts=False,
525
mapping=None, fetch_spec=None, include_tags=False):
529
mapping=None, fetch_spec=None, include_tags=False, lossy=False):
526
530
if mapping is None:
527
531
mapping = self.source.get_mapping()
528
532
if revision_id is not None:
544
548
determine_wants = self.determine_wants_all
546
(pack_hint, _, remote_refs) = self.fetch_objects(determine_wants,
550
(pack_hint, _, remote_refs) = self.fetch_objects(
551
determine_wants, mapping, lossy=lossy)
548
552
if pack_hint is not None and self.target._format.pack_compresses:
549
553
self.target.pack(hint=pack_hint)
554
result = FetchResult()
555
result.refs = remote_refs
553
559
class InterRemoteGitNonGitRepository(InterGitNonGitRepository):
559
565
all_revs = self.target.all_revision_ids()
560
566
parent_map = self.target.get_parent_map(all_revs)
561
567
all_parents = set()
562
for values in viewvalues(parent_map):
568
for values in parent_map.values():
563
569
all_parents.update(values)
564
570
return set(all_revs) - all_parents
574
580
lambda sha: store[sha].parents)
575
581
wants_recorder = DetermineWantsRecorder(determine_wants)
577
pb = ui.ui_factory.nested_progress_bar()
583
with ui.ui_factory.nested_progress_bar() as pb:
579
584
objects_iter = self.source.fetch_objects(
580
585
wants_recorder, graph_walker, store.get_raw)
581
586
trace.mutter("Importing %d new revisions",
584
589
self.target, mapping, objects_iter, store,
585
590
wants_recorder.wants, pb, limit)
586
591
return (pack_hint, last_rev, wants_recorder.remote_refs)
591
594
def is_compatible(source, target):
610
613
self._warn_slow()
611
614
remote_refs = self.source.controldir.get_refs_container().as_dict()
612
615
wants = determine_wants(remote_refs)
613
pb = ui.ui_factory.nested_progress_bar()
614
616
target_git_object_retriever = get_object_store(self.target, mapping)
617
with ui.ui_factory.nested_progress_bar() as pb:
616
618
target_git_object_retriever.lock_write()
618
620
(pack_hint, last_rev) = import_git_objects(
650
650
def determine_wants(heads):
651
651
old_refs = dict([(k, (v, None))
652
for (k, v) in viewitems(heads.as_dict())])
652
for (k, v) in heads.as_dict().items()])
653
653
new_refs = update_refs(old_refs)
654
654
ref_changes.update(new_refs)
655
return [sha1 for (sha1, bzr_revid) in viewvalues(new_refs)]
655
return [sha1 for (sha1, bzr_revid) in new_refs.values()]
656
656
self.fetch_objects(determine_wants, lossy=lossy)
657
for k, (git_sha, bzr_revid) in viewitems(ref_changes):
657
for k, (git_sha, bzr_revid) in ref_changes.items():
658
658
self.target._git.refs[k] = git_sha
659
659
new_refs = self.target.controldir.get_refs_container()
660
660
return None, old_refs, new_refs
670
670
def fetch(self, revision_id=None, find_ghosts=False,
671
671
mapping=None, fetch_spec=None, branches=None, limit=None,
672
include_tags=False, lossy=False):
673
673
if mapping is None:
674
674
mapping = self.source.get_mapping()
675
675
if revision_id is not None:
683
683
"Unsupported search result type %s" % recipe[0])
685
685
if branches is not None:
686
def determine_wants(refs):
688
for name, value in viewitems(refs):
689
if value == ZERO_SHA:
692
if name in branches or (include_tags and is_tag(name)):
686
determine_wants = self.get_determine_wants_branches(
687
branches, include_tags=include_tags)
695
688
elif fetch_spec is None and revision_id is None:
696
689
determine_wants = self.determine_wants_all
698
691
determine_wants = self.get_determine_wants_revids(
699
692
args, include_tags=include_tags)
700
693
wants_recorder = DetermineWantsRecorder(determine_wants)
701
self.fetch_objects(wants_recorder, mapping, limit=limit)
702
return wants_recorder.remote_refs
694
self.fetch_objects(wants_recorder, mapping, limit=limit, lossy=lossy)
695
result = FetchResult()
696
result.refs = wants_recorder.remote_refs
704
def get_determine_wants_revids(self, revids, include_tags=False):
699
def get_determine_wants_revids(self, revids, include_tags=False, tag_selector=None):
706
701
for revid in set(revids):
707
702
if revid == NULL_REVISION:
709
704
git_sha, mapping = self.source.lookup_bzr_revision_id(revid)
710
705
wants.add(git_sha)
711
return self.get_determine_wants_heads(wants, include_tags=include_tags)
706
return self.get_determine_wants_heads(wants, include_tags=include_tags, tag_selector=tag_selector)
708
def get_determine_wants_branches(self, branches, include_tags=False):
709
def determine_wants(refs):
711
for name, value in refs.items():
712
if value == ZERO_SHA:
715
if name.endswith(ANNOTATED_TAG_SUFFIX):
718
if name in branches or (include_tags and is_tag(name)):
721
return determine_wants
713
723
def determine_wants_all(self, refs):
714
724
potential = set([
726
736
if limit is not None:
727
737
raise FetchLimitUnsupported(self)
728
738
from .remote import DefaultProgressReporter
729
pb = ui.ui_factory.nested_progress_bar()
730
progress = DefaultProgressReporter(pb).progress
739
with ui.ui_factory.nested_progress_bar() as pb:
740
progress = DefaultProgressReporter(pb).progress
732
741
refs = self.source._git.fetch(
733
742
self.target._git, determine_wants,
734
743
progress=progress)
737
744
return (None, None, refs)
781
788
"""Be compatible with GitRepository."""
782
789
return (isinstance(source, RemoteGitRepository) and
783
790
isinstance(target, LocalGitRepository))
794
class InterLocalGitRemoteGitRepository(InterToGitRepository):
796
def fetch_refs(self, update_refs, lossy=False, overwrite=False):
797
"""Import the gist of the ancestry of a particular revision."""
799
raise LossyPushToSameVCS(self.source, self.target)
801
def git_update_refs(old_refs):
804
k: (v, None) for (k, v) in viewitems(old_refs)}
805
new_refs = update_refs(self.old_refs)
806
for name, (gitid, revid) in viewitems(new_refs):
808
gitid = self.source_store._lookup_revision_sha1(revid)
810
if remote_divergence(
811
old_refs.get(name), gitid, self.source_store):
812
raise DivergedBranches(self.source, self.target)
815
new_refs = self.target.send_pack(
817
self.source._git.generate_pack_data)
818
return None, self.old_refs, new_refs
821
def is_compatible(source, target):
822
return (isinstance(source, LocalGitRepository) and
823
isinstance(target, RemoteGitRepository))