97
96
inv = tree.inventory
98
97
return len(inv) * 250
99
98
self.repository = repository
100
self._cache = lru_cache.LRUSizeCache(max_size=MAX_TREE_CACHE_SIZE,
101
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)
103
103
def revision_tree(self, revid):
120
120
if tree.get_revision_id() != revid:
121
121
raise AssertionError(
122
"revision id did not match: %s != %s" % (
123
tree.get_revision_id(), revid))
122
"revision id did not match: %s != %s" % (
123
tree.get_revision_id(), revid))
124
124
trees[revid] = tree
125
125
for tree in self.repository.revision_trees(todo):
126
126
trees[tree.get_revision_id()] = tree
165
165
if len(expected_sha) == 40:
166
166
if expected_sha != object.sha().hexdigest().encode('ascii'):
167
167
raise AssertionError("Invalid sha for %r: %s" % (object,
169
169
elif len(expected_sha) == 20:
170
170
if expected_sha != object.sha().digest():
171
raise AssertionError("Invalid sha for %r: %s" % (object,
172
sha_to_hex(expected_sha)))
171
raise AssertionError("Invalid sha for %r: %s" % (
172
object, sha_to_hex(expected_sha)))
174
174
raise AssertionError("Unknown length %d for %r" % (len(expected_sha),
178
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):
180
180
"""Create a Git Tree object from a Bazaar directory.
182
182
:param path: directory path
228
227
except IndexError:
229
228
base_tree = tree._repository.revision_tree(NULL_REVISION)
230
229
other_parent_trees = []
231
231
def find_unchanged_parent_ie(file_id, kind, other, parent_trees):
232
232
for ptree in parent_trees:
238
238
pkind = ptree.kind(ppath, file_id)
239
239
if kind == "file":
240
240
if (pkind == "file" and
241
ptree.get_file_sha1(ppath, file_id) == other):
242
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))
243
244
if kind == "symlink":
244
245
if (pkind == "symlink" and
245
ptree.get_symlink_target(ppath, file_id) == other):
246
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))
249
251
# Find all the changed blobs
255
257
sha1 = tree.get_file_sha1(path[1], file_id)
258
(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)
276
279
shamap[path[1]] = blob_id
277
280
if add_cache_entry is not None:
278
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])
279
284
elif kind[1] == "symlink":
280
285
target = tree.get_symlink_target(path[1], file_id)
281
286
blob = symlink_to_blob(target)
282
287
shamap[path[1]] = blob.id
283
288
if add_cache_entry is not None:
284
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])
286
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)
288
295
if changed_content:
289
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)))
290
298
elif kind[1] is None:
291
299
shamap[path[1]] = None
292
300
elif kind[1] != 'directory':
299
307
# Fetch contents of the blobs that were changed
300
308
for (path, file_id), chunks in tree.iter_files_bytes(
301
[(path, (path, file_id)) for (path, file_id) in new_blobs]):
309
[(path, (path, file_id)) for (path, file_id) in new_blobs]):
303
311
obj.chunked = chunks
304
312
if add_cache_entry is not None:
305
313
add_cache_entry(obj, (file_id, tree.get_file_revision(path)), path)
306
yield path, obj, (file_id, tree.get_file_revision(path, file_id))
314
yield path, obj, (file_id, tree.get_file_revision(path))
307
315
shamap[path] = obj.id
309
317
for path in unusual_modes:
337
345
elif ie.kind == "directory":
338
346
# Not all cache backends store the tree information,
339
347
# calculate again from scratch
340
ret = directory_to_tree(path, ie.children.values(), ie_to_hexsha,
341
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)
424
433
if self._map_updated:
426
435
if (stop_revision is not None and
427
not self._missing_revisions([stop_revision])):
436
not self._missing_revisions([stop_revision])):
429
438
graph = self.repository.get_graph()
430
439
if stop_revision is None:
452
461
pb = ui.ui_factory.nested_progress_bar()
454
for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
463
for i, revid in enumerate(graph.iter_topo_order(
455
465
trace.mutter('processing %r', revid)
456
466
pb.update("updating git map", i, len(missing_revids))
457
467
self._update_sha_map_revision(revid)
484
494
except errors.NoSuchRevision:
486
496
return self.mapping.export_commit(rev, tree_sha, parent_lookup,
489
499
def _create_fileid_map_blob(self, tree):
490
500
# FIXME: This can probably be a lot more efficient,
507
517
parent_trees = self.tree_cache.revision_trees(
508
518
[p for p in rev.parent_ids if p in present_parents])
510
for path, obj, bzr_key_data in _tree_to_objects(tree, parent_trees,
511
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,
512
522
self.mapping.BZR_DUMMY_FILE, add_cache_entry):
535
545
yield "", root_tree
537
547
testament3 = StrictTestament3(rev, tree)
538
verifiers = { "testament3-sha1": testament3.as_sha1() }
548
verifiers = {"testament3-sha1": testament3.as_sha1()}
541
551
commit_obj = self._reconstruct_commit(rev, root_tree.id,
542
lossy=lossy, verifiers=verifiers)
552
lossy=lossy, verifiers=verifiers)
544
554
foreign_revid, mapping = mapping_registry.parse_revision_id(
584
594
tree = self.tree_cache.revision_tree(revision)
585
595
path = tree.id2path(file_id)
586
596
if tree.kind(path, file_id) == 'symlink':
587
blob = symlink_to_blob(tree.get_symlink_target(path, file_id))
597
blob = symlink_to_blob(
598
tree.get_symlink_target(path, file_id))
588
599
_check_expected_sha(expected_sha, blob)
591
602
def _reconstruct_tree(self, fileid, revid, bzr_tree, unusual_modes,
593
604
"""Return a Git Tree object from a file id and a revision stored in bzr.
595
606
:param fileid: fileid in the tree.
599
610
if entry.kind == "directory":
601
612
return self._cache.idmap.lookup_tree_id(entry.file_id,
603
614
except (NotImplementedError, KeyError):
604
obj = self._reconstruct_tree(entry.file_id, revid, bzr_tree,
615
obj = self._reconstruct_tree(
616
entry.file_id, revid, bzr_tree, unusual_modes)
622
633
raise AssertionError("unknown entry kind '%s'" % entry.kind)
623
634
path = bzr_tree.id2path(fileid)
624
635
tree = directory_to_tree(
626
bzr_tree.iter_child_entries(path),
627
get_ie_sha1, unusual_modes, self.mapping.BZR_DUMMY_FILE,
628
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)
629
640
if (bzr_tree.get_root_id() == fileid and
630
self.mapping.BZR_FILE_IDS_FILE is not None):
641
self.mapping.BZR_FILE_IDS_FILE is not None):
633
644
b = self._create_fileid_map_blob(bzr_tree)
744
755
trace.mutter('entry for %s %s in shamap: %r, but not '
745
756
'found in repository', kind, sha, type_data)
746
757
raise KeyError(sha)
747
# FIXME: the type data should say whether conversion was lossless
748
commit = self._reconstruct_commit(rev, tree_sha,
749
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),
750
763
_check_expected_sha(sha, commit)
752
765
elif kind == "blob":
759
772
tree = self.tree_cache.revision_tree(revid)
760
773
rev = self.repository.get_revision(revid)
761
774
except errors.NoSuchRevision:
762
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 '
763
777
'repository', kind, sha, type_data)
764
778
raise KeyError(sha)
765
779
unusual_modes = extract_unusual_modes(rev)
767
return self._reconstruct_tree(fileid, revid,
768
tree, unusual_modes, expected_sha=sha)
781
return self._reconstruct_tree(
782
fileid, revid, tree, unusual_modes, expected_sha=sha)
769
783
except errors.NoSuchRevision:
770
784
raise KeyError(sha)
774
788
raise KeyError(sha)
776
790
def generate_lossy_pack_data(self, have, want, progress=None,
777
get_tagged=None, ofs_delta=False):
791
get_tagged=None, ofs_delta=False):
778
792
return pack_objects_to_data(
779
self.generate_pack_contents(have, want, progress, get_tagged,
793
self.generate_pack_contents(have, want, progress, get_tagged,
782
796
def generate_pack_contents(self, have, want, progress=None,
783
ofs_delta=False, get_tagged=None, lossy=False):
797
ofs_delta=False, get_tagged=None, lossy=False):
784
798
"""Iterate over the contents of a pack file.
786
800
:param have: List of SHA1s of objects that should not be sent
840
855
if os.path.getsize(path) == 0:
842
857
pd = PackData(path)
843
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)
845
860
p = Pack(path[:-5])
846
861
with self.repository.lock_write():
847
862
self.repository.start_write_group()
849
864
import_git_objects(self.repository, self.mapping,
850
p.iterobjects(get_raw=self.get_raw),
865
p.iterobjects(get_raw=self.get_raw),
867
except BaseException:
853
868
self.repository.abort_write_group()