~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Martin Pool
  • Date: 2010-02-25 06:17:27 UTC
  • mfrom: (5055 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5057.
  • Revision ID: mbp@sourcefrog.net-20100225061727-4sd9lt0qmdc6087t
merge news

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
import warnings
17
18
 
18
19
from bzrlib import (
19
20
    branch as _mod_branch,
26
27
    merge3,
27
28
    osutils,
28
29
    patiencediff,
29
 
    progress,
30
30
    revision as _mod_revision,
31
31
    textfile,
32
32
    trace,
36
36
    ui,
37
37
    versionedfile
38
38
    )
 
39
from bzrlib.cleanup import OperationWithCleanups
39
40
from bzrlib.symbol_versioning import (
40
41
    deprecated_in,
41
42
    deprecated_method,
45
46
 
46
47
def transform_tree(from_tree, to_tree, interesting_ids=None):
47
48
    from_tree.lock_tree_write()
48
 
    try:
49
 
        merge_inner(from_tree.branch, to_tree, from_tree, ignore_zero=True,
50
 
                    interesting_ids=interesting_ids, this_tree=from_tree)
51
 
    finally:
52
 
        from_tree.unlock()
 
49
    operation = OperationWithCleanups(merge_inner)
 
50
    operation.add_cleanup(from_tree.unlock)
 
51
    operation.run_simple(from_tree.branch, to_tree, from_tree,
 
52
        ignore_zero=True, interesting_ids=interesting_ids, this_tree=from_tree)
53
53
 
54
54
 
55
55
class MergeHooks(hooks.Hooks):
130
130
        """
131
131
        affected_files = self.affected_files
132
132
        if affected_files is None:
133
 
            config = self.merger.this_tree.branch.get_config()
 
133
            config = self.merger.this_branch.get_config()
134
134
            # Until bzr provides a better policy for caching the config, we
135
135
            # just add the part we're interested in to the params to avoid
136
136
            # reading the config files repeatedly (bazaar.conf, location.conf,
237
237
        self.interesting_files = None
238
238
        self.show_base = False
239
239
        self.reprocess = False
240
 
        if pb is None:
241
 
            pb = progress.DummyProgress()
242
 
        self._pb = pb
 
240
        if pb is not None:
 
241
            warnings.warn("pb parameter to Merger() is deprecated and ignored")
243
242
        self.pp = None
244
243
        self.recurse = recurse
245
244
        self.change_reporter = change_reporter
455
454
    def _add_parent(self):
456
455
        new_parents = self.this_tree.get_parent_ids() + [self.other_rev_id]
457
456
        new_parent_trees = []
 
457
        operation = OperationWithCleanups(self.this_tree.set_parent_trees)
458
458
        for revision_id in new_parents:
459
459
            try:
460
460
                tree = self.revision_tree(revision_id)
462
462
                tree = None
463
463
            else:
464
464
                tree.lock_read()
 
465
                operation.add_cleanup(tree.unlock)
465
466
            new_parent_trees.append((revision_id, tree))
466
 
        try:
467
 
            self.this_tree.set_parent_trees(new_parent_trees,
468
 
                                            allow_leftmost_as_ghost=True)
469
 
        finally:
470
 
            for _revision_id, tree in new_parent_trees:
471
 
                if tree is not None:
472
 
                    tree.unlock()
 
467
        operation.run_simple(new_parent_trees, allow_leftmost_as_ghost=True)
473
468
 
474
469
    def set_other(self, other_revision, possible_transports=None):
475
470
        """Set the revision and tree to merge from.
598
593
                  'other_tree': self.other_tree,
599
594
                  'interesting_ids': self.interesting_ids,
600
595
                  'interesting_files': self.interesting_files,
601
 
                  'pp': self.pp, 'this_branch': self.this_branch,
 
596
                  'this_branch': self.this_branch,
602
597
                  'do_merge': False}
603
598
        if self.merge_type.requires_base:
604
599
            kwargs['base_tree'] = self.base_tree
622
617
        if self._is_criss_cross and getattr(self.merge_type,
623
618
                                            'supports_lca_trees', False):
624
619
            kwargs['lca_trees'] = self._lca_trees
625
 
        return self.merge_type(pb=self._pb,
 
620
        return self.merge_type(pb=None,
626
621
                               change_reporter=self.change_reporter,
627
622
                               **kwargs)
628
623
 
629
 
    def _do_merge_to(self, merge):
 
624
    def _do_merge_to(self):
 
625
        merge = self.make_merger()
630
626
        if self.other_branch is not None:
631
627
            self.other_branch.update_references(self.this_branch)
632
628
        merge.do_merge()
646
642
                    sub_tree.branch.repository.revision_tree(base_revision)
647
643
                sub_merge.base_rev_id = base_revision
648
644
                sub_merge.do_merge()
 
645
        return merge
649
646
 
650
647
    def do_merge(self):
 
648
        operation = OperationWithCleanups(self._do_merge_to)
651
649
        self.this_tree.lock_tree_write()
652
 
        try:
653
 
            if self.base_tree is not None:
654
 
                self.base_tree.lock_read()
655
 
            try:
656
 
                if self.other_tree is not None:
657
 
                    self.other_tree.lock_read()
658
 
                try:
659
 
                    merge = self.make_merger()
660
 
                    self._do_merge_to(merge)
661
 
                finally:
662
 
                    if self.other_tree is not None:
663
 
                        self.other_tree.unlock()
664
 
            finally:
665
 
                if self.base_tree is not None:
666
 
                    self.base_tree.unlock()
667
 
        finally:
668
 
            self.this_tree.unlock()
 
650
        operation.add_cleanup(self.this_tree.unlock)
 
651
        if self.base_tree is not None:
 
652
            self.base_tree.lock_read()
 
653
            operation.add_cleanup(self.base_tree.unlock)
 
654
        if self.other_tree is not None:
 
655
            self.other_tree.lock_read()
 
656
            operation.add_cleanup(self.other_tree.unlock)
 
657
        merge = operation.run_simple()
669
658
        if len(merge.cooked_conflicts) == 0:
670
659
            if not self.ignore_zero and not trace.is_quiet():
671
660
                trace.note("All changes applied successfully.")
706
695
 
707
696
    def __init__(self, working_tree, this_tree, base_tree, other_tree,
708
697
                 interesting_ids=None, reprocess=False, show_base=False,
709
 
                 pb=progress.DummyProgress(), pp=None, change_reporter=None,
 
698
                 pb=None, pp=None, change_reporter=None,
710
699
                 interesting_files=None, do_merge=True,
711
700
                 cherrypick=False, lca_trees=None, this_branch=None):
712
701
        """Initialize the merger object and perform the merge.
722
711
        :param: reprocess If True, perform conflict-reduction processing.
723
712
        :param show_base: If True, show the base revision in text conflicts.
724
713
            (incompatible with reprocess)
725
 
        :param pb: A Progress bar
 
714
        :param pb: ignored
726
715
        :param pp: A ProgressPhase object
727
716
        :param change_reporter: An object that should report changes made
728
717
        :param interesting_files: The tree-relative paths of files that should
755
744
        # making sure we haven't missed any corner cases.
756
745
        # if lca_trees is None:
757
746
        #     self._lca_trees = [self.base_tree]
758
 
        self.pb = pb
759
 
        self.pp = pp
760
747
        self.change_reporter = change_reporter
761
748
        self.cherrypick = cherrypick
762
 
        if self.pp is None:
763
 
            self.pp = progress.ProgressPhase("Merge phase", 3, self.pb)
764
749
        if do_merge:
765
750
            self.do_merge()
 
751
        if pp is not None:
 
752
            warnings.warn("pp argument to Merge3Merger is deprecated")
 
753
        if pb is not None:
 
754
            warnings.warn("pb argument to Merge3Merger is deprecated")
766
755
 
767
756
    def do_merge(self):
 
757
        operation = OperationWithCleanups(self._do_merge)
768
758
        self.this_tree.lock_tree_write()
 
759
        operation.add_cleanup(self.this_tree.unlock)
769
760
        self.base_tree.lock_read()
 
761
        operation.add_cleanup(self.base_tree.unlock)
770
762
        self.other_tree.lock_read()
 
763
        operation.add_cleanup(self.other_tree.unlock)
 
764
        operation.run()
 
765
 
 
766
    def _do_merge(self, operation):
 
767
        self.tt = transform.TreeTransform(self.this_tree, None)
 
768
        operation.add_cleanup(self.tt.finalize)
 
769
        self._compute_transform()
 
770
        results = self.tt.apply(no_conflicts=True)
 
771
        self.write_modified(results)
771
772
        try:
772
 
            self.tt = transform.TreeTransform(self.this_tree, self.pb)
773
 
            try:
774
 
                self.pp.next_phase()
775
 
                self._compute_transform()
776
 
                self.pp.next_phase()
777
 
                results = self.tt.apply(no_conflicts=True)
778
 
                self.write_modified(results)
779
 
                try:
780
 
                    self.this_tree.add_conflicts(self.cooked_conflicts)
781
 
                except errors.UnsupportedOperation:
782
 
                    pass
783
 
            finally:
784
 
                self.tt.finalize()
785
 
        finally:
786
 
            self.other_tree.unlock()
787
 
            self.base_tree.unlock()
788
 
            self.this_tree.unlock()
789
 
            self.pb.clear()
 
773
            self.this_tree.add_conflicts(self.cooked_conflicts)
 
774
        except errors.UnsupportedOperation:
 
775
            pass
790
776
 
791
777
    def make_preview_transform(self):
 
778
        operation = OperationWithCleanups(self._make_preview_transform)
792
779
        self.base_tree.lock_read()
 
780
        operation.add_cleanup(self.base_tree.unlock)
793
781
        self.other_tree.lock_read()
 
782
        operation.add_cleanup(self.other_tree.unlock)
 
783
        return operation.run_simple()
 
784
 
 
785
    def _make_preview_transform(self):
794
786
        self.tt = transform.TransformPreview(self.this_tree)
795
 
        try:
796
 
            self.pp.next_phase()
797
 
            self._compute_transform()
798
 
            self.pp.next_phase()
799
 
        finally:
800
 
            self.other_tree.unlock()
801
 
            self.base_tree.unlock()
802
 
            self.pb.clear()
 
787
        self._compute_transform()
803
788
        return self.tt
804
789
 
805
790
    def _compute_transform(self):
827
812
        finally:
828
813
            child_pb.finished()
829
814
        self.fix_root()
830
 
        self.pp.next_phase()
831
815
        child_pb = ui.ui_factory.nested_progress_bar()
832
816
        try:
833
817
            fs_conflicts = transform.resolve_conflicts(self.tt, child_pb,
1726
1710
                other_rev_id=None,
1727
1711
                interesting_files=None,
1728
1712
                this_tree=None,
1729
 
                pb=progress.DummyProgress(),
 
1713
                pb=None,
1730
1714
                change_reporter=None):
1731
1715
    """Primary interface for merging.
1732
1716