/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/commit.py

  • Committer: Jelmer Vernooij
  • Date: 2019-03-04 00:16:27 UTC
  • mfrom: (7293 work)
  • mto: This revision was merged to the branch mainline in revision 7318.
  • Revision ID: jelmer@jelmer.uk-20190304001627-v6u7o6pf97tukhek
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
    debug,
55
55
    errors,
56
56
    trace,
57
 
    tree,
58
57
    ui,
59
58
    )
60
59
from .branch import Branch
68
67
                      has_symlinks,
69
68
                      is_inside_any,
70
69
                      minimum_path_selection,
71
 
                      splitpath,
72
70
                      )
73
71
from .trace import mutter, note, is_quiet
74
72
from .urlutils import unescape_for_display
102
100
        new_path = change[1][1]
103
101
 
104
102
        new_excluded = (new_path is not None and
105
 
            is_inside_any(exclude, new_path))
 
103
                        is_inside_any(exclude, new_path))
106
104
 
107
105
        old_excluded = (old_path is not None and
108
 
            is_inside_any(exclude, old_path))
 
106
                        is_inside_any(exclude, old_path))
109
107
 
110
108
        if old_excluded and new_excluded:
111
109
            continue
195
193
            the working directory; these should be removed from the
196
194
            working inventory.
197
195
    """
 
196
 
198
197
    def __init__(self,
199
198
                 reporter=None,
200
199
                 config_stack=None):
212
211
            revprops = {}
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(
218
217
                local,
225
224
                for individual in authors:
226
225
                    if '\n' in individual:
227
226
                        raise AssertionError('\\n is not a valid character '
228
 
                                'in an author identity')
 
227
                                             'in an author identity')
229
228
                revprops[u'authors'] = '\n'.join(authors)
230
229
        return revprops
231
230
 
252
251
        """Commit working copy as a new revision.
253
252
 
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)
256
256
 
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(
292
 
               message=message,
293
 
               timestamp=timestamp,
294
 
               timezone=timezone,
295
 
               committer=committer,
296
 
               specific_files=specific_files,
297
 
               rev_id=rev_id,
298
 
               allow_pointless=allow_pointless,
299
 
               strict=strict,
300
 
               verbose=verbose,
301
 
               working_tree=working_tree,
302
 
               local=local,
303
 
               reporter=reporter,
304
 
               message_callback=message_callback,
305
 
               recursive=recursive,
306
 
               exclude=exclude,
307
 
               possible_master_transports=possible_master_transports,
308
 
               lossy=lossy)
 
292
            message=message,
 
293
            timestamp=timestamp,
 
294
            timezone=timezone,
 
295
            committer=committer,
 
296
            specific_files=specific_files,
 
297
            rev_id=rev_id,
 
298
            allow_pointless=allow_pointless,
 
299
            strict=strict,
 
300
            verbose=verbose,
 
301
            working_tree=working_tree,
 
302
            local=local,
 
303
            reporter=reporter,
 
304
            message_callback=message_callback,
 
305
            recursive=recursive,
 
306
            exclude=exclude,
 
307
            possible_master_transports=possible_master_transports,
 
308
            lossy=lossy)
309
309
 
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')
315
315
 
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
 
328
 
 
329
                def message_callback(x):
 
330
                    return message
329
331
            else:
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
 
            rev_id, lossy=lossy)
 
417
        self.builder = self.branch.get_commit_builder(
 
418
            self.parents, self.config_stack, timestamp, timezone, committer,
 
419
            self.revprops, rev_id, lossy=lossy)
418
420
 
419
421
        if self.builder.updates_branch and self.bound_branch:
420
422
            self.builder.abort()
449
451
            # Add revision data to the local branch
450
452
            self.rev_id = self.builder.commit(self.message)
451
453
 
452
 
        except Exception as e:
 
454
        except Exception:
453
455
            mutter("aborting commit write group because of exception:")
454
456
            trace.log_exception_quietly()
455
457
            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
498
500
        else:
499
501
            try:
500
502
                self._process_pre_hooks(old_revno, new_revno)
501
 
            except:
 
503
            except BaseException:
502
504
                # The commit builder will already have updated the branch,
503
505
                # revert it.
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))))
516
518
 
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)
557
559
 
558
560
        # TODO: jam 20051230 We could automatically push local
559
561
        #       commits to the remote branch if they would fit.
561
563
        #       to local.
562
564
 
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,
568
 
                    self.master_branch)
 
570
                                              self.master_branch)
569
571
 
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()
 
592
        try:
 
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,
619
 
                               'breezy':breezy,
620
 
                               'rev_id':self.rev_id})
 
624
                              {'branch': self.branch,
 
625
                               'breezy': breezy,
 
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)
623
629
 
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,
646
 
                                             include_root=True)
 
652
                                                  include_root=True)
647
653
 
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)
672
678
 
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)
676
682
        if self.exclude:
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)
682
688
 
683
689
    def _filter_iter_changes(self, iter_changes):
684
690
        """Process iter_changes.
685
691
 
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
689
695
 
704
710
                # 'missing' path
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],))
710
716
                    continue
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]:
721
727
                yield change
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'),
 
735
                                         old_path, new_path)
729
736
                    else:
730
 
                        if (new_path or 
731
 
                            self.work_tree.branch.repository._format.rich_root_data):
 
737
                        if (new_path
 
738
                                or self.work_tree.branch.repository._format.rich_root_data):
732
739
                            # Don't report on changes to '' in non rich root
733
740
                            # repositories.
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()
747
755
 
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
761
769
        try:
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)
772
781
 
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)
792
801
        else:
793
802
            text = gettext("%s - Stage") % (self.pb_stage_name, )
794
803
        self.pb.update(text, self.pb_stage_count, self.pb_stage_total)