102
100
new_path = change[1][1]
104
102
new_excluded = (new_path is not None and
105
is_inside_any(exclude, new_path))
103
is_inside_any(exclude, new_path))
107
105
old_excluded = (old_path is not None and
108
is_inside_any(exclude, old_path))
106
is_inside_any(exclude, old_path))
110
108
if old_excluded and new_excluded:
213
212
if possible_master_transports is None:
214
213
possible_master_transports = []
215
if (not u'branch-nick' in revprops and
214
if (u'branch-nick' not in revprops and
216
215
branch.repository._format.supports_storing_branch_nick):
217
216
revprops[u'branch-nick'] = branch._get_nick(
252
251
"""Commit working copy as a new revision.
254
253
:param message: the commit message (it or message_callback is required)
255
:param message_callback: A callback: message = message_callback(cmt_obj)
254
:param message_callback: A callback: message =
255
message_callback(cmt_obj)
257
257
:param timestamp: if not None, seconds-since-epoch for a
258
258
postdated/predated commit.
289
289
# XXX: Can be set on __init__ or passed in - this is a bit ugly.
290
290
self.config_stack = config or self.config_stack
291
291
return operation.run(
296
specific_files=specific_files,
298
allow_pointless=allow_pointless,
301
working_tree=working_tree,
304
message_callback=message_callback,
307
possible_master_transports=possible_master_transports,
296
specific_files=specific_files,
298
allow_pointless=allow_pointless,
301
working_tree=working_tree,
304
message_callback=message_callback,
307
possible_master_transports=possible_master_transports,
310
310
def _commit(self, operation, message, timestamp, timezone, committer,
311
specific_files, rev_id, allow_pointless, strict, verbose,
312
working_tree, local, reporter, message_callback, recursive,
313
exclude, possible_master_transports, lossy):
311
specific_files, rev_id, allow_pointless, strict, verbose,
312
working_tree, local, reporter, message_callback, recursive,
313
exclude, possible_master_transports, lossy):
314
314
mutter('preparing to commit')
316
316
if working_tree is None:
325
325
if message is not None:
326
326
if isinstance(message, bytes):
327
327
message = message.decode(get_user_encoding())
328
message_callback = lambda x: message
329
def message_callback(x):
330
332
raise BzrError("The message or message_callback keyword"
331
333
" parameter is required for commit().")
412
414
# Collect the changes
413
415
self._set_progress_stage("Collecting changes", counter=True)
414
416
self._lossy = lossy
415
self.builder = self.branch.get_commit_builder(self.parents,
416
self.config_stack, timestamp, timezone, committer, self.revprops,
417
self.builder = self.branch.get_commit_builder(
418
self.parents, self.config_stack, timestamp, timezone, committer,
419
self.revprops, rev_id, lossy=lossy)
419
421
if self.builder.updates_branch and self.bound_branch:
420
422
self.builder.abort()
463
465
self.work_tree.unversion(self.deleted_paths)
464
466
self._set_progress_stage("Updating the working tree")
465
467
self.work_tree.update_basis_by_delta(self.rev_id,
466
self.builder.get_basis_delta())
468
self.builder.get_basis_delta())
467
469
self.reporter.completed(new_revno, self.rev_id)
468
470
self._process_post_hooks(old_revno, new_revno)
469
471
return self.rev_id
500
502
self._process_pre_hooks(old_revno, new_revno)
503
except BaseException:
502
504
# The commit builder will already have updated the branch,
504
506
self.branch.set_last_revision_info(old_revno, old_revid)
511
513
self.master_branch.tags)
512
514
if tag_conflicts:
513
515
warning_lines = [' ' + name for name, _, _ in tag_conflicts]
514
note( gettext("Conflicting tags in bound branch:\n{0}".format(
515
"\n".join(warning_lines))) )
516
note(gettext("Conflicting tags in bound branch:\n{0}".format(
517
"\n".join(warning_lines))))
517
519
def _select_reporter(self):
518
520
"""Select the CommitReporter to use."""
552
554
# If the master branch is bound, we must fail
553
555
master_bound_location = self.master_branch.get_bound_location()
554
556
if master_bound_location:
555
raise errors.CommitToDoubleBoundBranch(self.branch,
556
self.master_branch, master_bound_location)
557
raise errors.CommitToDoubleBoundBranch(
558
self.branch, self.master_branch, master_bound_location)
558
560
# TODO: jam 20051230 We could automatically push local
559
561
# commits to the remote branch if they would fit.
563
565
# Make sure the local branch is identical to the master
564
master_info = self.master_branch.last_revision_info()
565
local_info = self.branch.last_revision_info()
566
if local_info != master_info:
566
master_revid = self.master_branch.last_revision()
567
local_revid = self.branch.last_revision()
568
if local_revid != master_revid:
567
569
raise errors.BoundBranchOutOfDate(self.branch,
570
572
# Now things are ready to change the master branch
571
573
# so grab the lock
587
589
# - in a checkout scenario the tree may have no
588
590
# parents but the branch may do.
589
591
first_tree_parent = breezy.revision.NULL_REVISION
590
old_revno, master_last = self.master_branch.last_revision_info()
593
old_revno, master_last = self.master_branch.last_revision_info()
594
except errors.UnsupportedOperation:
595
master_last = self.master_branch.last_revision()
596
old_revno = self.branch.revision_id_to_revno(master_last)
591
597
if master_last != first_tree_parent:
592
598
if master_last != breezy.revision.NULL_REVISION:
593
599
raise errors.OutOfDateTree(self.work_tree)
615
621
# this would be nicer with twisted.python.reflect.namedAny
616
622
for hook in hooks:
617
623
result = eval(hook + '(branch, rev_id)',
618
{'branch':self.branch,
620
'rev_id':self.rev_id})
624
{'branch': self.branch,
626
'rev_id': self.rev_id})
621
627
# process new style post commit hooks
622
628
self._process_hooks("post_commit", old_revno, new_revno)
643
649
if hook_name == "pre_commit":
644
650
future_tree = self.builder.revision_tree()
645
651
tree_delta = future_tree.changes_from(self.basis_tree,
648
654
for hook in Branch.hooks[hook_name]:
649
655
# show the running hook in the progress bar. As hooks may
671
677
mutter("Selecting files for commit with filter %r", specific_files)
673
679
self._check_strict()
674
iter_changes = self.work_tree.iter_changes(self.basis_tree,
675
specific_files=specific_files)
680
iter_changes = self.work_tree.iter_changes(
681
self.basis_tree, specific_files=specific_files)
677
683
iter_changes = filter_excluded(iter_changes, self.exclude)
678
684
iter_changes = self._filter_iter_changes(iter_changes)
679
for file_id, path, fs_hash in self.builder.record_iter_changes(
680
self.work_tree, self.basis_revid, iter_changes):
681
self.work_tree._observed_sha1(file_id, path, fs_hash)
685
for path, fs_hash in self.builder.record_iter_changes(
686
self.work_tree, self.basis_revid, iter_changes):
687
self.work_tree._observed_sha1(path, fs_hash)
683
689
def _filter_iter_changes(self, iter_changes):
684
690
"""Process iter_changes.
686
This method reports on the changes in iter_changes to the user, and
692
This method reports on the changes in iter_changes to the user, and
687
693
converts 'missing' entries in the iter_changes iterator to 'deleted'
688
694
entries. 'missing' entries have their
705
711
if report_changes:
706
712
reporter.missing(new_path)
707
if change[6][0] == 'symlink' and not has_symlinks():
713
if change[6][0] == 'symlink' and not self.work_tree.supports_symlinks():
708
714
trace.warning('Ignoring "%s" as symlinks are not '
709
715
'supported on this platform.' % (change[1][0],))
711
717
deleted_paths.append(change[1][1])
712
718
# Reset the new path (None) and new versioned flag (False)
713
719
change = (change[0], (change[1][0], None), change[2],
714
(change[3][0], False)) + change[4:]
720
(change[3][0], False)) + change[4:]
715
721
new_path = change[1][1]
716
722
versioned = False
717
723
elif kind == 'tree-reference':
718
724
if self.recursive == 'down':
719
self._commit_nested_tree(change[0], change[1][1])
725
self._commit_nested_tree(change[1][1])
720
726
if change[3][0] or change[3][1]:
722
728
if report_changes:
725
731
elif old_path is None:
726
732
reporter.snapshot_change(gettext('added'), new_path)
727
733
elif old_path != new_path:
728
reporter.renamed(gettext('renamed'), old_path, new_path)
734
reporter.renamed(gettext('renamed'),
731
self.work_tree.branch.repository._format.rich_root_data):
738
or self.work_tree.branch.repository._format.rich_root_data):
732
739
# Don't report on changes to '' in non rich root
734
reporter.snapshot_change(gettext('modified'), new_path)
741
reporter.snapshot_change(
742
gettext('modified'), new_path)
735
743
self._next_progress_entry()
736
744
# Unversion files that were found to be deleted
737
745
self.deleted_paths = deleted_paths
745
753
for unknown in self.work_tree.unknowns():
746
754
raise StrictCommitFailed()
748
def _commit_nested_tree(self, file_id, path):
756
def _commit_nested_tree(self, path):
749
757
"Commit a nested tree."
750
sub_tree = self.work_tree.get_nested_tree(path, file_id)
758
sub_tree = self.work_tree.get_nested_tree(path)
751
759
# FIXME: be more comprehensive here:
752
760
# this works when both trees are in --trees repository,
753
761
# but when both are bound to a different repository,
755
763
# finally implement the explicit-caches approach design
756
764
# a while back - RBC 20070306.
757
765
if sub_tree.branch.repository.has_same_location(
758
self.work_tree.branch.repository):
766
self.work_tree.branch.repository):
759
767
sub_tree.branch.repository = \
760
768
self.work_tree.branch.repository
762
770
return sub_tree.commit(message=None, revprops=self.revprops,
763
recursive=self.recursive,
764
message_callback=self.message_callback,
765
timestamp=self.timestamp, timezone=self.timezone,
766
committer=self.committer,
767
allow_pointless=self.allow_pointless,
768
strict=self.strict, verbose=self.verbose,
769
local=self.local, reporter=self.reporter)
771
recursive=self.recursive,
772
message_callback=self.message_callback,
773
timestamp=self.timestamp,
774
timezone=self.timezone,
775
committer=self.committer,
776
allow_pointless=self.allow_pointless,
777
strict=self.strict, verbose=self.verbose,
778
local=self.local, reporter=self.reporter)
770
779
except PointlessCommit:
771
return self.work_tree.get_reference_revision(path, file_id)
780
return self.work_tree.get_reference_revision(path)
773
782
def _set_progress_stage(self, name, counter=False):
774
783
"""Set the progress stage and emit an update to the progress bar."""
788
797
def _emit_progress(self):
789
798
if self.pb_entries_count is not None:
790
799
text = gettext("{0} [{1}] - Stage").format(self.pb_stage_name,
791
self.pb_entries_count)
800
self.pb_entries_count)
793
802
text = gettext("%s - Stage") % (self.pb_stage_name, )
794
803
self.pb.update(text, self.pb_stage_count, self.pb_stage_total)