2637
2638
directory=None,
2639
2640
from bzrlib.tag import _merge_tags_if_possible
2640
other_revision_id = None
2641
# This is actually a branch (or merge-directive) *location*.
2641
2645
if merge_type is None:
2642
2646
merge_type = _mod_merge.Merge3Merger
2644
2648
if directory is None: directory = u'.'
2645
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2646
# inventory. Because merge is a mutating operation, it really
2647
# should be a lock_write() for the whole cmd_merge operation.
2648
# However, cmd_merge open's its own tree in _merge_helper, which
2649
# means if we lock here, the later lock_write() will always block.
2650
# Either the merge helper code should be updated to take a tree,
2651
# (What about tree.merge_from_branch?)
2649
possible_transports = []
2651
allow_pending = True
2652
verified = 'inapplicable'
2652
2653
tree = WorkingTree.open_containing(directory)[0]
2653
2654
change_reporter = delta._ChangeReporter(
2654
2655
unversioned_filter=tree.is_ignored)
2656
if branch is not None:
2658
mergeable = bundle.read_mergeable_from_url(
2660
except errors.NotABundle:
2661
pass # Continue on considering this url a Branch
2663
if revision is not None:
2664
raise errors.BzrCommandError(
2665
'Cannot use -r with merge directives or bundles')
2666
other_revision_id = mergeable.install_revisions(
2667
tree.branch.repository)
2668
revision = [RevisionSpec.from_string(
2669
'revid:' + other_revision_id)]
2671
if revision is None \
2672
or len(revision) < 1 or revision[0].needs_branch():
2673
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2675
if revision is None or len(revision) < 1:
2678
other = [branch, None]
2681
other = [branch, -1]
2682
other_branch, path = Branch.open_containing(branch)
2685
raise errors.BzrCommandError('Cannot use --uncommitted and'
2686
' --revision at the same time.')
2687
branch = revision[0].get_branch() or branch
2688
if len(revision) == 1:
2690
if other_revision_id is not None:
2695
other_branch, path = Branch.open_containing(branch)
2696
revno = revision[0].in_history(other_branch).revno
2697
other = [branch, revno]
2699
assert len(revision) == 2
2700
if None in revision:
2701
raise errors.BzrCommandError(
2702
"Merge doesn't permit empty revision specifier.")
2703
base_branch, path = Branch.open_containing(branch)
2704
branch1 = revision[1].get_branch() or branch
2705
other_branch, path1 = Branch.open_containing(branch1)
2706
if revision[0].get_branch() is not None:
2707
# then path was obtained from it, and is None.
2710
base = [branch, revision[0].in_history(base_branch).revno]
2711
other = [branch1, revision[1].in_history(other_branch).revno]
2658
pb = ui.ui_factory.nested_progress_bar()
2659
cleanups.append(pb.finished)
2661
cleanups.append(tree.unlock)
2662
if location is not None:
2663
mergeable, other_transport = _get_mergeable_helper(location)
2666
raise errors.BzrCommandError('Cannot use --uncommitted'
2667
' with bundles or merge directives.')
2669
if revision is not None:
2670
raise errors.BzrCommandError(
2671
'Cannot use -r with merge directives or bundles')
2672
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2674
possible_transports.append(other_transport)
2676
if merger is None and uncommitted:
2677
if revision is not None and len(revision) > 0:
2678
raise errors.BzrCommandError('Cannot use --uncommitted and'
2679
' --revision at the same time.')
2680
location = self._select_branch_location(tree, location)[0]
2681
other_tree, other_path = WorkingTree.open_containing(location)
2682
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2684
allow_pending = False
2687
merger, allow_pending = self._get_merger_from_branch(tree,
2688
location, revision, remember, possible_transports, pb)
2690
merger.merge_type = merge_type
2691
merger.reprocess = reprocess
2692
merger.show_base = show_base
2693
merger.change_reporter = change_reporter
2694
self.sanity_check_merger(merger)
2695
if (merger.base_rev_id == merger.other_rev_id and
2696
merger.other_rev_id != None):
2697
note('Nothing to do.')
2700
if merger.interesting_files is not None:
2701
raise BzrCommandError('Cannot pull individual files')
2702
if (merger.base_rev_id == tree.last_revision()):
2703
result = tree.pull(merger.other_branch, False,
2704
merger.other_rev_id)
2705
result.report(self.outf)
2707
merger.check_basis(not force)
2708
conflict_count = merger.do_merge()
2710
merger.set_pending()
2711
if verified == 'failed':
2712
warning('Preview patch does not match changes')
2713
if conflict_count != 0:
2718
for cleanup in reversed(cleanups):
2721
def sanity_check_merger(self, merger):
2722
if (merger.show_base and
2723
not merger.merge_type is _mod_merge.Merge3Merger):
2724
raise errors.BzrCommandError("Show-base is not supported for this"
2725
" merge type. %s" % merge_type)
2726
if merger.reprocess and not merger.merge_type.supports_reprocess:
2727
raise errors.BzrCommandError("Conflict reduction is not supported"
2728
" for merge type %s." % merge_type)
2729
if merger.reprocess and merger.show_base:
2730
raise errors.BzrCommandError("Cannot do conflict reduction and"
2733
def _get_merger_from_branch(self, tree, location, revision, remember,
2734
possible_transports, pb):
2735
"""Produce a merger from a location, assuming it refers to a branch."""
2736
from bzrlib.tag import _merge_tags_if_possible
2737
assert revision is None or len(revision) < 3
2738
# find the branch locations
2739
other_loc, location = self._select_branch_location(tree, location,
2741
if revision is not None and len(revision) == 2:
2742
base_loc, location = self._select_branch_location(tree, location,
2745
base_loc = other_loc
2747
other_branch, other_path = Branch.open_containing(other_loc,
2748
possible_transports)
2749
if base_loc == other_loc:
2750
base_branch = other_branch
2752
base_branch, base_path = Branch.open_containing(base_loc,
2753
possible_transports)
2754
# Find the revision ids
2755
if revision is None or len(revision) < 1 or revision[-1] is None:
2756
other_revision_id = _mod_revision.ensure_null(
2757
other_branch.last_revision())
2759
other_revision_id = \
2760
_mod_revision.ensure_null(
2761
revision[-1].in_history(other_branch).rev_id)
2762
if (revision is not None and len(revision) == 2
2763
and revision[0] is not None):
2764
base_revision_id = \
2765
_mod_revision.ensure_null(
2766
revision[0].in_history(base_branch).rev_id)
2768
base_revision_id = None
2769
# Remember where we merge from
2713
2770
if ((tree.branch.get_parent() is None or remember) and
2714
2771
other_branch is not None):
2715
2772
tree.branch.set_parent(other_branch.base)
2717
# pull tags now... it's a bit inconsistent to do it ahead of copying
2718
# the history but that's done inside the merge code
2719
if other_branch is not None:
2720
_merge_tags_if_possible(other_branch, tree.branch)
2723
interesting_files = [path]
2773
_merge_tags_if_possible(other_branch, tree.branch)
2774
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2775
other_revision_id, base_revision_id, other_branch, base_branch)
2776
if other_path != '':
2777
allow_pending = False
2778
merger.interesting_files = [other_path]
2725
interesting_files = None
2726
pb = ui.ui_factory.nested_progress_bar()
2729
conflict_count = _merge_helper(
2730
other, base, other_rev_id=other_revision_id,
2731
check_clean=(not force),
2732
merge_type=merge_type,
2733
reprocess=reprocess,
2734
show_base=show_base,
2737
pb=pb, file_list=interesting_files,
2738
change_reporter=change_reporter)
2741
if conflict_count != 0:
2745
except errors.AmbiguousBase, e:
2746
m = ("sorry, bzr can't determine the right merge base yet\n"
2747
"candidates are:\n "
2748
+ "\n ".join(e.bases)
2750
"please specify an explicit base with -r,\n"
2751
"and (if you want) report this to the bzr developers\n")
2780
allow_pending = True
2781
return merger, allow_pending
2783
def _select_branch_location(self, tree, location, revision=None,
2785
"""Select a branch location, according to possible inputs.
2787
If provided, branches from ``revision`` are preferred. (Both
2788
``revision`` and ``index`` must be supplied.)
2790
Otherwise, the ``location`` parameter is used. If it is None, then the
2791
``parent`` location is used, and a note is printed.
2793
:param tree: The working tree to select a branch for merging into
2794
:param location: The location entered by the user
2795
:param revision: The revision parameter to the command
2796
:param index: The index to use for the revision parameter. Negative
2797
indices are permitted.
2798
:return: (selected_location, default_location). The default location
2799
will be the user-entered location, if any, or else the remembered
2802
if (revision is not None and index is not None
2803
and revision[index] is not None):
2804
branch = revision[index].get_branch()
2805
if branch is not None:
2806
return branch, location
2807
location = self._get_remembered_parent(tree, location, 'Merging from')
2808
return location, location
2754
2810
# TODO: move up to common parent; this isn't merge-specific anymore.
2755
2811
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3626
3723
s.send_email(message)
3726
class cmd_send(Command):
3727
"""Create a merge-directive for submiting changes.
3729
A merge directive provides many things needed for requesting merges:
3730
- A machine-readable description of the merge to perform
3731
- An optional patch that is a preview of the changes requested
3732
- An optional bundle of revision data, so that the changes can be applied
3733
directly from the merge directive, without retrieving data from a
3736
If --no-bundle is specified, then public_branch is needed (and must be
3737
up-to-date), so that the receiver can perform the merge using the
3738
public_branch. The public_branch is always included if known, so that
3739
people can check it later.
3741
The submit branch defaults to the parent, but can be overridden. Both
3742
submit branch and public branch will be remembered if supplied.
3744
If a public_branch is known for the submit_branch, that public submit
3745
branch is used in the merge instructions. This means that a local mirror
3746
can be used as your actual submit branch, once you have set public_branch
3750
encoding_type = 'exact'
3752
aliases = ['bundle', 'bundle-revisions']
3754
_see_also = ['merge']
3756
takes_args = ['submit_branch?', 'public_branch?']
3760
help='Do not include a bundle in the merge directive.'),
3761
Option('no-patch', help='Do not include a preview patch in the merge'
3764
help='Remember submit and public branch.'),
3766
help='Branch to generate the submission from, '
3767
'rather than the one containing the working directory.',
3770
Option('output', short_name='o', help='Write directive to this file.',
3775
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3776
no_patch=False, revision=None, remember=False, output=None,
3778
from bzrlib.revision import ensure_null, NULL_REVISION
3780
raise errors.BzrCommandError('File must be specified with'
3785
outfile = open(output, 'wb')
3787
from_ = kwargs.get('from', '.')
3788
branch = Branch.open_containing(from_)[0]
3789
if remember and submit_branch is None:
3790
raise errors.BzrCommandError(
3791
'--remember requires a branch to be specified.')
3792
stored_submit_branch = branch.get_submit_branch()
3793
remembered_submit_branch = False
3794
if submit_branch is None:
3795
submit_branch = stored_submit_branch
3796
remembered_submit_branch = True
3798
if stored_submit_branch is None or remember:
3799
branch.set_submit_branch(submit_branch)
3800
if submit_branch is None:
3801
submit_branch = branch.get_parent()
3802
remembered_submit_branch = True
3803
if submit_branch is None:
3804
raise errors.BzrCommandError('No submit branch known or'
3806
if remembered_submit_branch:
3807
note('Using saved location: %s', submit_branch)
3809
stored_public_branch = branch.get_public_branch()
3810
if public_branch is None:
3811
public_branch = stored_public_branch
3812
elif stored_public_branch is None or remember:
3813
branch.set_public_branch(public_branch)
3814
if no_bundle and public_branch is None:
3815
raise errors.BzrCommandError('No public branch specified or'
3817
base_revision_id = None
3818
if revision is not None:
3819
if len(revision) > 2:
3820
raise errors.BzrCommandError('bzr send takes '
3821
'at most two one revision identifiers')
3822
revision_id = revision[-1].in_history(branch).rev_id
3823
if len(revision) == 2:
3824
base_revision_id = revision[0].in_history(branch).rev_id
3825
base_revision_id = ensure_null(base_revision_id)
3827
revision_id = branch.last_revision()
3828
revision_id = ensure_null(revision_id)
3829
if revision_id == NULL_REVISION:
3830
raise errors.BzrCommandError('No revisions to submit.')
3831
directive = merge_directive.MergeDirective2.from_objects(
3832
branch.repository, revision_id, time.time(),
3833
osutils.local_time_offset(), submit_branch,
3834
public_branch=public_branch, include_patch=not no_patch,
3835
include_bundle=not no_bundle, message=None,
3836
base_revision_id=base_revision_id)
3837
outfile.writelines(directive.to_lines())
3629
3843
class cmd_tag(Command):
3630
"""Create a tag naming a revision.
3844
"""Create, remove or modify a tag naming a revision.
3632
3846
Tags give human-meaningful names to revisions. Commands that take a -r
3633
3847
(--revision) option can be given -rtag:X, where X is any previously
3710
3924
self.outf.write('%-20s %s\n' % (tag_name, target))
3713
# command-line interpretation helper for merge-related commands
3714
def _merge_helper(other_revision, base_revision,
3715
check_clean=True, ignore_zero=False,
3716
this_dir=None, backup_files=False,
3718
file_list=None, show_base=False, reprocess=False,
3721
change_reporter=None,
3723
"""Merge changes into a tree.
3726
list(path, revno) Base for three-way merge.
3727
If [None, None] then a base will be automatically determined.
3729
list(path, revno) Other revision for three-way merge.
3731
Directory to merge changes into; '.' by default.
3733
If true, this_dir must have no uncommitted changes before the
3735
ignore_zero - If true, suppress the "zero conflicts" message when
3736
there are no conflicts; should be set when doing something we expect
3737
to complete perfectly.
3738
file_list - If supplied, merge only changes to selected files.
3740
All available ancestors of other_revision and base_revision are
3741
automatically pulled into the branch.
3743
The revno may be -1 to indicate the last revision on the branch, which is
3746
This function is intended for use from the command line; programmatic
3747
clients might prefer to call merge.merge_inner(), which has less magic
3750
# Loading it late, so that we don't always have to import bzrlib.merge
3751
if merge_type is None:
3752
merge_type = _mod_merge.Merge3Merger
3753
if this_dir is None:
3755
this_tree = WorkingTree.open_containing(this_dir)[0]
3756
if show_base and not merge_type is _mod_merge.Merge3Merger:
3757
raise errors.BzrCommandError("Show-base is not supported for this merge"
3758
" type. %s" % merge_type)
3759
if reprocess and not merge_type.supports_reprocess:
3760
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3761
" type %s." % merge_type)
3762
if reprocess and show_base:
3763
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3764
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3765
# only want to take out a lock_tree_write() if we don't have to pull
3766
# any ancestry. But merge might fetch ancestry in the middle, in
3767
# which case we would need a lock_write().
3768
# Because we cannot upgrade locks, for now we live with the fact that
3769
# the tree will be locked multiple times during a merge. (Maybe
3770
# read-only some of the time, but it means things will get read
3773
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3774
pb=pb, change_reporter=change_reporter)
3775
merger.pp = ProgressPhase("Merge phase", 5, pb)
3776
merger.pp.next_phase()
3777
merger.check_basis(check_clean)
3778
if other_rev_id is not None:
3779
merger.set_other_revision(other_rev_id, this_tree.branch)
3781
merger.set_other(other_revision)
3782
merger.pp.next_phase()
3783
merger.set_base(base_revision)
3784
if merger.base_rev_id == merger.other_rev_id:
3785
note('Nothing to do.')
3787
if file_list is None:
3788
if pull and merger.base_rev_id == merger.this_rev_id:
3789
# FIXME: deduplicate with pull
3790
result = merger.this_tree.pull(merger.this_branch,
3791
False, merger.other_rev_id)
3792
if result.old_revid == result.new_revid:
3793
note('No revisions to pull.')
3795
note('Now on revision %d.' % result.new_revno)
3797
merger.backup_files = backup_files
3798
merger.merge_type = merge_type
3799
merger.set_interesting_files(file_list)
3800
merger.show_base = show_base
3801
merger.reprocess = reprocess
3802
conflicts = merger.do_merge()
3803
if file_list is None:
3804
merger.set_pending()
3810
3927
def _create_prefix(cur_transport):
3811
3928
needed = [cur_transport]
3812
3929
# Recurse upwards until we can create a directory successfully