287
281
shamap[ie.file_id] = obj.id
284
class PackTupleIterable(object):
286
def __init__(self, store):
290
def add(self, sha, path):
291
self.objects[sha] = path
294
return len(self.objects)
297
return ((self.store[object_id], path) for (object_id, path) in
298
self.objects.iteritems())
290
301
class BazaarObjectStore(BaseObjectStore):
291
302
"""A Git-style object store backed onto a Bazaar repository."""
293
304
def __init__(self, repository, mapping=None):
294
305
self.repository = repository
306
self._map_updated = False
295
308
if mapping is None:
296
309
self.mapping = default_mapping
298
311
self.mapping = mapping
299
312
self._cache = cache_from_repository(repository)
300
self._content_cache_types = ("tree")
313
self._content_cache_types = ("tree",)
301
314
self.start_write_group = self._cache.idmap.start_write_group
302
315
self.abort_write_group = self._cache.idmap.abort_write_group
303
316
self.commit_write_group = self._cache.idmap.commit_write_group
304
317
self.tree_cache = LRUTreeCache(self.repository)
306
319
def _update_sha_map(self, stop_revision=None):
320
if not self.is_locked():
321
raise AssertionError()
322
if self._map_updated:
324
if (stop_revision is not None and
325
not self._cache.idmap.missing_revisions([stop_revision])):
307
327
graph = self.repository.get_graph()
308
328
if stop_revision is None:
309
329
heads = graph.heads(self.repository.all_revision_ids())
399
423
if roundtrip and self.mapping.BZR_FILE_IDS_FILE is not None:
400
424
b = self._create_fileid_map_blob(tree.inventory)
401
425
if b is not None:
402
root_tree[self.mapping.BZR_FILE_IDS_FILE] = ((stat.S_IFREG | 0644), b.id)
426
root_tree[self.mapping.BZR_FILE_IDS_FILE] = (
427
(stat.S_IFREG | 0644), b.id)
403
428
yield self.mapping.BZR_FILE_IDS_FILE, b, None
404
429
yield "", root_tree, root_ie
406
testament3 = StrictTestament3(rev, tree.inventory)
431
if getattr(StrictTestament3, "from_revision_tree", None):
432
testament3 = StrictTestament3(rev, tree)
434
testament3 = StrictTestament3(rev, tree.inventory)
407
435
verifiers = { "testament3-sha1": testament3.as_sha1() }
428
456
for path, obj, ie in self._revision_to_objects(rev, tree,
430
458
if isinstance(obj, Commit):
431
testament3 = StrictTestament3(rev, tree.inventory)
459
if getattr(StrictTestament3, "from_revision_tree", None):
460
testament3 = StrictTestament3(rev, tree)
462
testament3 = StrictTestament3(rev, tree.inventory)
432
463
ie = { "testament3-sha1": testament3.as_sha1() }
433
464
updater.add_object(obj, ie, path)
434
465
commit_obj = updater.finish()
487
518
self.mapping.BZR_DUMMY_FILE)
488
519
if (inv.root.file_id == fileid and
489
520
self.mapping.BZR_FILE_IDS_FILE is not None):
490
523
b = self._create_fileid_map_blob(inv)
491
524
# If this is the root tree, add the file ids
492
tree[self.mapping.BZR_FILE_IDS_FILE] = ((stat.S_IFREG | 0644), b.id)
493
_check_expected_sha(expected_sha, tree)
525
tree[self.mapping.BZR_FILE_IDS_FILE] = (
526
(stat.S_IFREG | 0644), b.id)
528
_check_expected_sha(expected_sha, tree)
496
531
def get_parents(self, sha):
530
560
def __contains__(self, sha):
531
561
# See if sha is in map
533
(type, type_data) = self.lookup_git_sha(sha)
535
return self.repository.has_revision(type_data[0])
537
return self.repository.texts.has_key(type_data)
539
return self.repository.has_revision(type_data[1])
563
for (type, type_data) in self.lookup_git_sha(sha):
565
if self.repository.has_revision(type_data[0]):
568
if self.repository.texts.has_key(type_data):
571
if self.repository.has_revision(type_data[1]):
574
raise AssertionError("Unknown object type '%s'" % type)
541
raise AssertionError("Unknown object type '%s'" % type)
545
def lookup_git_shas(self, shas, update_map=True):
546
from dulwich.protocol import ZERO_SHA
582
self._map_updated = False
583
self.repository.lock_read()
584
return LogicalLockResult(self.unlock)
586
def lock_write(self):
588
self._map_updated = False
589
self.repository.lock_write()
590
return LogicalLockResult(self.unlock)
593
return (self._locked is not None)
597
self._map_updated = False
598
self.repository.unlock()
600
def lookup_git_shas(self, shas):
549
603
if sha == ZERO_SHA:
550
ret[sha] = ("commit", (NULL_REVISION, None, {}))
604
ret[sha] = [("commit", (NULL_REVISION, None, {}))]
553
ret[sha] = self._cache.idmap.lookup_git_sha(sha)
607
ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
556
# if not, see if there are any unconverted revisions and add
557
# them to the map, search for sha in map again
558
self._update_sha_map()
561
ret[sha] = self._cache.idmap.lookup_git_sha(sha)
609
# if not, see if there are any unconverted revisions and
610
# add them to the map, search for sha in map again
611
self._update_sha_map()
613
ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
566
def lookup_git_sha(self, sha, update_map=True):
567
return self.lookup_git_shas([sha], update_map=update_map)[sha]
618
def lookup_git_sha(self, sha):
619
return self.lookup_git_shas([sha])[sha]
569
621
def __getitem__(self, sha):
570
622
if self._cache.content_cache is not None:
572
624
return self._cache.content_cache[sha]
575
(type, type_data) = self.lookup_git_sha(sha)
576
# convert object to git object
578
(revid, tree_sha, verifiers) = type_data
580
rev = self.repository.get_revision(revid)
581
except errors.NoSuchRevision:
582
trace.mutter('entry for %s %s in shamap: %r, but not found in '
583
'repository', type, sha, type_data)
585
commit = self._reconstruct_commit(rev, tree_sha, roundtrip=True,
587
_check_expected_sha(sha, commit)
590
(fileid, revision) = type_data
591
return self._reconstruct_blobs([(fileid, revision, sha)]).next()
593
(fileid, revid) = type_data
595
tree = self.tree_cache.revision_tree(revid)
596
rev = self.repository.get_revision(revid)
597
except errors.NoSuchRevision:
598
trace.mutter('entry for %s %s in shamap: %r, but not found in repository', type, sha, type_data)
600
unusual_modes = extract_unusual_modes(rev)
602
return self._reconstruct_tree(fileid, revid, tree.inventory,
603
unusual_modes, expected_sha=sha)
604
except errors.NoSuchRevision:
627
for (kind, type_data) in self.lookup_git_sha(sha):
628
# convert object to git object
630
(revid, tree_sha, verifiers) = type_data
632
rev = self.repository.get_revision(revid)
633
except errors.NoSuchRevision:
634
trace.mutter('entry for %s %s in shamap: %r, but not '
635
'found in repository', kind, sha, type_data)
637
commit = self._reconstruct_commit(rev, tree_sha,
638
roundtrip=True, verifiers=verifiers)
639
_check_expected_sha(sha, commit)
642
(fileid, revision) = type_data
643
blobs = self._reconstruct_blobs([(fileid, revision, sha)])
646
(fileid, revid) = type_data
648
tree = self.tree_cache.revision_tree(revid)
649
rev = self.repository.get_revision(revid)
650
except errors.NoSuchRevision:
651
trace.mutter('entry for %s %s in shamap: %r, but not found in repository', kind, sha, type_data)
653
unusual_modes = extract_unusual_modes(rev)
655
return self._reconstruct_tree(fileid, revid,
656
tree.inventory, unusual_modes, expected_sha=sha)
657
except errors.NoSuchRevision:
660
raise AssertionError("Unknown object type '%s'" % kind)
607
raise AssertionError("Unknown object type '%s'" % type)
609
664
def generate_lossy_pack_contents(self, have, want, progress=None,
610
665
get_tagged=None):
622
677
ret = self.lookup_git_shas(have + want)
623
678
for commit_sha in have:
625
(type, (revid, tree_sha)) = ret[commit_sha]
680
for (type, type_data) in ret[commit_sha]:
681
assert type == "commit"
682
processed.add(type_data[0])
629
assert type == "commit"
632
686
for commit_sha in want:
633
687
if commit_sha in have:
636
(type, (revid, tree_sha)) = ret[commit_sha]
690
for (type, type_data) in ret[commit_sha]:
691
assert type == "commit"
692
pending.add(type_data[0])
640
assert type == "commit"
643
todo = _find_missing_bzr_revids(self.repository.get_parent_map,
696
graph = self.repository.get_graph()
697
todo = _find_missing_bzr_revids(graph, pending, processed)
645
698
trace.mutter('sending revisions %r', todo)
699
ret = PackTupleIterable(self)
647
700
pb = ui.ui_factory.nested_progress_bar()
649
702
for i, revid in enumerate(todo):
650
703
pb.update("generating git objects", i, len(todo))
651
rev = self.repository.get_revision(revid)
705
rev = self.repository.get_revision(revid)
706
except errors.NoSuchRevision:
652
708
tree = self.tree_cache.revision_tree(revid)
653
709
for path, obj, ie in self._revision_to_objects(rev, tree,
654
710
roundtrip=not lossy):
655
ret.append((obj, path))
711
ret.add(obj.id, path)