232
233
:param verbose: if True and the reporter is not None, report everything
233
234
:param recursive: If set to 'down', commit in any subtrees that have
234
235
pending changes of any sort during this commit.
236
:param exclude: None or a list of relative paths to exclude from the
237
commit. Pending changes to excluded files will be ignored by the
236
240
mutter('preparing to commit')
255
259
self.bound_branch = None
256
260
self.any_entries_changed = False
257
261
self.any_entries_deleted = False
262
if exclude is not None:
263
self.exclude = sorted(
264
minimum_path_selection(exclude))
258
267
self.local = local
259
268
self.master_branch = None
260
269
self.master_locked = False
329
338
self.pb.show_count = True
330
339
self.pb.show_bar = True
341
self.basis_inv = self.basis_tree.inventory
342
self._gather_parents()
332
343
# After a merge, a selected file commit is not supported.
333
344
# See 'bzr help merge' for an explanation as to why.
334
self.basis_inv = self.basis_tree.inventory
335
self._gather_parents()
336
345
if len(self.parents) > 1 and self.specific_files:
337
346
raise errors.CannotCommitSelectedFileMerge(self.specific_files)
347
# Excludes are a form of selected file commit.
348
if len(self.parents) > 1 and self.exclude:
349
raise errors.CannotCommitSelectedFileMerge(self.exclude)
339
351
# Collect the changes
340
352
self._set_progress_stage("Collecting changes",
366
378
# Prompt the user for a commit message if none provided
367
379
message = message_callback(self)
368
assert isinstance(message, unicode), type(message)
369
380
self.message = message
370
381
self._escape_commit_message()
649
660
# in bugs like #46635. Any reason not to use/enhance Tree.changes_from?
650
661
# ADHB 11-07-2006
652
specific_files = self.specific_files
663
exclude = self.exclude
664
specific_files = self.specific_files or []
653
665
mutter("Selecting files for commit with filter %s", specific_files)
655
667
# Build the new inventory
656
self._populate_from_inventory(specific_files)
668
self._populate_from_inventory()
658
670
# If specific files are selected, then all un-selected files must be
659
671
# recorded in their previous state. For more details, see
660
672
# https://lists.ubuntu.com/archives/bazaar/2007q3/028476.html.
673
if specific_files or exclude:
662
674
for path, old_ie in self.basis_inv.iter_entries():
663
675
if old_ie.file_id in self.builder.new_inventory:
664
676
# already added - skip.
666
if is_inside_any(specific_files, path):
667
# was inside the selected path, if not present it has been
678
if (is_inside_any(specific_files, path)
679
and not is_inside_any(exclude, path)):
680
# was inside the selected path, and not excluded - if not
681
# present it has been deleted so skip.
683
# From here down it was either not selected, or was excluded:
670
684
if old_ie.kind == 'directory':
671
685
self._next_progress_entry()
672
# not in final inv yet, was not in the selected files, so is an
673
# entry to be preserved unaltered.
686
# We preserve the entry unaltered.
674
687
ie = old_ie.copy()
675
688
# Note: specific file commits after a merge are currently
676
689
# prohibited. This test is for sanity/safety in case it's
698
711
self._basis_delta.append((path, None, file_id, None))
699
712
self.reporter.deleted(path)
701
def _populate_from_inventory(self, specific_files):
714
def _populate_from_inventory(self):
702
715
"""Populate the CommitBuilder by walking the working tree inventory."""
704
717
# raise an exception as soon as we find a single unknown.
705
718
for unknown in self.work_tree.unknowns():
706
719
raise StrictCommitFailed()
721
specific_files = self.specific_files
722
exclude = self.exclude
708
723
report_changes = self.reporter.is_verbose()
710
725
# A tree of paths that have been deleted. E.g. if foo/bar has been
713
728
# XXX: Note that entries may have the wrong kind because the entry does
714
729
# not reflect the status on disk.
715
730
work_inv = self.work_tree.inventory
731
# NB: entries will include entries within the excluded ids/paths
732
# because iter_entries_by_dir has no 'exclude' facility today.
716
733
entries = work_inv.iter_entries_by_dir(
717
734
specific_file_ids=self.specific_file_ids, yield_parents=True)
718
735
for path, existing_ie in entries:
740
757
if deleted_dict is not None:
741
758
# the path has a deleted parent, do not add it.
760
if exclude and is_inside_any(exclude, path):
761
# Skip excluded paths. Excluded paths are processed by
762
# _update_builder_with_changes.
743
764
content_summary = self.work_tree.path_content_summary(path)
744
765
# Note that when a filter of specific files is given, we must only
745
766
# skip/record deleted files matching that filter.