72
72
from bzrlib.inventory import Inventory, InventoryEntry, make_entry
73
73
from bzrlib import symbol_versioning
74
74
from bzrlib.urlutils import unescape_for_display
75
from bzrlib.i18n import gettext
77
77
class NullCommitReporter(object):
78
78
"""I report on progress of a commit."""
113
113
note(format, *args)
115
115
def snapshot_change(self, change, path):
116
if path == '' and change in (gettext('added'), gettext('modified')):
116
if path == '' and change in ('added', 'modified'):
118
118
self._note("%s %s", change, path)
127
127
"to started.", DeprecationWarning,
130
self._note(gettext('Committing%s'), location)
130
self._note('Committing%s', location)
132
132
def completed(self, revno, rev_id):
133
self._note(gettext('Committed revision %d.'), revno)
133
self._note('Committed revision %d.', revno)
134
134
# self._note goes to the console too; so while we want to log the
135
135
# rev_id, we can't trivially only log it. (See bug 526425). Long
136
136
# term we should rearrange the reporting structure, but for now
139
139
mutter('Committed revid %s as revno %d.', rev_id, revno)
141
141
def deleted(self, path):
142
self._note(gettext('deleted %s'), path)
142
self._note('deleted %s', path)
144
144
def missing(self, path):
145
self._note(gettext('missing %s'), path)
145
self._note('missing %s', path)
147
147
def renamed(self, change, old_path, new_path):
148
148
self._note('%s %s => %s', change, old_path, new_path)
363
363
self._check_bound_branch(operation, possible_master_transports)
365
365
# Check that the working tree is up to date
366
old_revno, old_revid, new_revno = self._check_out_of_date_tree()
366
old_revno, new_revno = self._check_out_of_date_tree()
368
368
# Complete configuration setup
369
369
if reporter is not None:
411
411
self.builder.abort()
412
412
raise errors.ExcludesUnsupported(self.branch.repository)
414
if self.builder.updates_branch and self.bound_branch:
416
raise AssertionError(
417
"bound branches not supported for commit builders "
418
"that update the branch")
421
415
self.builder.will_record_deletes()
422
416
# find the location being committed to
451
445
self.builder.abort()
454
self._update_branches(old_revno, old_revid, new_revno)
448
self._process_pre_hooks(old_revno, new_revno)
450
# Upload revision data to the master.
451
# this will propagate merged revisions too if needed.
452
if self.bound_branch:
453
self._set_progress_stage("Uploading data to master branch")
454
# 'commit' to the master first so a timeout here causes the
455
# local branch to be out of date
456
(new_revno, self.rev_id) = self.master_branch.import_last_revision_info_and_tags(
457
self.branch, new_revno, self.rev_id, lossy=lossy)
459
self.branch.fetch(self.master_branch, self.rev_id)
461
# and now do the commit locally.
462
self.branch.set_last_revision_info(new_revno, self.rev_id)
464
# Merge local tags to remote
465
if self.bound_branch:
466
self._set_progress_stage("Merging tags to master branch")
467
tag_conflicts = self.branch.tags.merge_to(self.master_branch.tags)
469
warning_lines = [' ' + name for name, _, _ in tag_conflicts]
470
note("Conflicting tags in bound branch:\n" +
471
"\n".join(warning_lines))
456
473
# Make the working tree be up to date with the branch. This
457
474
# includes automatic changes scheduled to be made to the tree, such
464
481
self._process_post_hooks(old_revno, new_revno)
465
482
return self.rev_id
467
def _update_branches(self, old_revno, old_revid, new_revno):
468
"""Update the master and local branch to the new revision.
470
This will try to make sure that the master branch is updated
471
before the local branch.
473
:param old_revno: Revision number of master branch before the
475
:param old_revid: Tip of master branch before the commit
476
:param new_revno: Revision number of the new commit
478
if not self.builder.updates_branch:
479
self._process_pre_hooks(old_revno, new_revno)
481
# Upload revision data to the master.
482
# this will propagate merged revisions too if needed.
483
if self.bound_branch:
484
self._set_progress_stage("Uploading data to master branch")
485
# 'commit' to the master first so a timeout here causes the
486
# local branch to be out of date
487
(new_revno, self.rev_id) = self.master_branch.import_last_revision_info_and_tags(
488
self.branch, new_revno, self.rev_id, lossy=self._lossy)
490
self.branch.fetch(self.master_branch, self.rev_id)
492
# and now do the commit locally.
493
self.branch.set_last_revision_info(new_revno, self.rev_id)
496
self._process_pre_hooks(old_revno, new_revno)
498
# The commit builder will already have updated the branch,
500
self.branch.set_last_revision_info(old_revno, old_revid)
503
# Merge local tags to remote
504
if self.bound_branch:
505
self._set_progress_stage("Merging tags to master branch")
506
tag_updates, tag_conflicts = self.branch.tags.merge_to(
507
self.master_branch.tags)
509
warning_lines = [' ' + name for name, _, _ in tag_conflicts]
510
note( gettext("Conflicting tags in bound branch:\n{0}".format(
511
"\n".join(warning_lines))) )
513
484
def _select_reporter(self):
514
485
"""Select the CommitReporter to use."""
572
543
def _check_out_of_date_tree(self):
573
544
"""Check that the working tree is up to date.
575
:return: old_revision_number, old_revision_id, new_revision_number
546
:return: old_revision_number,new_revision_number tuple
579
549
first_tree_parent = self.work_tree.get_parent_ids()[0]
593
563
# ghost parents never appear in revision history.
595
return old_revno, master_last, new_revno
565
return old_revno,new_revno
597
567
def _process_pre_hooks(self, old_revno, new_revno):
598
568
"""Process any registered pre commit hooks."""
724
694
# Reset the new path (None) and new versioned flag (False)
725
695
change = (change[0], (change[1][0], None), change[2],
726
696
(change[3][0], False)) + change[4:]
727
new_path = change[1][1]
729
697
elif kind == 'tree-reference':
730
698
if self.recursive == 'down':
731
699
self._commit_nested_tree(change[0], change[1][1])
735
703
if new_path is None:
736
704
reporter.deleted(old_path)
737
705
elif old_path is None:
738
reporter.snapshot_change(gettext('added'), new_path)
706
reporter.snapshot_change('added', new_path)
739
707
elif old_path != new_path:
740
reporter.renamed(gettext('renamed'), old_path, new_path)
708
reporter.renamed('renamed', old_path, new_path)
743
711
self.work_tree.branch.repository._format.rich_root_data):
744
712
# Don't report on changes to '' in non rich root
746
reporter.snapshot_change(gettext('modified'), new_path)
714
reporter.snapshot_change('modified', new_path)
747
715
self._next_progress_entry()
748
716
# Unversion IDs that were found to be deleted
749
717
self.deleted_ids = deleted_ids
755
723
if self.specific_files or self.exclude:
756
724
specific_files = self.specific_files or []
757
725
for path, old_ie in self.basis_inv.iter_entries():
758
if self.builder.new_inventory.has_id(old_ie.file_id):
726
if old_ie.file_id in self.builder.new_inventory:
759
727
# already added - skip.
761
729
if (is_inside_any(specific_files, path)
972
940
self.reporter.renamed(change, old_path, path)
973
941
self._next_progress_entry()
975
if change == gettext('unchanged'):
943
if change == 'unchanged':
977
945
self.reporter.snapshot_change(change, path)
978
946
self._next_progress_entry()
995
963
def _emit_progress(self):
996
964
if self.pb_entries_count is not None:
997
text = gettext("{0} [{1}] - Stage").format(self.pb_stage_name,
965
text = "%s [%d] - Stage" % (self.pb_stage_name,
998
966
self.pb_entries_count)
1000
text = gettext("%s - Stage") % (self.pb_stage_name, )
968
text = "%s - Stage" % (self.pb_stage_name, )
1001
969
self.pb.update(text, self.pb_stage_count, self.pb_stage_total)
1003
971
def _set_specific_file_ids(self):