292
291
raise errors.CannotCommitSelectedFileMerge(self.specific_files)
294
293
# Collect the changes
295
self._emit_progress_set_stage("Collecting changes",
294
self._set_progress_stage("Collecting changes",
296
295
entries_title="Directory")
297
296
self.builder = self.branch.get_commit_builder(self.parents,
298
297
self.config, timestamp, timezone, committer, revprops, rev_id)
303
302
# ADHB 2006-08-08: If this is done, populate_new_inv should not add
304
303
# weave lines, because nothing should be recorded until it is known
305
304
# that commit will succeed.
306
self._emit_progress_set_stage("Saving data locally")
305
self._set_progress_stage("Saving data locally")
307
306
self.builder.finish_inventory()
309
308
# Prompt the user for a commit message if none provided
318
317
# Upload revision data to the master.
319
318
# this will propagate merged revisions too if needed.
320
319
if self.bound_branch:
321
self._emit_progress_set_stage("Uploading data to master branch")
320
self._set_progress_stage("Uploading data to master branch")
322
321
self.master_branch.repository.fetch(self.branch.repository,
323
322
revision_id=self.rev_id)
324
323
# now the master has the revision data
331
330
self.branch.set_last_revision_info(new_revno, self.rev_id)
333
332
# Make the working tree up to date with the branch
334
self._emit_progress_set_stage("Updating the working tree")
333
self._set_progress_stage("Updating the working tree")
335
334
rev_tree = self.builder.revision_tree()
336
335
self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
337
336
self.reporter.completed(new_revno, self.rev_id)
464
463
def _process_hooks(self, old_revno, new_revno):
465
464
"""Process any registered commit hooks."""
466
465
# Process the post commit hooks, if any
467
self._emit_progress_set_stage("Running post commit hooks")
466
self._set_progress_stage("Running post commit hooks")
468
467
# old style commit hooks - should be deprecated ? (obsoleted in
470
469
if self.config.post_commit() is not None:
598
597
self.builder.new_inventory.add(self.basis_inv.root.copy())
599
598
root_added_already = True
601
# Build the new inventory. _populate_from_tree() is the preferred
602
# direction here but it doesn't support multiple parents yet,
603
# it triggers a unicode normalisation issue in the test suite and
604
# it needs more testing.
605
populator = self._populate_from_inventory
606
#if len(self.parents) == 1:
607
# populator = self._populate_from_tree
608
populator(specific_files, root_added_already)
600
# Build the new inventory
601
self._populate_from_inventory(specific_files, root_added_already)
610
603
# If specific files/directories were nominated, it is possible
611
604
# that some data from outside those needs to be preserved from
685
678
# Unversion IDs that were found to be deleted
686
679
self.work_tree.unversion(deleted_ids)
688
def _populate_from_tree(self, specific_files, root_added_already):
689
"""Populate the CommitBuilder by walking the working tree."""
690
# Until trees supports an "iter_commitable" iterator that
691
# understand multiple parents, this assertion is required.
692
assert len(self.parents) == 1
695
deleted_paths = set()
696
entries = self.work_tree._iter_changes(self.basis_tree,
697
include_unchanged=True, want_unversioned=True,
698
require_versioned=False)
699
if root_added_already:
701
for entry in entries:
702
(file_id, paths, changed_content, versioned_flags, parents, names,
703
kinds, executables) = entry
705
if kind == 'directory':
706
self._emit_progress_next_entry()
708
# Skip unknowns unless strict mode
709
if versioned_flags == (False,False):
711
raise StrictCommitFailed()
715
# Skip missing files (may auto-delete these one day)
716
# Note that when a filter of specific files is given, we must
717
# only skip/record deleted files matching that filter.
720
if is_inside_any(deleted_paths, path):
722
if not specific_files or is_inside_any(specific_files, path):
723
deleted_paths.add(path)
724
self.reporter.missing(path)
725
deleted_ids.append(file_id)
727
# It's missing but still needs to be recorded
734
parent = parents[index]
737
# TODO: specific_files filtering before nested tree processing?
738
# TODO: keep track of nested trees and don't recurse into them?
739
if kind == 'tree-reference' and self.recursive == 'down':
740
self._commit_nested_tree(path)
742
# Record an entry for this item
743
self._record_entry(path, file_id, specific_files, kind,
744
name, parent, changed_content, None)
745
# Note: If the iterator passed back the sha here we could
746
# set it and the executable info *now* into the inventory entry
747
# saving look ups later
749
# Unversion IDs that were found to be deleted
750
# Note: the logic above collects some IDs already gone so
751
# we walk the list and trap the exception
752
for id in deleted_ids:
754
self.work_tree.unversion([id])
758
681
def _commit_nested_tree(self, path):
759
682
"Commit a nested tree."
760
683
sub_tree = WorkingTree.open(self.work_tree.abspath(path))
825
748
self.reporter.snapshot_change(change, path)
827
def _emit_progress_set_stage(self, name, entries_title=None):
750
def _set_progress_stage(self, name, entries_title=None):
828
751
"""Set the progress stage and emit an update to the progress bar."""
829
752
self.pb_stage_name = name
830
753
self.pb_stage_count += 1