2641
2686
directory=None,
2643
2688
from bzrlib.tag import _merge_tags_if_possible
2644
other_revision_id = None
2645
base_revision_id = None
2689
# This is actually a branch (or merge-directive) *location*.
2646
2693
if merge_type is None:
2647
2694
merge_type = _mod_merge.Merge3Merger
2649
2696
if directory is None: directory = u'.'
2650
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2651
# inventory. Because merge is a mutating operation, it really
2652
# should be a lock_write() for the whole cmd_merge operation.
2653
# However, cmd_merge open's its own tree in _merge_helper, which
2654
# means if we lock here, the later lock_write() will always block.
2655
# Either the merge helper code should be updated to take a tree,
2656
# (What about tree.merge_from_branch?)
2697
possible_transports = []
2699
allow_pending = True
2700
verified = 'inapplicable'
2657
2701
tree = WorkingTree.open_containing(directory)[0]
2658
2702
change_reporter = delta._ChangeReporter(
2659
2703
unversioned_filter=tree.is_ignored)
2661
if branch is not None:
2663
mergeable = bundle.read_mergeable_from_url(
2665
except errors.NotABundle:
2666
pass # Continue on considering this url a Branch
2668
if revision is not None:
2669
raise errors.BzrCommandError(
2670
'Cannot use -r with merge directives or bundles')
2671
mergeable.install_revisions(tree.branch.repository)
2672
base_revision_id, other_revision_id, verified =\
2673
mergeable.get_merge_request(tree.branch.repository)
2674
if base_revision_id in tree.branch.repository.get_ancestry(
2675
tree.branch.last_revision(), topo_sorted=False):
2676
base_revision_id = None
2682
if other_revision_id is None:
2683
verified = 'inapplicable'
2684
if revision is None \
2685
or len(revision) < 1 or revision[0].needs_branch():
2686
branch = self._get_remembered_parent(tree, branch,
2689
if revision is None or len(revision) < 1:
2692
other = [branch, None]
2695
other = [branch, -1]
2696
other_branch, path = Branch.open_containing(branch)
2706
pb = ui.ui_factory.nested_progress_bar()
2707
cleanups.append(pb.finished)
2709
cleanups.append(tree.unlock)
2710
if location is not None:
2711
mergeable, other_transport = _get_mergeable_helper(location)
2714
raise errors.BzrCommandError('Cannot use --uncommitted'
2715
' with bundles or merge directives.')
2717
if revision is not None:
2718
raise errors.BzrCommandError(
2719
'Cannot use -r with merge directives or bundles')
2720
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2722
possible_transports.append(other_transport)
2724
if merger is None and uncommitted:
2725
if revision is not None and len(revision) > 0:
2699
2726
raise errors.BzrCommandError('Cannot use --uncommitted and'
2700
2727
' --revision at the same time.')
2701
branch = revision[0].get_branch() or branch
2702
if len(revision) == 1:
2704
other_branch, path = Branch.open_containing(branch)
2705
revno = revision[0].in_history(other_branch).revno
2706
other = [branch, revno]
2708
assert len(revision) == 2
2709
if None in revision:
2710
raise errors.BzrCommandError(
2711
"Merge doesn't permit empty revision specifier.")
2712
base_branch, path = Branch.open_containing(branch)
2713
branch1 = revision[1].get_branch() or branch
2714
other_branch, path1 = Branch.open_containing(branch1)
2715
if revision[0].get_branch() is not None:
2716
# then path was obtained from it, and is None.
2719
base = [branch, revision[0].in_history(base_branch).revno]
2721
revision[1].in_history(other_branch).revno]
2728
location = self._select_branch_location(tree, location)[0]
2729
other_tree, other_path = WorkingTree.open_containing(location)
2730
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2732
allow_pending = False
2735
merger, allow_pending = self._get_merger_from_branch(tree,
2736
location, revision, remember, possible_transports, pb)
2738
merger.merge_type = merge_type
2739
merger.reprocess = reprocess
2740
merger.show_base = show_base
2741
merger.change_reporter = change_reporter
2742
self.sanity_check_merger(merger)
2743
if (merger.base_rev_id == merger.other_rev_id and
2744
merger.other_rev_id != None):
2745
note('Nothing to do.')
2748
if merger.interesting_files is not None:
2749
raise BzrCommandError('Cannot pull individual files')
2750
if (merger.base_rev_id == tree.last_revision()):
2751
result = tree.pull(merger.other_branch, False,
2752
merger.other_rev_id)
2753
result.report(self.outf)
2755
merger.check_basis(not force)
2756
conflict_count = merger.do_merge()
2758
merger.set_pending()
2759
if verified == 'failed':
2760
warning('Preview patch does not match changes')
2761
if conflict_count != 0:
2766
for cleanup in reversed(cleanups):
2769
def sanity_check_merger(self, merger):
2770
if (merger.show_base and
2771
not merger.merge_type is _mod_merge.Merge3Merger):
2772
raise errors.BzrCommandError("Show-base is not supported for this"
2773
" merge type. %s" % merger.merge_type)
2774
if merger.reprocess and not merger.merge_type.supports_reprocess:
2775
raise errors.BzrCommandError("Conflict reduction is not supported"
2776
" for merge type %s." %
2778
if merger.reprocess and merger.show_base:
2779
raise errors.BzrCommandError("Cannot do conflict reduction and"
2782
def _get_merger_from_branch(self, tree, location, revision, remember,
2783
possible_transports, pb):
2784
"""Produce a merger from a location, assuming it refers to a branch."""
2785
from bzrlib.tag import _merge_tags_if_possible
2786
assert revision is None or len(revision) < 3
2787
# find the branch locations
2788
other_loc, location = self._select_branch_location(tree, location,
2790
if revision is not None and len(revision) == 2:
2791
base_loc, location = self._select_branch_location(tree, location,
2794
base_loc = other_loc
2796
other_branch, other_path = Branch.open_containing(other_loc,
2797
possible_transports)
2798
if base_loc == other_loc:
2799
base_branch = other_branch
2801
base_branch, base_path = Branch.open_containing(base_loc,
2802
possible_transports)
2803
# Find the revision ids
2804
if revision is None or len(revision) < 1 or revision[-1] is None:
2805
other_revision_id = _mod_revision.ensure_null(
2806
other_branch.last_revision())
2808
other_revision_id = \
2809
_mod_revision.ensure_null(
2810
revision[-1].in_history(other_branch).rev_id)
2811
if (revision is not None and len(revision) == 2
2812
and revision[0] is not None):
2813
base_revision_id = \
2814
_mod_revision.ensure_null(
2815
revision[0].in_history(base_branch).rev_id)
2817
base_revision_id = None
2818
# Remember where we merge from
2723
2819
if ((tree.branch.get_parent() is None or remember) and
2724
2820
other_branch is not None):
2725
2821
tree.branch.set_parent(other_branch.base)
2727
# pull tags now... it's a bit inconsistent to do it ahead of copying
2728
# the history but that's done inside the merge code
2729
if other_branch is not None:
2730
_merge_tags_if_possible(other_branch, tree.branch)
2733
interesting_files = [path]
2822
_merge_tags_if_possible(other_branch, tree.branch)
2823
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2824
other_revision_id, base_revision_id, other_branch, base_branch)
2825
if other_path != '':
2826
allow_pending = False
2827
merger.interesting_files = [other_path]
2735
interesting_files = None
2736
pb = ui.ui_factory.nested_progress_bar()
2739
conflict_count = _merge_helper(
2740
other, base, other_rev_id=other_revision_id,
2741
base_rev_id=base_revision_id,
2742
check_clean=(not force),
2743
merge_type=merge_type,
2744
reprocess=reprocess,
2745
show_base=show_base,
2748
pb=pb, file_list=interesting_files,
2749
change_reporter=change_reporter)
2752
if verified == 'failed':
2753
warning('Preview patch does not match changes')
2754
if conflict_count != 0:
2758
except errors.AmbiguousBase, e:
2759
m = ("sorry, bzr can't determine the right merge base yet\n"
2760
"candidates are:\n "
2761
+ "\n ".join(e.bases)
2763
"please specify an explicit base with -r,\n"
2764
"and (if you want) report this to the bzr developers\n")
2829
allow_pending = True
2830
return merger, allow_pending
2832
def _select_branch_location(self, tree, location, revision=None,
2834
"""Select a branch location, according to possible inputs.
2836
If provided, branches from ``revision`` are preferred. (Both
2837
``revision`` and ``index`` must be supplied.)
2839
Otherwise, the ``location`` parameter is used. If it is None, then the
2840
``parent`` location is used, and a note is printed.
2842
:param tree: The working tree to select a branch for merging into
2843
:param location: The location entered by the user
2844
:param revision: The revision parameter to the command
2845
:param index: The index to use for the revision parameter. Negative
2846
indices are permitted.
2847
:return: (selected_location, default_location). The default location
2848
will be the user-entered location, if any, or else the remembered
2851
if (revision is not None and index is not None
2852
and revision[index] is not None):
2853
branch = revision[index].get_branch()
2854
if branch is not None:
2855
return branch, location
2856
location = self._get_remembered_parent(tree, location, 'Merging from')
2857
return location, location
2767
2859
# TODO: move up to common parent; this isn't merge-specific anymore.
2768
2860
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3861
3977
self.outf.write('%-20s %s\n' % (tag_name, target))
3864
# command-line interpretation helper for merge-related commands
3865
def _merge_helper(other_revision, base_revision,
3866
check_clean=True, ignore_zero=False,
3867
this_dir=None, backup_files=False,
3869
file_list=None, show_base=False, reprocess=False,
3872
change_reporter=None,
3873
other_rev_id=None, base_rev_id=None):
3874
"""Merge changes into a tree.
3877
list(path, revno) Base for three-way merge.
3878
If [None, None] then a base will be automatically determined.
3880
list(path, revno) Other revision for three-way merge.
3882
Directory to merge changes into; '.' by default.
3884
If true, this_dir must have no uncommitted changes before the
3886
ignore_zero - If true, suppress the "zero conflicts" message when
3887
there are no conflicts; should be set when doing something we expect
3888
to complete perfectly.
3889
file_list - If supplied, merge only changes to selected files.
3891
All available ancestors of other_revision and base_revision are
3892
automatically pulled into the branch.
3894
The revno may be -1 to indicate the last revision on the branch, which is
3897
This function is intended for use from the command line; programmatic
3898
clients might prefer to call merge.merge_inner(), which has less magic
3901
# Loading it late, so that we don't always have to import bzrlib.merge
3902
if merge_type is None:
3903
merge_type = _mod_merge.Merge3Merger
3904
if this_dir is None:
3906
this_tree = WorkingTree.open_containing(this_dir)[0]
3907
if show_base and not merge_type is _mod_merge.Merge3Merger:
3908
raise errors.BzrCommandError("Show-base is not supported for this merge"
3909
" type. %s" % merge_type)
3910
if reprocess and not merge_type.supports_reprocess:
3911
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3912
" type %s." % merge_type)
3913
if reprocess and show_base:
3914
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3915
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3916
# only want to take out a lock_tree_write() if we don't have to pull
3917
# any ancestry. But merge might fetch ancestry in the middle, in
3918
# which case we would need a lock_write().
3919
# Because we cannot upgrade locks, for now we live with the fact that
3920
# the tree will be locked multiple times during a merge. (Maybe
3921
# read-only some of the time, but it means things will get read
3924
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3925
pb=pb, change_reporter=change_reporter)
3926
merger.pp = ProgressPhase("Merge phase", 5, pb)
3927
merger.pp.next_phase()
3928
merger.check_basis(check_clean)
3929
if other_rev_id is not None:
3930
merger.set_other_revision(other_rev_id, this_tree.branch)
3932
merger.set_other(other_revision)
3933
merger.pp.next_phase()
3934
if base_rev_id is not None:
3935
merger.set_base_revision(base_rev_id, this_tree.branch)
3936
elif base_revision is not None:
3937
merger.set_base(base_revision)
3940
if merger.base_rev_id == merger.other_rev_id:
3941
note('Nothing to do.')
3943
if file_list is None:
3944
if pull and merger.base_rev_id == merger.this_rev_id:
3945
# FIXME: deduplicate with pull
3946
result = merger.this_tree.pull(merger.this_branch,
3947
False, merger.other_rev_id)
3948
if result.old_revid == result.new_revid:
3949
note('No revisions to pull.')
3951
note('Now on revision %d.' % result.new_revno)
3953
merger.backup_files = backup_files
3954
merger.merge_type = merge_type
3955
merger.set_interesting_files(file_list)
3956
merger.show_base = show_base
3957
merger.reprocess = reprocess
3958
conflicts = merger.do_merge()
3959
if file_list is None:
3960
merger.set_pending()
3966
3980
def _create_prefix(cur_transport):
3967
3981
needed = [cur_transport]
3968
3982
# Recurse upwards until we can create a directory successfully