247
247
self.local = local
248
248
self.master_branch = None
249
249
self.master_locked = False
250
self.recursive = recursive
250
251
self.rev_id = None
251
252
if specific_files is not None:
252
253
self.specific_files = sorted(
255
256
self.specific_files = None
256
257
self.specific_file_ids = None
257
258
self.allow_pointless = allow_pointless
258
self.recursive = recursive
259
259
self.revprops = revprops
260
260
self.message_callback = message_callback
261
261
self.timestamp = timestamp
290
290
# If provided, ensure the specified files are versioned
291
291
if self.specific_files is not None:
293
# is being called because it raises PathNotVerisonedError
294
# as a side effect of finding the IDs. We later use the ids we
295
# found as input to the working tree inventory iterator, so we
296
# only consider those ids rather than examining the whole tree
292
# Note: This routine is being called because it raises
293
# PathNotVersionedError as a side effect of finding the IDs. We
294
# later use the ids we found as input to the working tree
295
# inventory iterator, so we only consider those ids rather than
296
# examining the whole tree again.
298
297
# XXX: Dont we have filter_unversioned to do this more
300
299
self.specific_file_ids = tree.find_ids_across_trees(
650
649
if specific_files:
651
650
for path, old_ie in self.basis_inv.iter_entries():
652
651
if old_ie.file_id in self.builder.new_inventory:
652
# already added - skip.
654
654
if is_inside_any(specific_files, path):
655
# was inside the selected path, if not present it has been
656
658
if old_ie.kind == 'directory':
657
659
self._next_progress_entry()
660
# not in final inv yet, was not in the selected files, so is an
661
# entry to be preserved unaltered.
658
662
ie = old_ie.copy()
659
663
# Note: specific file commits after a merge are currently
660
664
# prohibited. This test is for sanity/safety in case it's
661
665
# required after that changes.
662
666
if len(self.parents) > 1:
663
667
ie.revision = None
664
if self.builder.record_entry_contents(ie, self.parent_invs, path,
668
delta, version_recorded = self.builder.record_entry_contents(
669
ie, self.parent_invs, path, self.basis_tree, None)
666
671
self.any_entries_changed = True
668
673
# note that deletes have occurred
686
691
deleted_paths = set()
687
692
work_inv = self.work_tree.inventory
688
693
assert work_inv.root is not None
694
# XXX: Note that entries may have the wrong kind.
689
695
entries = work_inv.iter_entries_by_dir(
690
696
specific_file_ids=self.specific_file_ids, yield_parents=True)
691
697
if not self.builder.record_root_entry:
704
710
# deleted files matching that filter.
705
711
if is_inside_any(deleted_paths, path):
707
if not self.work_tree.has_filename(path):
708
deleted_paths.add(path)
709
self.reporter.missing(path)
710
deleted_ids.append(file_id)
713
kind = self.work_tree.kind(file_id)
714
# TODO: specific_files filtering before nested tree processing
715
if kind == 'tree-reference' and self.recursive == 'down':
716
self._commit_nested_tree(file_id, path)
717
except errors.NoSuchFile:
713
content_summary = self.work_tree.path_content_summary(path)
714
if not specific_files or is_inside_any(specific_files, path):
715
if content_summary[0] == 'missing':
716
deleted_paths.add(path)
717
self.reporter.missing(path)
718
deleted_ids.append(file_id)
720
# TODO: have the builder do the nested commit just-in-time IF and
722
if content_summary[0] == 'tree-reference':
723
# enforce repository nested tree policy.
724
if (not self.work_tree.supports_tree_reference() or
725
# repository does not support it either.
726
not self.branch.repository._format.supports_tree_reference):
727
content_summary = ('directory',) + content_summary[1:]
728
kind = content_summary[0]
729
# TODO: specific_files filtering before nested tree processing
730
if kind == 'tree-reference':
731
if self.recursive == 'down':
732
nested_revision_id = self._commit_nested_tree(
734
content_summary = content_summary[:3] + (
737
content_summary = content_summary[:3] + (
738
self.work_tree.get_reference_revision(file_id),)
720
740
# Record an entry for this item
721
741
# Note: I don't particularly want to have the existing_ie
723
743
# without it thanks to a unicode normalisation issue. :-(
724
744
definitely_changed = kind != existing_ie.kind
725
745
self._record_entry(path, file_id, specific_files, kind, name,
726
parent_id, definitely_changed, existing_ie, report_changes)
746
parent_id, definitely_changed, existing_ie, report_changes,
728
749
# Unversion IDs that were found to be deleted
729
750
self.work_tree.unversion(deleted_ids)
742
763
sub_tree.branch.repository = \
743
764
self.work_tree.branch.repository
745
sub_tree.commit(message=None, revprops=self.revprops,
766
return sub_tree.commit(message=None, revprops=self.revprops,
746
767
recursive=self.recursive,
747
768
message_callback=self.message_callback,
748
769
timestamp=self.timestamp, timezone=self.timezone,
751
772
strict=self.strict, verbose=self.verbose,
752
773
local=self.local, reporter=self.reporter)
753
774
except errors.PointlessCommit:
775
return self.work_tree.get_reference_revision(file_id)
756
777
def _record_entry(self, path, file_id, specific_files, kind, name,
757
parent_id, definitely_changed, existing_ie=None,
758
report_changes=True):
778
parent_id, definitely_changed, existing_ie, report_changes,
759
780
"Record the new inventory entry for a path if any."
760
781
# mutter('check %s {%s}', path, file_id)
761
782
# mutter('%s selected for commit', path)
765
786
ie = existing_ie.copy()
766
787
ie.revision = None
767
if self.builder.record_entry_contents(ie, self.parent_invs,
768
path, self.work_tree):
788
delta, version_recorded = self.builder.record_entry_contents(ie,
789
self.parent_invs, path, self.work_tree, content_summary)
769
791
self.any_entries_changed = True
770
792
if report_changes:
771
793
self._report_change(ie, path)