~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

  • Committer: Patch Queue Manager
  • Date: 2015-12-17 18:39:00 UTC
  • mfrom: (6606.1.2 fix-float)
  • Revision ID: pqm@pqm.ubuntu.com-20151217183900-0719du2uv1kwu3lc
(vila) Inline testtools private method to fix an issue in xenial (the
 private implementation has changed in an backward incompatible way).
 (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
from __future__ import absolute_import
17
18
 
18
19
# The newly committed revision is going to have a shape corresponding
19
20
# to that of the working tree.  Files that are not in the
165
166
    """
166
167
    def __init__(self,
167
168
                 reporter=None,
168
 
                 config=None):
 
169
                 config_stack=None):
169
170
        """Create a Commit object.
170
171
 
171
172
        :param reporter: the default reporter to use or None to decide later
172
173
        """
173
174
        self.reporter = reporter
174
 
        self.config = config
 
175
        self.config_stack = config_stack
175
176
 
176
177
    @staticmethod
177
178
    def update_revprops(revprops, branch, authors=None, author=None,
268
269
        operation = OperationWithCleanups(self._commit)
269
270
        self.revprops = revprops or {}
270
271
        # XXX: Can be set on __init__ or passed in - this is a bit ugly.
271
 
        self.config = config or self.config
 
272
        self.config_stack = config or self.config_stack
272
273
        return operation.run(
273
274
               message=message,
274
275
               timestamp=timestamp,
363
364
        self._check_bound_branch(operation, possible_master_transports)
364
365
 
365
366
        # Check that the working tree is up to date
366
 
        old_revno, new_revno = self._check_out_of_date_tree()
 
367
        old_revno, old_revid, new_revno = self._check_out_of_date_tree()
367
368
 
368
369
        # Complete configuration setup
369
370
        if reporter is not None:
370
371
            self.reporter = reporter
371
372
        elif self.reporter is None:
372
373
            self.reporter = self._select_reporter()
373
 
        if self.config is None:
374
 
            self.config = self.branch.get_config()
 
374
        if self.config_stack is None:
 
375
            self.config_stack = self.work_tree.get_config_stack()
375
376
 
376
377
        self._set_specific_file_ids()
377
378
 
405
406
        self._set_progress_stage("Collecting changes", counter=True)
406
407
        self._lossy = lossy
407
408
        self.builder = self.branch.get_commit_builder(self.parents,
408
 
            self.config, timestamp, timezone, committer, self.revprops,
 
409
            self.config_stack, timestamp, timezone, committer, self.revprops,
409
410
            rev_id, lossy=lossy)
410
411
        if not self.builder.supports_record_entry_contents and self.exclude:
411
412
            self.builder.abort()
412
413
            raise errors.ExcludesUnsupported(self.branch.repository)
413
414
 
 
415
        if self.builder.updates_branch and self.bound_branch:
 
416
            self.builder.abort()
 
417
            raise AssertionError(
 
418
                "bound branches not supported for commit builders "
 
419
                "that update the branch")
 
420
 
414
421
        try:
415
422
            self.builder.will_record_deletes()
416
423
            # find the location being committed to
445
452
            self.builder.abort()
446
453
            raise
447
454
 
448
 
        self._process_pre_hooks(old_revno, new_revno)
449
 
 
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)
458
 
            if lossy:
459
 
                self.branch.fetch(self.master_branch, self.rev_id)
460
 
 
461
 
        # and now do the commit locally.
462
 
        self.branch.set_last_revision_info(new_revno, self.rev_id)
463
 
 
464
 
        # Merge local tags to remote
465
 
        if self.bound_branch:
466
 
            self._set_progress_stage("Merging tags to master branch")
467
 
            tag_updates, tag_conflicts = self.branch.tags.merge_to(
468
 
                self.master_branch.tags)
469
 
            if tag_conflicts:
470
 
                warning_lines = ['    ' + name for name, _, _ in tag_conflicts]
471
 
                note( gettext("Conflicting tags in bound branch:\n{0}".format(
472
 
                    "\n".join(warning_lines))) )
 
455
        self._update_branches(old_revno, old_revid, new_revno)
473
456
 
474
457
        # Make the working tree be up to date with the branch. This
475
458
        # includes automatic changes scheduled to be made to the tree, such
482
465
        self._process_post_hooks(old_revno, new_revno)
483
466
        return self.rev_id
484
467
 
 
468
    def _update_branches(self, old_revno, old_revid, new_revno):
 
469
        """Update the master and local branch to the new revision.
 
470
 
 
471
        This will try to make sure that the master branch is updated
 
472
        before the local branch.
 
473
 
 
474
        :param old_revno: Revision number of master branch before the
 
475
            commit
 
476
        :param old_revid: Tip of master branch before the commit
 
477
        :param new_revno: Revision number of the new commit
 
478
        """
 
479
        if not self.builder.updates_branch:
 
480
            self._process_pre_hooks(old_revno, new_revno)
 
481
 
 
482
            # Upload revision data to the master.
 
483
            # this will propagate merged revisions too if needed.
 
484
            if self.bound_branch:
 
485
                self._set_progress_stage("Uploading data to master branch")
 
486
                # 'commit' to the master first so a timeout here causes the
 
487
                # local branch to be out of date
 
488
                (new_revno, self.rev_id) = self.master_branch.import_last_revision_info_and_tags(
 
489
                    self.branch, new_revno, self.rev_id, lossy=self._lossy)
 
490
                if self._lossy:
 
491
                    self.branch.fetch(self.master_branch, self.rev_id)
 
492
 
 
493
            # and now do the commit locally.
 
494
            self.branch.set_last_revision_info(new_revno, self.rev_id)
 
495
        else:
 
496
            try:
 
497
                self._process_pre_hooks(old_revno, new_revno)
 
498
            except:
 
499
                # The commit builder will already have updated the branch,
 
500
                # revert it.
 
501
                self.branch.set_last_revision_info(old_revno, old_revid)
 
502
                raise
 
503
 
 
504
        # Merge local tags to remote
 
505
        if self.bound_branch:
 
506
            self._set_progress_stage("Merging tags to master branch")
 
507
            tag_updates, tag_conflicts = self.branch.tags.merge_to(
 
508
                self.master_branch.tags)
 
509
            if tag_conflicts:
 
510
                warning_lines = ['    ' + name for name, _, _ in tag_conflicts]
 
511
                note( gettext("Conflicting tags in bound branch:\n{0}".format(
 
512
                    "\n".join(warning_lines))) )
 
513
 
485
514
    def _select_reporter(self):
486
515
        """Select the CommitReporter to use."""
487
516
        if is_quiet():
544
573
    def _check_out_of_date_tree(self):
545
574
        """Check that the working tree is up to date.
546
575
 
547
 
        :return: old_revision_number,new_revision_number tuple
 
576
        :return: old_revision_number, old_revision_id, new_revision_number
 
577
            tuple
548
578
        """
549
579
        try:
550
580
            first_tree_parent = self.work_tree.get_parent_ids()[0]
563
593
        else:
564
594
            # ghost parents never appear in revision history.
565
595
            new_revno = 1
566
 
        return old_revno,new_revno
 
596
        return old_revno, master_last, new_revno
567
597
 
568
598
    def _process_pre_hooks(self, old_revno, new_revno):
569
599
        """Process any registered pre commit hooks."""
575
605
        # Process the post commit hooks, if any
576
606
        self._set_progress_stage("Running post_commit hooks")
577
607
        # old style commit hooks - should be deprecated ? (obsoleted in
578
 
        # 0.15)
579
 
        if self.config.post_commit() is not None:
580
 
            hooks = self.config.post_commit().split(' ')
 
608
        # 0.15^H^H^H^H 2.5.0)
 
609
        post_commit = self.config_stack.get('post_commit')
 
610
        if post_commit is not None:
 
611
            hooks = post_commit.split(' ')
581
612
            # this would be nicer with twisted.python.reflect.namedAny
582
613
            for hook in hooks:
583
614
                result = eval(hook + '(branch, rev_id)',
636
667
        # entries and the order is preserved when doing this.
637
668
        if self.use_record_iter_changes:
638
669
            return
639
 
        self.basis_inv = self.basis_tree.inventory
 
670
        self.basis_inv = self.basis_tree.root_inventory
640
671
        self.parent_invs = [self.basis_inv]
641
672
        for revision in self.parents[1:]:
642
673
            if self.branch.repository.has_revision(revision):
803
834
        deleted_paths = {}
804
835
        # XXX: Note that entries may have the wrong kind because the entry does
805
836
        # not reflect the status on disk.
806
 
        work_inv = self.work_tree.inventory
807
837
        # NB: entries will include entries within the excluded ids/paths
808
838
        # because iter_entries_by_dir has no 'exclude' facility today.
809
 
        entries = work_inv.iter_entries_by_dir(
 
839
        entries = self.work_tree.iter_entries_by_dir(
810
840
            specific_file_ids=self.specific_file_ids, yield_parents=True)
811
841
        for path, existing_ie in entries:
812
842
            file_id = existing_ie.file_id