324
324
raise AssertionError("recording deletes not activated.")
325
325
delta = (path, None, file_id, None)
326
326
self._basis_delta.append(delta)
327
self._any_changes = True
329
330
def will_record_deletes(self):
558
559
has been generated against. Currently assumed to be the same
559
560
as self.parents[0] - if it is not, errors may occur.
560
561
:param iter_changes: An iter_changes iterator with the changes to apply
561
to basis_revision_id.
562
to basis_revision_id. The iterator must not include any items with
563
a current kind of None - missing items must be either filtered out
564
or errored-on beefore record_iter_changes sees the item.
562
565
:param _entry_factory: Private method to bind entry_factory locally for
567
:return: A generator of (file_id, relpath, fs_hash) tuples for use with
566
570
# Create an inventory delta based on deltas between all the parents and
567
571
# deltas between all the parent inventories. We use inventory delta's
574
578
# {file_id -> revision_id -> inventory entry, for entries in parent
575
579
# trees that are not parents[0]
576
580
parent_entries = {}
577
revtrees = list(self.repository.revision_trees(self.parents))
583
revtrees = list(self.repository.revision_trees(self.parents))
584
except errors.NoSuchRevision:
585
# one or more ghosts, slow path.
587
for revision_id in self.parents:
589
revtrees.append(self.repository.revision_tree(revision_id))
590
except errors.NoSuchRevision:
592
basis_revision_id = _mod_revision.NULL_REVISION
594
revtrees.append(self.repository.revision_tree(
595
_mod_revision.NULL_REVISION))
578
596
# The basis inventory from a repository
580
598
basis_inv = revtrees[0].inventory
582
600
basis_inv = self.repository.revision_tree(
583
601
_mod_revision.NULL_REVISION).inventory
584
602
if len(self.parents) > 0:
585
if basis_revision_id != self.parents[0]:
603
if basis_revision_id != self.parents[0] and not ghost_basis:
587
605
"arbitrary basis parents not yet supported with merges")
588
606
for revtree in revtrees[1:]:
593
611
if change[2] not in merged_ids:
594
612
if change[0] is not None:
613
basis_entry = basis_inv[change[2]]
595
614
merged_ids[change[2]] = [
596
basis_inv[change[2]].revision,
616
basis_entry.revision,
597
618
change[3].revision]
619
parent_entries[change[2]] = {
621
basis_entry.revision:basis_entry,
623
change[3].revision:change[3],
599
626
merged_ids[change[2]] = [change[3].revision]
600
parent_entries[change[2]] = {change[3].revision:change[3]}
627
parent_entries[change[2]] = {change[3].revision:change[3]}
602
629
merged_ids[change[2]].append(change[3].revision)
603
630
parent_entries[change[2]][change[3].revision] = change[3]
628
655
# inv delta change: (file_id, (path_in_source, path_in_target),
629
656
# changed_content, versioned, parent, name, kind,
631
basis_entry = basis_inv[file_id]
633
(basis_inv.id2path(file_id), tree.id2path(file_id)),
635
(basis_entry.parent_id, basis_entry.parent_id),
636
(basis_entry.name, basis_entry.name),
637
(basis_entry.kind, basis_entry.kind),
638
(basis_entry.executable, basis_entry.executable))
639
changes[file_id] = (change, merged_ids[file_id])
659
basis_entry = basis_inv[file_id]
660
except errors.NoSuchId:
661
# a change from basis->some_parents but file_id isn't in basis
662
# so was new in the merge, which means it must have changed
663
# from basis -> current, and as it hasn't the add was reverted
664
# by the user. So we discard this change.
668
(basis_inv.id2path(file_id), tree.id2path(file_id)),
670
(basis_entry.parent_id, basis_entry.parent_id),
671
(basis_entry.name, basis_entry.name),
672
(basis_entry.kind, basis_entry.kind),
673
(basis_entry.executable, basis_entry.executable))
674
changes[file_id] = (change, merged_ids[file_id])
640
675
# changes contains tuples with the change and a set of inventory
641
676
# candidates for the file.
724
759
entry.text_sha1, entry.text_size = self._add_text_to_weave(
725
760
file_id, lines, heads, nostore_sha)
761
yield file_id, change[1][1], (entry.text_sha1, stat_value)
726
762
except errors.ExistingContent:
727
763
# No content change against a carry_over parent
764
# Perhaps this should also yield a fs hash update?
728
765
carried_over = True
729
766
entry.text_size = parent_entry.text_size
730
767
entry.text_sha1 = parent_entry.text_sha1
733
770
entry.symlink_target = tree.get_symlink_target(file_id)
734
771
if (carry_over_possible and
735
772
parent_entry.symlink_target == entry.symlink_target):
738
775
self._add_text_to_weave(change[0], [], heads, None)
739
776
elif kind == 'directory':
745
782
if change[1][1] != '' or self.repository.supports_rich_root():
746
783
self._add_text_to_weave(change[0], [], heads, None)
747
784
elif kind == 'tree-reference':
748
raise AssertionError('unknown kind %r' % kind)
785
if not self.repository._format.supports_tree_reference:
786
# This isn't quite sane as an error, but we shouldn't
787
# ever see this code path in practice: tree's don't
788
# permit references when the repo doesn't support tree
790
raise errors.UnsupportedOperation(tree.add_reference,
792
entry.reference_revision = \
793
tree.get_reference_revision(change[0])
794
if (carry_over_possible and
795
parent_entry.reference_revision == reference_revision):
798
self._add_text_to_weave(change[0], [], heads, None)
750
800
raise AssertionError('unknown kind %r' % kind)
751
801
if not carried_over: