144
def _tree_to_objects(tree, parent_trees, idmap, unusual_modes):
145
def _tree_to_objects(tree, parent_trees, idmap, unusual_modes, dummy_file_name=None):
145
146
"""Iterate over the objects that were introduced in a revision.
147
148
:param idmap: id map
148
149
:param unusual_modes: Unusual file modes
150
:param dummy_file_name: File name to use for dummy files
151
in empty directories. None to skip empty directories
149
152
:return: Yields (path, object, ie) entries
175
178
if kind[1] == "file":
176
179
ie = tree.inventory[file_id]
177
180
if changed_content:
180
182
pie = find_unchanged_parent_ie(ie, other_parent_trees)
184
shamap[ie.file_id] = idmap.lookup_blob_id(
185
pie.file_id, pie.revision)
187
shamap[ie.file_id] = idmap.lookup_blob_id(
188
pie.file_id, pie.revision)
192
blob.data = tree.get_file_text(ie.file_id)
193
shamap[ie.file_id] = blob.id
186
194
if not file_id in shamap:
187
195
new_blobs.append((path[1], ie))
188
196
new_trees[posixpath.dirname(path[1])] = parent[1]
253
262
for path in sorted(trees.keys(), reverse=True):
254
263
ie = tree.inventory[trees[path]]
255
264
assert ie.kind == "directory"
256
obj = directory_to_tree(ie, ie_to_hexsha, unusual_modes)
265
obj = directory_to_tree(ie, ie_to_hexsha, unusual_modes,
257
267
if obj is not None:
258
268
yield path, obj, ie
259
269
shamap[ie.file_id] = obj.id
314
324
self._update_sha_map()
315
325
return iter(self._cache.idmap.sha1s())
317
def _reconstruct_commit(self, rev, tree_sha):
327
def _reconstruct_commit(self, rev, tree_sha, roundtrip):
318
328
def parent_lookup(revid):
320
330
return self._lookup_revision_sha1(revid)
321
331
except errors.NoSuchRevision:
322
trace.warning("Ignoring ghost parent %s", revid)
324
return self.mapping.export_commit(rev, tree_sha, parent_lookup)
326
def _revision_to_objects(self, rev, tree):
333
return self.mapping.export_commit(rev, tree_sha, parent_lookup,
336
def _create_fileid_map_blob(self, inv):
337
# FIXME: This can probably be a lot more efficient,
338
# not all files necessarily have to be processed.
340
for (path, ie) in inv.iter_entries():
341
if self.mapping.generate_file_id(path) != ie.file_id:
342
file_ids[path] = ie.file_id
343
return self.mapping.export_fileid_map(file_ids)
345
def _revision_to_objects(self, rev, tree, roundtrip):
346
"""Convert a revision to a set of git objects.
348
:param rev: Bazaar revision object
349
:param tree: Bazaar revision tree
350
:param roundtrip: Whether to roundtrip all Bazaar revision data
327
352
unusual_modes = extract_unusual_modes(rev)
328
353
present_parents = self.repository.has_revisions(rev.parent_ids)
329
354
parent_trees = self.tree_cache.revision_trees(
330
355
[p for p in rev.parent_ids if p in present_parents])
332
357
for path, obj, ie in _tree_to_objects(tree, parent_trees,
333
self._cache.idmap, unusual_modes):
358
self._cache.idmap, unusual_modes, self.mapping.BZR_DUMMY_FILE):
362
# Don't yield just yet
365
if root_tree is None:
338
366
# Pointless commit - get the tree sha elsewhere
339
367
if not rev.parent_ids:
342
370
base_sha1 = self._lookup_revision_sha1(rev.parent_ids[0])
343
tree_sha = self[base_sha1].tree
344
commit_obj = self._reconstruct_commit(rev, tree_sha)
371
root_tree = self[self[base_sha1].tree]
372
root_ie = tree.inventory.root
374
b = self._create_fileid_map_blob(tree.inventory)
376
root_tree[self.mapping.BZR_FILE_IDS_FILE] = ((stat.S_IFREG | 0644), b.id)
377
yield self.mapping.BZR_FILE_IDS_FILE, b, None
378
yield "", root_tree, root_ie
379
commit_obj = self._reconstruct_commit(rev, root_tree.id,
346
382
foreign_revid, mapping = mapping_registry.parse_revision_id(
358
394
rev = self.repository.get_revision(revid)
359
395
tree = self.tree_cache.revision_tree(rev.revision_id)
360
396
updater = self._get_updater(rev)
361
for path, obj, ie in self._revision_to_objects(rev, tree):
397
for path, obj, ie in self._revision_to_objects(rev, tree,
362
399
updater.add_object(obj, ie)
363
400
commit_obj = updater.finish()
364
401
return commit_obj.id
412
449
[(entry.file_id, entry.revision, None)]).next().id
414
451
raise AssertionError("unknown entry kind '%s'" % entry.kind)
415
tree = directory_to_tree(inv[fileid], get_ie_sha1, unusual_modes)
452
tree = directory_to_tree(inv[fileid], get_ie_sha1, unusual_modes,
453
self.mapping.BZR_DUMMY_FILE)
454
if inv.root.file_id == fileid:
455
b = self._create_fileid_map_blob(inv)
456
# If this is the root tree, add the file ids
457
tree[self.mapping.BZR_FILE_IDS_FILE] = ((stat.S_IFREG | 0644), b.id)
416
458
_check_expected_sha(expected_sha, tree)
497
543
trace.mutter('entry for %s %s in shamap: %r, but not found in '
498
544
'repository', type, sha, type_data)
499
545
raise KeyError(sha)
500
commit = self._reconstruct_commit(rev, tree_sha)
546
commit = self._reconstruct_commit(rev, tree_sha, roundtrip=True)
501
547
_check_expected_sha(sha, commit)
503
549
elif type == "blob":
521
567
raise AssertionError("Unknown object type '%s'" % type)
569
def generate_lossy_pack_contents(self, have, want, progress=None,
571
return self.generate_pack_contents(have, want, progress, get_tagged,
523
574
def generate_pack_contents(self, have, want, progress=None,
575
get_tagged=None, lossy=False):
525
576
"""Iterate over the contents of a pack file.
527
578
:param have: List of SHA1s of objects that should not be sent
559
610
pb.update("generating git objects", i, len(todo))
560
611
rev = self.repository.get_revision(revid)
561
612
tree = self.tree_cache.revision_tree(revid)
562
for path, obj, ie in self._revision_to_objects(rev, tree):
613
for path, obj, ie in self._revision_to_objects(rev, tree,
614
roundtrip=not lossy):
563
615
ret.append((obj, path))