126
125
raise NotImplementedError(self.fetch_refs)
128
127
def search_missing_revision_ids(self,
129
find_ghosts=True, revision_ids=None, if_present_ids=None,
128
find_ghosts=True, revision_ids=None,
129
if_present_ids=None, limit=None):
131
130
if limit is not None:
132
131
raise FetchLimitUnsupported(self)
146
145
raise NoSuchRevision(revid, self.source)
147
146
git_shas.append(git_sha)
148
walker = Walker(self.source_store,
149
include=git_shas, exclude=[
150
151
sha for sha in self.target.controldir.get_refs_container().as_dict().values()
151
152
if sha != ZERO_SHA])
152
153
missing_revids = set()
153
154
for entry in walker:
154
for (kind, type_data) in self.source_store.lookup_git_sha(entry.commit.id):
155
for (kind, type_data) in self.source_store.lookup_git_sha(
155
157
if kind == "commit":
156
158
missing_revids.add(type_data[0])
157
159
return self.source.revision_ids_to_search_result(missing_revids)
219
221
new_stop_revids = []
220
222
for revid in stop_revids:
221
223
sha1 = revid_sha_map.get(revid)
222
if (not revid in missing and
223
self._revision_needs_fetching(sha1, revid)):
224
if (revid not in missing and
225
self._revision_needs_fetching(sha1, revid)):
224
226
missing.add(revid)
225
227
new_stop_revids.append(revid)
226
228
stop_revids = set()
248
249
if not v.startswith(SYMREF):
250
for (kind, type_data) in self.source_store.lookup_git_sha(v):
251
if kind == "commit" and self.source.has_revision(type_data[0]):
251
for (kind, type_data) in self.source_store.lookup_git_sha(
253
if kind == "commit" and self.source.has_revision(
252
255
revid = type_data[0]
259
262
def fetch_refs(self, update_refs, lossy, overwrite=False):
260
263
self._warn_slow()
261
265
with self.source_store.lock_read():
262
266
old_refs = self._get_target_bzr_refs()
263
267
new_refs = update_refs(old_refs)
264
268
revidmap = self.fetch_objects(
265
[(git_sha, bzr_revid) for (git_sha, bzr_revid) in new_refs.values() if git_sha is None or not git_sha.startswith(SYMREF)], lossy=lossy)
269
[(git_sha, bzr_revid)
270
for (git_sha, bzr_revid) in new_refs.values()
271
if git_sha is None or not git_sha.startswith(SYMREF)],
266
273
for name, (gitid, revid) in viewitems(new_refs):
267
274
if gitid is None:
271
278
gitid = self.source_store._lookup_revision_sha1(revid)
272
279
if gitid.startswith(SYMREF):
273
self.target_refs.set_symbolic_ref(name, gitid[len(SYMREF):])
280
self.target_refs.set_symbolic_ref(
281
name, gitid[len(SYMREF):])
276
284
old_git_id = old_refs[name][0]
278
286
self.target_refs.add_if_new(name, gitid)
280
288
self.target_refs.set_if_equals(name, old_git_id, gitid)
281
return revidmap, old_refs, new_refs
289
result_refs[name] = (gitid, revid if not lossy else self.mapping.revision_id_foreign_to_bzr(gitid))
290
return revidmap, old_refs, result_refs
283
292
def fetch_objects(self, revs, lossy, limit=None):
284
293
if not lossy and not self.mapping.roundtripping:
285
294
for git_sha, bzr_revid in revs:
286
if bzr_revid is not None and needs_roundtripping(self.source, bzr_revid):
295
if (bzr_revid is not None and
296
needs_roundtripping(self.source, bzr_revid)):
287
297
raise NoPushSupport(self.source, self.target, self.mapping,
289
299
with self.source_store.lock_read():
293
303
object_generator = MissingObjectsIterator(
294
304
self.source_store, self.source, pb)
295
305
for (old_revid, git_sha) in object_generator.import_revisions(
298
new_revid = self.mapping.revision_id_foreign_to_bzr(git_sha)
308
new_revid = self.mapping.revision_id_foreign_to_bzr(
300
311
new_revid = old_revid
310
321
def fetch(self, revision_id=None, pb=None, find_ghosts=False,
311
fetch_spec=None, mapped_refs=None):
322
fetch_spec=None, mapped_refs=None):
312
323
if mapped_refs is not None:
313
324
stop_revisions = mapped_refs
314
325
elif revision_id is not None:
318
329
if recipe[0] in ("search", "proxy-search"):
319
330
stop_revisions = [(None, revid) for revid in recipe[1]]
321
raise AssertionError("Unsupported search result type %s" % recipe[0])
332
raise AssertionError(
333
"Unsupported search result type %s" % recipe[0])
323
stop_revisions = [(None, revid) for revid in self.source.all_revision_ids()]
335
stop_revisions = [(None, revid)
336
for revid in self.source.all_revision_ids()]
324
337
self._warn_slow()
326
339
self.fetch_objects(stop_revisions, lossy=False)
342
355
raise NoPushSupport(self.source, self.target, self.mapping)
343
356
unpeel_map = UnpeelMap.from_repository(self.source)
345
359
def git_update_refs(old_refs):
347
self.old_refs = dict([(k, (v, None)) for (k, v) in viewitems(old_refs)])
348
self.new_refs = update_refs(self.old_refs)
349
for name, (gitid, revid) in viewitems(self.new_refs):
362
k: (v, None) for (k, v) in viewitems(old_refs)}
363
new_refs = update_refs(self.old_refs)
364
for name, (gitid, revid) in viewitems(new_refs):
350
365
if gitid is None:
351
366
git_sha = self.source_store._lookup_revision_sha1(revid)
352
gitid = unpeel_map.re_unpeel_tag(git_sha, old_refs.get(name))
367
gitid = unpeel_map.re_unpeel_tag(
368
git_sha, old_refs.get(name))
353
369
if not overwrite:
354
if remote_divergence(old_refs.get(name), gitid, self.source_store):
370
if remote_divergence(
371
old_refs.get(name), gitid, self.source_store):
355
372
raise DivergedBranches(self.source, self.target)
356
373
ret[name] = gitid
358
375
self._warn_slow()
359
376
with self.source_store.lock_read():
360
new_refs = self.target.send_pack(git_update_refs,
361
self.source_store.generate_lossy_pack_data)
377
new_refs = self.target.send_pack(
378
git_update_refs, self.source_store.generate_lossy_pack_data)
362
379
# FIXME: revidmap?
363
return revidmap, self.old_refs, self.new_refs
380
return revidmap, self.old_refs, new_refs
366
383
def is_compatible(source, target):
393
410
def get_determine_wants_heads(self, wants, include_tags=False):
394
411
wants = set(wants)
395
413
def determine_wants(refs):
396
potential = set(wants)
415
for k, v in viewitems(refs):
416
if k.endswith(ANNOTATED_TAG_SUFFIX):
417
unpeel_lookup[v] = refs[k[:-len(ANNOTATED_TAG_SUFFIX)]]
418
potential = set([unpeel_lookup.get(w, w) for w in wants])
398
for k, unpeeled in viewitems(refs):
420
for k, sha in viewitems(refs):
399
421
if k.endswith(ANNOTATED_TAG_SUFFIX):
401
423
if not is_tag(k):
403
if unpeeled == ZERO_SHA:
405
potential.add(unpeeled)
406
428
return list(potential - self._target_has_shas(potential))
407
429
return determine_wants
418
440
self.fetch(revision_id, find_ghosts=False)
420
442
def search_missing_revision_ids(self,
421
find_ghosts=True, revision_ids=None, if_present_ids=None,
443
find_ghosts=True, revision_ids=None,
444
if_present_ids=None, limit=None):
423
445
if limit is not None:
424
446
raise FetchLimitUnsupported(self)
425
447
if revision_ids is None and if_present_ids is None:
467
489
potential.add(self.source.controldir.get_peeled(k) or v)
468
490
return list(potential - self._target_has_shas(potential))
470
def get_determine_wants_heads(self, wants, include_tags=False):
472
def determine_wants(refs):
473
potential = set(wants)
475
for k, unpeeled in viewitems(refs):
478
if unpeeled == ZERO_SHA:
480
potential.add(self.source.controldir.get_peeled(k) or unpeeled)
481
return list(potential - self._target_has_shas(potential))
482
return determine_wants
484
492
def _warn_slow(self):
485
493
if not config.GlobalConfig().suppress_warning('slow_intervcs_push'):
493
501
:param determine_wants: determine_wants callback
494
502
:param mapping: BzrGitMapping to use
495
503
:param limit: Maximum number of commits to import.
496
:return: Tuple with pack hint, last imported revision id and remote refs
504
:return: Tuple with pack hint, last imported revision id and remote
498
507
raise NotImplementedError(self.fetch_objects)
529
538
determine_wants = self.determine_wants_all
531
540
(pack_hint, _, remote_refs) = self.fetch_objects(determine_wants,
533
542
if pack_hint is not None and self.target._format.pack_compresses:
534
543
self.target.pack(hint=pack_hint)
535
544
return remote_refs
564
573
wants_recorder, graph_walker, store.get_raw)
565
574
trace.mutter("Importing %d new revisions",
566
575
len(wants_recorder.wants))
567
(pack_hint, last_rev) = import_git_objects(self.target,
568
mapping, objects_iter, store, wants_recorder.wants, pb,
576
(pack_hint, last_rev) = import_git_objects(
577
self.target, mapping, objects_iter, store,
578
wants_recorder.wants, pb, limit)
570
579
return (pack_hint, last_rev, wants_recorder.remote_refs)
596
605
with ui.ui_factory.nested_progress_bar() as pb:
597
606
target_git_object_retriever.lock_write()
599
(pack_hint, last_rev) = import_git_objects(self.target,
600
mapping, self.source._git.object_store,
608
(pack_hint, last_rev) = import_git_objects(
609
self.target, mapping, self.source._git.object_store,
601
610
target_git_object_retriever, wants, pb, limit)
602
611
return (pack_hint, last_rev, remote_refs)
625
634
raise LossyPushToSameVCS(self.source, self.target)
626
635
old_refs = self.target.controldir.get_refs_container()
628
638
def determine_wants(heads):
629
old_refs = dict([(k, (v, None)) for (k, v) in viewitems(heads.as_dict())])
639
old_refs = dict([(k, (v, None))
640
for (k, v) in viewitems(heads.as_dict())])
630
641
new_refs = update_refs(old_refs)
631
642
ref_changes.update(new_refs)
632
643
return [sha1 for (sha1, bzr_revid) in viewvalues(new_refs)]
636
647
new_refs = self.target.controldir.get_refs_container()
637
648
return None, old_refs, new_refs
639
def fetch_objects(self, determine_wants, mapping=None, limit=None, lossy=False):
650
def fetch_objects(self, determine_wants, mapping=None, limit=None,
640
652
raise NotImplementedError(self.fetch_objects)
642
654
def _target_has_shas(self, shas):
643
return set([sha for sha in shas if sha in self.target._git.object_store])
656
[sha for sha in shas if sha in self.target._git.object_store])
645
658
def fetch(self, revision_id=None, find_ghosts=False,
646
mapping=None, fetch_spec=None, branches=None, limit=None, include_tags=False):
659
mapping=None, fetch_spec=None, branches=None, limit=None,
647
661
if mapping is None:
648
662
mapping = self.source.get_mapping()
649
663
if revision_id is not None:
669
683
elif fetch_spec is None and revision_id is None:
670
684
determine_wants = self.determine_wants_all
672
determine_wants = self.get_determine_wants_revids(args, include_tags=include_tags)
686
determine_wants = self.get_determine_wants_revids(
687
args, include_tags=include_tags)
673
688
wants_recorder = DetermineWantsRecorder(determine_wants)
674
689
self.fetch_objects(wants_recorder, mapping, limit=limit)
675
690
return wants_recorder.remote_refs
693
708
class InterLocalGitLocalGitRepository(InterGitGitRepository):
695
def fetch_objects(self, determine_wants, mapping=None, limit=None, lossy=False):
710
def fetch_objects(self, determine_wants, mapping=None, limit=None,
697
713
raise LossyPushToSameVCS(self.source, self.target)
698
714
if limit is not None:
701
717
with ui.ui_factory.nested_progress_bar() as pb:
702
718
progress = DefaultProgressReporter(pb).progress
703
719
refs = self.source._git.fetch(
704
self.target._git, determine_wants,
720
self.target._git, determine_wants,
706
722
return (None, None, refs)
715
731
class InterRemoteGitLocalGitRepository(InterGitGitRepository):
717
def fetch_objects(self, determine_wants, mapping=None, limit=None, lossy=False):
733
def fetch_objects(self, determine_wants, mapping=None, limit=None,
719
736
raise LossyPushToSameVCS(self.source, self.target)
720
737
if limit is not None:
721
738
raise FetchLimitUnsupported(self)
722
739
graphwalker = self.target._git.get_graph_walker()
723
if CAPABILITY_THIN_PACK in self.source.controldir._client._fetch_capabilities:
740
if (CAPABILITY_THIN_PACK in
741
self.source.controldir._client._fetch_capabilities):
724
742
# TODO(jelmer): Avoid reading entire file into memory and
725
743
# only processing it after the whole file has been fetched.