96
96
inv = tree.inventory
97
97
return len(inv) * 250
98
98
self.repository = repository
99
self._cache = lru_cache.LRUSizeCache(max_size=MAX_TREE_CACHE_SIZE,
100
after_cleanup_size=None, compute_size=approx_tree_size)
99
self._cache = lru_cache.LRUSizeCache(
100
max_size=MAX_TREE_CACHE_SIZE, after_cleanup_size=None,
101
compute_size=approx_tree_size)
102
103
def revision_tree(self, revid):
119
120
if tree.get_revision_id() != revid:
120
121
raise AssertionError(
121
"revision id did not match: %s != %s" % (
122
tree.get_revision_id(), revid))
122
"revision id did not match: %s != %s" % (
123
tree.get_revision_id(), revid))
123
124
trees[revid] = tree
124
125
for tree in self.repository.revision_trees(todo):
125
126
trees[tree.get_revision_id()] = tree
164
165
if len(expected_sha) == 40:
165
166
if expected_sha != object.sha().hexdigest().encode('ascii'):
166
167
raise AssertionError("Invalid sha for %r: %s" % (object,
168
169
elif len(expected_sha) == 20:
169
170
if expected_sha != object.sha().digest():
170
raise AssertionError("Invalid sha for %r: %s" % (object,
171
sha_to_hex(expected_sha)))
171
raise AssertionError("Invalid sha for %r: %s" % (
172
object, sha_to_hex(expected_sha)))
173
174
raise AssertionError("Unknown length %d for %r" % (len(expected_sha),
177
def directory_to_tree(path, children, lookup_ie_sha1, unusual_modes, empty_file_name,
178
def directory_to_tree(path, children, lookup_ie_sha1, unusual_modes,
179
empty_file_name, allow_empty=False):
179
180
"""Create a Git Tree object from a Bazaar directory.
181
182
:param path: directory path
227
227
except IndexError:
228
228
base_tree = tree._repository.revision_tree(NULL_REVISION)
229
229
other_parent_trees = []
230
231
def find_unchanged_parent_ie(file_id, kind, other, parent_trees):
231
232
for ptree in parent_trees:
237
238
pkind = ptree.kind(ppath, file_id)
238
239
if kind == "file":
239
240
if (pkind == "file" and
240
ptree.get_file_sha1(ppath, file_id) == other):
241
return (file_id, ptree.get_file_revision(ppath, file_id))
241
ptree.get_file_sha1(ppath, file_id) == other):
243
file_id, ptree.get_file_revision(ppath, file_id))
242
244
if kind == "symlink":
243
245
if (pkind == "symlink" and
244
ptree.get_symlink_target(ppath, file_id) == other):
245
return (file_id, ptree.get_file_revision(ppath, file_id))
246
ptree.get_symlink_target(ppath, file_id) == other):
248
file_id, ptree.get_file_revision(ppath, file_id))
248
251
# Find all the changed blobs
254
257
sha1 = tree.get_file_sha1(path[1], file_id)
257
(pfile_id, prevision) = find_unchanged_parent_ie(file_id, kind[1], sha1, other_parent_trees)
260
(pfile_id, prevision) = find_unchanged_parent_ie(
261
file_id, kind[1], sha1, other_parent_trees)
275
279
shamap[path[1]] = blob_id
276
280
if add_cache_entry is not None:
277
add_cache_entry(("blob", blob_id), (file_id, tree.get_file_revision(path[1])), path[1])
283
(file_id, tree.get_file_revision(path[1])), path[1])
278
284
elif kind[1] == "symlink":
279
285
target = tree.get_symlink_target(path[1], file_id)
280
286
blob = symlink_to_blob(target)
281
287
shamap[path[1]] = blob.id
282
288
if add_cache_entry is not None:
283
add_cache_entry(blob, (file_id, tree.get_file_revision(path[1])), path[1])
290
blob, (file_id, tree.get_file_revision(path[1])), path[1])
285
find_unchanged_parent_ie(file_id, kind[1], target, other_parent_trees)
292
find_unchanged_parent_ie(
293
file_id, kind[1], target, other_parent_trees)
287
295
if changed_content:
288
yield path[1], blob, (file_id, tree.get_file_revision(path[1], file_id))
296
yield (path[1], blob,
297
(file_id, tree.get_file_revision(path[1], file_id)))
289
298
elif kind[1] is None:
290
299
shamap[path[1]] = None
291
300
elif kind[1] != 'directory':
298
307
# Fetch contents of the blobs that were changed
299
308
for (path, file_id), chunks in tree.iter_files_bytes(
300
[(path, (path, file_id)) for (path, file_id) in new_blobs]):
309
[(path, (path, file_id)) for (path, file_id) in new_blobs]):
302
311
obj.chunked = chunks
303
312
if add_cache_entry is not None:
336
345
elif ie.kind == "directory":
337
346
# Not all cache backends store the tree information,
338
347
# calculate again from scratch
339
ret = directory_to_tree(path, ie.children.values(), ie_to_hexsha,
340
unusual_modes, dummy_file_name, ie.parent_id is None)
348
ret = directory_to_tree(
349
path, ie.children.values(), ie_to_hexsha, unusual_modes,
350
dummy_file_name, ie.parent_id is None)
423
433
if self._map_updated:
425
435
if (stop_revision is not None and
426
not self._missing_revisions([stop_revision])):
436
not self._missing_revisions([stop_revision])):
428
438
graph = self.repository.get_graph()
429
439
if stop_revision is None:
451
461
pb = ui.ui_factory.nested_progress_bar()
453
for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
463
for i, revid in enumerate(graph.iter_topo_order(
454
465
trace.mutter('processing %r', revid)
455
466
pb.update("updating git map", i, len(missing_revids))
456
467
self._update_sha_map_revision(revid)
483
494
except errors.NoSuchRevision:
485
496
return self.mapping.export_commit(rev, tree_sha, parent_lookup,
488
499
def _create_fileid_map_blob(self, tree):
489
500
# FIXME: This can probably be a lot more efficient,
506
517
parent_trees = self.tree_cache.revision_trees(
507
518
[p for p in rev.parent_ids if p in present_parents])
509
for path, obj, bzr_key_data in _tree_to_objects(tree, parent_trees,
510
self._cache.idmap, unusual_modes,
520
for path, obj, bzr_key_data in _tree_to_objects(
521
tree, parent_trees, self._cache.idmap, unusual_modes,
511
522
self.mapping.BZR_DUMMY_FILE, add_cache_entry):
534
545
yield "", root_tree
536
547
testament3 = StrictTestament3(rev, tree)
537
verifiers = { "testament3-sha1": testament3.as_sha1() }
548
verifiers = {"testament3-sha1": testament3.as_sha1()}
540
551
commit_obj = self._reconstruct_commit(rev, root_tree.id,
541
lossy=lossy, verifiers=verifiers)
552
lossy=lossy, verifiers=verifiers)
543
554
foreign_revid, mapping = mapping_registry.parse_revision_id(
583
594
tree = self.tree_cache.revision_tree(revision)
584
595
path = tree.id2path(file_id)
585
596
if tree.kind(path, file_id) == 'symlink':
586
blob = symlink_to_blob(tree.get_symlink_target(path, file_id))
597
blob = symlink_to_blob(
598
tree.get_symlink_target(path, file_id))
587
599
_check_expected_sha(expected_sha, blob)
590
602
def _reconstruct_tree(self, fileid, revid, bzr_tree, unusual_modes,
592
604
"""Return a Git Tree object from a file id and a revision stored in bzr.
594
606
:param fileid: fileid in the tree.
598
610
if entry.kind == "directory":
600
612
return self._cache.idmap.lookup_tree_id(entry.file_id,
602
614
except (NotImplementedError, KeyError):
603
obj = self._reconstruct_tree(entry.file_id, revid, bzr_tree,
615
obj = self._reconstruct_tree(
616
entry.file_id, revid, bzr_tree, unusual_modes)
621
633
raise AssertionError("unknown entry kind '%s'" % entry.kind)
622
634
path = bzr_tree.id2path(fileid)
623
635
tree = directory_to_tree(
625
bzr_tree.iter_child_entries(path),
626
get_ie_sha1, unusual_modes, self.mapping.BZR_DUMMY_FILE,
627
bzr_tree.get_root_id() == fileid)
637
bzr_tree.iter_child_entries(path),
638
get_ie_sha1, unusual_modes, self.mapping.BZR_DUMMY_FILE,
639
bzr_tree.get_root_id() == fileid)
628
640
if (bzr_tree.get_root_id() == fileid and
629
self.mapping.BZR_FILE_IDS_FILE is not None):
641
self.mapping.BZR_FILE_IDS_FILE is not None):
632
644
b = self._create_fileid_map_blob(bzr_tree)
743
755
trace.mutter('entry for %s %s in shamap: %r, but not '
744
756
'found in repository', kind, sha, type_data)
745
757
raise KeyError(sha)
746
# FIXME: the type data should say whether conversion was lossless
747
commit = self._reconstruct_commit(rev, tree_sha,
748
lossy=(not self.mapping.roundtripping), verifiers=verifiers)
758
# FIXME: the type data should say whether conversion was
760
commit = self._reconstruct_commit(
761
rev, tree_sha, lossy=(not self.mapping.roundtripping),
749
763
_check_expected_sha(sha, commit)
751
765
elif kind == "blob":
758
772
tree = self.tree_cache.revision_tree(revid)
759
773
rev = self.repository.get_revision(revid)
760
774
except errors.NoSuchRevision:
761
trace.mutter('entry for %s %s in shamap: %r, but not found in '
776
'entry for %s %s in shamap: %r, but not found in '
762
777
'repository', kind, sha, type_data)
763
778
raise KeyError(sha)
764
779
unusual_modes = extract_unusual_modes(rev)
766
return self._reconstruct_tree(fileid, revid,
767
tree, unusual_modes, expected_sha=sha)
781
return self._reconstruct_tree(
782
fileid, revid, tree, unusual_modes, expected_sha=sha)
768
783
except errors.NoSuchRevision:
769
784
raise KeyError(sha)
773
788
raise KeyError(sha)
775
790
def generate_lossy_pack_data(self, have, want, progress=None,
776
get_tagged=None, ofs_delta=False):
791
get_tagged=None, ofs_delta=False):
777
792
return pack_objects_to_data(
778
self.generate_pack_contents(have, want, progress, get_tagged,
793
self.generate_pack_contents(have, want, progress, get_tagged,
781
796
def generate_pack_contents(self, have, want, progress=None,
782
ofs_delta=False, get_tagged=None, lossy=False):
797
ofs_delta=False, get_tagged=None, lossy=False):
783
798
"""Iterate over the contents of a pack file.
785
800
:param have: List of SHA1s of objects that should not be sent
839
855
if os.path.getsize(path) == 0:
841
857
pd = PackData(path)
842
pd.create_index_v2(path[:-5]+".idx", self.object_store.get_raw)
858
pd.create_index_v2(path[:-5] + ".idx", self.object_store.get_raw)
844
860
p = Pack(path[:-5])
845
861
with self.repository.lock_write():
846
862
self.repository.start_write_group()
848
864
import_git_objects(self.repository, self.mapping,
849
p.iterobjects(get_raw=self.get_raw),
865
p.iterobjects(get_raw=self.get_raw),
867
except BaseException:
852
868
self.repository.abort_write_group()