~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2007-07-25 00:52:21 UTC
  • mfrom: (2650 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2651.
  • Revision ID: robertc@robertcollins.net-20070725005221-0ysm6il5mqnme3wz
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
    urlutils,
54
54
    )
55
55
from bzrlib.branch import Branch
56
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
57
56
from bzrlib.conflicts import ConflictList
58
57
from bzrlib.revisionspec import RevisionSpec
59
58
from bzrlib.smtp_connection import SMTPConnection
595
594
            tree_to = None
596
595
            branch_to = Branch.open_containing(directory)[0]
597
596
 
598
 
        reader = None
599
597
        if location is not None:
600
 
            try:
601
 
                mergeable = bundle.read_mergeable_from_url(
602
 
                    location)
603
 
            except errors.NotABundle:
604
 
                pass # Continue on considering this url a Branch
 
598
            mergeable, location_transport = _get_bundle_helper(location)
605
599
 
606
600
        stored_loc = branch_to.get_parent()
607
601
        if location is None:
613
607
                        self.outf.encoding)
614
608
                self.outf.write("Using saved location: %s\n" % display_url)
615
609
                location = stored_loc
 
610
                location_transport = transport.get_transport(location)
616
611
 
617
612
        if mergeable is not None:
618
613
            if revision is not None:
619
614
                raise errors.BzrCommandError(
620
615
                    'Cannot use -r with merge directives or bundles')
621
 
            revision_id = mergeable.install_revisions(branch_to.repository)
 
616
            mergeable.install_revisions(branch_to.repository)
 
617
            base_revision_id, revision_id, verified = \
 
618
                mergeable.get_merge_request(branch_to.repository)
622
619
            branch_from = branch_to
623
620
        else:
624
 
            branch_from = Branch.open(location)
 
621
            branch_from = Branch.open_from_transport(location_transport)
625
622
 
626
623
            if branch_to.get_parent() is None or remember:
627
624
                branch_to.set_parent(branch_from.base)
633
630
                raise errors.BzrCommandError(
634
631
                    'bzr pull --revision takes one value.')
635
632
 
636
 
        old_rh = branch_to.revision_history()
 
633
        if verbose:
 
634
            old_rh = branch_to.revision_history()
637
635
        if tree_to is not None:
638
636
            result = tree_to.pull(branch_from, overwrite, revision_id,
639
637
                delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
735
733
                # Found a branch, so we must have found a repository
736
734
                repository_to = br_to.repository
737
735
        push_result = None
738
 
        old_rh = []
 
736
        if verbose:
 
737
            old_rh = []
739
738
        if dir_to is None:
740
739
            # The destination doesn't exist; create it.
741
740
            # XXX: Refactor the create_prefix/no_create_prefix code into a
791
790
            # we don't need to successfully push because of possible divergence.
792
791
            if br_from.get_push_location() is None or remember:
793
792
                br_from.set_push_location(br_to.base)
794
 
            old_rh = br_to.revision_history()
 
793
            if verbose:
 
794
                old_rh = br_to.revision_history()
795
795
            try:
796
796
                try:
797
797
                    tree_to = dir_to.open_workingtree()
881
881
                                             % to_location)
882
882
            try:
883
883
                # preserve whatever source format we have.
884
 
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id)
 
884
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
885
                                            possible_transports=[to_transport])
885
886
                branch = dir.open_branch()
886
887
            except errors.NoSuchRevision:
887
888
                to_transport.delete_tree('.')
941
942
            to_location = branch_location
942
943
        source = Branch.open(branch_location)
943
944
        if len(revision) == 1 and revision[0] is not None:
944
 
            revision_id = revision[0].in_history(source)[1]
 
945
            revision_id = _mod_revision.ensure_null(
 
946
                revision[0].in_history(source)[1])
945
947
        else:
946
948
            revision_id = None
947
949
        if to_location is None:
954
956
            try:
955
957
                source.bzrdir.open_workingtree()
956
958
            except errors.NoWorkingTree:
957
 
                source.bzrdir.create_workingtree()
 
959
                source.bzrdir.create_workingtree(revision_id)
958
960
                return
959
961
        try:
960
962
            os.mkdir(to_location)
1010
1012
    'bzr revert' instead of 'bzr commit' after the update.
1011
1013
    """
1012
1014
 
1013
 
    _see_also = ['pull', 'working-trees']
 
1015
    _see_also = ['pull', 'working-trees', 'status-flags']
1014
1016
    takes_args = ['dir?']
1015
1017
    aliases = ['up']
1016
1018
 
1295
1297
            _create_prefix(to_transport)
1296
1298
 
1297
1299
        try:
1298
 
            existing_bzrdir = bzrdir.BzrDir.open(location)
 
1300
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1299
1301
        except errors.NotBranchError:
1300
1302
            # really a NotBzrDir error...
1301
 
            branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1302
 
                                                             format=format)
 
1303
            create_branch = bzrdir.BzrDir.create_branch_convenience
 
1304
            branch = create_branch(to_transport.base, format=format,
 
1305
                                   possible_transports=[to_transport])
1303
1306
        else:
1304
1307
            from bzrlib.transport.local import LocalTransport
1305
1308
            if existing_bzrdir.has_branch():
2637
2640
            directory=None,
2638
2641
            ):
2639
2642
        from bzrlib.tag import _merge_tags_if_possible
2640
 
        other_revision_id = None
2641
2643
        if merge_type is None:
2642
2644
            merge_type = _mod_merge.Merge3Merger
2643
2645
 
2653
2655
        change_reporter = delta._ChangeReporter(
2654
2656
            unversioned_filter=tree.is_ignored)
2655
2657
 
 
2658
        other_transport = None
 
2659
        other_revision_id = None
 
2660
        base_revision_id = None
 
2661
        possible_transports = []
 
2662
 
2656
2663
        if branch is not None:
2657
 
            try:
2658
 
                mergeable = bundle.read_mergeable_from_url(
2659
 
                    branch)
2660
 
            except errors.NotABundle:
2661
 
                pass # Continue on considering this url a Branch
2662
 
            else:
 
2664
            mergeable, other_transport = _get_bundle_helper(branch)
 
2665
            if mergeable:
2663
2666
                if revision is not None:
2664
2667
                    raise errors.BzrCommandError(
2665
2668
                        '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)]
2670
 
 
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')
2674
 
 
2675
 
        if revision is None or len(revision) < 1:
2676
 
            if uncommitted:
2677
 
                base = [branch, -1]
2678
 
                other = [branch, None]
 
2669
                mergeable.install_revisions(tree.branch.repository)
 
2670
                base_revision_id, other_revision_id, verified =\
 
2671
                    mergeable.get_merge_request(tree.branch.repository)
 
2672
                if base_revision_id in tree.branch.repository.get_ancestry(
 
2673
                    tree.branch.last_revision(), topo_sorted=False):
 
2674
                    base_revision_id = None
 
2675
                other_branch = None
 
2676
                path = ''
 
2677
                other = None
 
2678
                base = None
 
2679
            possible_transports.append(other_transport)
 
2680
 
 
2681
        if other_revision_id is None:
 
2682
            verified = 'inapplicable'
 
2683
            if revision is None \
 
2684
                    or len(revision) < 1 or revision[0].needs_branch():
 
2685
                branch = self._get_remembered_parent(tree, branch,
 
2686
                    'Merging from')
 
2687
 
 
2688
            if revision is None or len(revision) < 1:
 
2689
                if uncommitted:
 
2690
                    base = [branch, -1]
 
2691
                    other = [branch, None]
 
2692
                else:
 
2693
                    base = [None, None]
 
2694
                    other = [branch, -1]
 
2695
                other_branch, path = Branch.open_containing(branch,
 
2696
                                                            possible_transports)
2679
2697
            else:
2680
 
                base = [None, None]
2681
 
                other = [branch, -1]
2682
 
            other_branch, path = Branch.open_containing(branch)
2683
 
        else:
2684
 
            if uncommitted:
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:
2689
 
                base = [None, None]
2690
 
                if other_revision_id is not None:
2691
 
                    other_branch = None
2692
 
                    path = ""
2693
 
                    other = None
2694
 
                else:
2695
 
                    other_branch, path = Branch.open_containing(branch)
 
2698
                if uncommitted:
 
2699
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2700
                        ' --revision at the same time.')
 
2701
                branch = revision[0].get_branch() or branch
 
2702
                if len(revision) == 1:
 
2703
                    base = [None, None]
 
2704
                    other_branch, path = Branch.open_containing(
 
2705
                        branch, possible_transports)
2696
2706
                    revno = revision[0].in_history(other_branch).revno
2697
2707
                    other = [branch, revno]
2698
 
            else:
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.
2708
 
                    path = path1
2709
 
 
2710
 
                base = [branch, revision[0].in_history(base_branch).revno]
2711
 
                other = [branch1, revision[1].in_history(other_branch).revno]
2712
 
 
 
2708
                else:
 
2709
                    assert len(revision) == 2
 
2710
                    if None in revision:
 
2711
                        raise errors.BzrCommandError(
 
2712
                            "Merge doesn't permit empty revision specifier.")
 
2713
                    base_branch, path = Branch.open_containing(
 
2714
                        branch, possible_transports)
 
2715
                    branch1 = revision[1].get_branch() or branch
 
2716
                    other_branch, path1 = Branch.open_containing(
 
2717
                        branch1, possible_transports)
 
2718
                    if revision[0].get_branch() is not None:
 
2719
                        # then path was obtained from it, and is None.
 
2720
                        path = path1
 
2721
 
 
2722
                    base = [branch, revision[0].in_history(base_branch).revno]
 
2723
                    other = [branch1,
 
2724
                             revision[1].in_history(other_branch).revno]
 
2725
 
 
2726
        # Remember where we merge from
2713
2727
        if ((tree.branch.get_parent() is None or remember) and
2714
2728
            other_branch is not None):
2715
2729
            tree.branch.set_parent(other_branch.base)
2728
2742
            try:
2729
2743
                conflict_count = _merge_helper(
2730
2744
                    other, base, other_rev_id=other_revision_id,
 
2745
                    base_rev_id=base_revision_id,
2731
2746
                    check_clean=(not force),
2732
2747
                    merge_type=merge_type,
2733
2748
                    reprocess=reprocess,
2735
2750
                    pull=pull,
2736
2751
                    this_dir=directory,
2737
2752
                    pb=pb, file_list=interesting_files,
2738
 
                    change_reporter=change_reporter)
 
2753
                    change_reporter=change_reporter,
 
2754
                    possible_transports=possible_transports)
2739
2755
            finally:
2740
2756
                pb.finished()
 
2757
            if verified == 'failed':
 
2758
                warning('Preview patch does not match changes')
2741
2759
            if conflict_count != 0:
2742
2760
                return 1
2743
2761
            else:
2844
2862
                    restore(tree.abspath(filename))
2845
2863
                except errors.NotConflicted:
2846
2864
                    pass
2847
 
            conflicts = _mod_merge.merge_inner(
2848
 
                                      tree.branch, other_tree, base_tree,
2849
 
                                      this_tree=tree,
2850
 
                                      interesting_ids=interesting_ids,
2851
 
                                      other_rev_id=parents[1],
2852
 
                                      merge_type=merge_type,
2853
 
                                      show_base=show_base,
2854
 
                                      reprocess=reprocess)
 
2865
            # Disable pending merges, because the file texts we are remerging
 
2866
            # have not had those merges performed.  If we use the wrong parents
 
2867
            # list, we imply that the working tree text has seen and rejected
 
2868
            # all the changes from the other tree, when in fact those changes
 
2869
            # have not yet been seen.
 
2870
            tree.set_parent_ids(parents[:1])
 
2871
            try:
 
2872
                conflicts = _mod_merge.merge_inner(
 
2873
                                          tree.branch, other_tree, base_tree,
 
2874
                                          this_tree=tree,
 
2875
                                          interesting_ids=interesting_ids,
 
2876
                                          other_rev_id=parents[1],
 
2877
                                          merge_type=merge_type,
 
2878
                                          show_base=show_base,
 
2879
                                          reprocess=reprocess)
 
2880
            finally:
 
2881
                tree.set_parent_ids(parents)
2855
2882
        finally:
2856
2883
            tree.unlock()
2857
2884
        if conflicts > 0:
3010
3037
        if other_branch is None:
3011
3038
            other_branch = parent
3012
3039
            if other_branch is None:
3013
 
                raise errors.BzrCommandError("No peer location known or specified.")
 
3040
                raise errors.BzrCommandError("No peer location known"
 
3041
                                             " or specified.")
3014
3042
            display_url = urlutils.unescape_for_display(parent,
3015
3043
                                                        self.outf.encoding)
3016
 
            print "Using last location: " + display_url
 
3044
            self.outf.write("Using last location: " + display_url + "\n")
3017
3045
 
3018
3046
        remote_branch = Branch.open(other_branch)
3019
3047
        if remote_branch.base == local_branch.base:
3022
3050
        try:
3023
3051
            remote_branch.lock_read()
3024
3052
            try:
3025
 
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
3026
 
                if (log_format is None):
3027
 
                    log_format = log.log_formatter_registry.get_default(
3028
 
                        local_branch)
 
3053
                local_extra, remote_extra = find_unmerged(local_branch,
 
3054
                                                          remote_branch)
 
3055
                if log_format is None:
 
3056
                    registry = log.log_formatter_registry
 
3057
                    log_format = registry.get_default(local_branch)
3029
3058
                lf = log_format(to_file=self.outf,
3030
3059
                                show_ids=show_ids,
3031
3060
                                show_timezone='original')
3033
3062
                    local_extra.reverse()
3034
3063
                    remote_extra.reverse()
3035
3064
                if local_extra and not theirs_only:
3036
 
                    print "You have %d extra revision(s):" % len(local_extra)
3037
 
                    for revision in iter_log_revisions(local_extra, 
 
3065
                    self.outf.write("You have %d extra revision(s):\n" %
 
3066
                                    len(local_extra))
 
3067
                    for revision in iter_log_revisions(local_extra,
3038
3068
                                        local_branch.repository,
3039
3069
                                        verbose):
3040
3070
                        lf.log_revision(revision)
3043
3073
                    printed_local = False
3044
3074
                if remote_extra and not mine_only:
3045
3075
                    if printed_local is True:
3046
 
                        print "\n\n"
3047
 
                    print "You are missing %d revision(s):" % len(remote_extra)
3048
 
                    for revision in iter_log_revisions(remote_extra, 
3049
 
                                        remote_branch.repository, 
 
3076
                        self.outf.write("\n\n\n")
 
3077
                    self.outf.write("You are missing %d revision(s):\n" %
 
3078
                                    len(remote_extra))
 
3079
                    for revision in iter_log_revisions(remote_extra,
 
3080
                                        remote_branch.repository,
3050
3081
                                        verbose):
3051
3082
                        lf.log_revision(revision)
3052
3083
                if not remote_extra and not local_extra:
3053
3084
                    status_code = 0
3054
 
                    print "Branches are up to date."
 
3085
                    self.outf.write("Branches are up to date.\n")
3055
3086
                else:
3056
3087
                    status_code = 1
3057
3088
            finally:
3086
3117
 
3087
3118
 
3088
3119
class cmd_plugins(Command):
3089
 
    """List plugins"""
3090
 
    hidden = True
 
3120
    """List the installed plugins.
 
3121
    
 
3122
    This command displays the list of installed plugins including the
 
3123
    path where each one is located and a short description of each.
 
3124
 
 
3125
    A plugin is an external component for Bazaar that extends the
 
3126
    revision control system, by adding or replacing code in Bazaar.
 
3127
    Plugins can do a variety of things, including overriding commands,
 
3128
    adding new commands, providing additional network transports and
 
3129
    customizing log output.
 
3130
 
 
3131
    See the Bazaar web site, http://bazaar-vcs.org, for further
 
3132
    information on plugins including where to find them and how to
 
3133
    install them. Instructions are also provided there on how to
 
3134
    write new plugins using the Python programming language.
 
3135
    """
 
3136
 
3091
3137
    @display_command
3092
3138
    def run(self):
3093
3139
        import bzrlib.plugin
3556
3602
 
3557
3603
    takes_args = ['submit_branch?', 'public_branch?']
3558
3604
 
 
3605
    hidden = True
 
3606
 
 
3607
    _see_also = ['submit']
 
3608
 
3559
3609
    takes_options = [
3560
3610
        RegistryOption.from_kwargs('patch-type',
3561
3611
            'The type of patch to include in the directive',
3577
3627
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3578
3628
            sign=False, revision=None, mail_to=None, message=None):
3579
3629
        from bzrlib.revision import ensure_null, NULL_REVISION
3580
 
        if patch_type == 'plain':
3581
 
            patch_type = None
 
3630
        include_patch, include_bundle = {
 
3631
            'plain': (False, False),
 
3632
            'diff': (True, False),
 
3633
            'bundle': (True, True),
 
3634
            }[patch_type]
3582
3635
        branch = Branch.open('.')
3583
3636
        stored_submit_branch = branch.get_submit_branch()
3584
3637
        if submit_branch is None:
3596
3649
            public_branch = stored_public_branch
3597
3650
        elif stored_public_branch is None:
3598
3651
            branch.set_public_branch(public_branch)
3599
 
        if patch_type != "bundle" and public_branch is None:
 
3652
        if not include_bundle and public_branch is None:
3600
3653
            raise errors.BzrCommandError('No public branch specified or'
3601
3654
                                         ' known')
 
3655
        base_revision_id = None
3602
3656
        if revision is not None:
3603
 
            if len(revision) != 1:
 
3657
            if len(revision) > 2:
3604
3658
                raise errors.BzrCommandError('bzr merge-directive takes '
3605
 
                    'exactly one revision identifier')
3606
 
            else:
3607
 
                revision_id = revision[0].in_history(branch).rev_id
 
3659
                    'at most two one revision identifiers')
 
3660
            revision_id = revision[-1].in_history(branch).rev_id
 
3661
            if len(revision) == 2:
 
3662
                base_revision_id = revision[0].in_history(branch).rev_id
 
3663
                base_revision_id = ensure_null(base_revision_id)
3608
3664
        else:
3609
3665
            revision_id = branch.last_revision()
3610
3666
        revision_id = ensure_null(revision_id)
3611
3667
        if revision_id == NULL_REVISION:
3612
3668
            raise errors.BzrCommandError('No revisions to bundle.')
3613
 
        directive = merge_directive.MergeDirective.from_objects(
 
3669
        directive = merge_directive.MergeDirective2.from_objects(
3614
3670
            branch.repository, revision_id, time.time(),
3615
3671
            osutils.local_time_offset(), submit_branch,
3616
 
            public_branch=public_branch, patch_type=patch_type,
3617
 
            message=message)
 
3672
            public_branch=public_branch, include_patch=include_patch,
 
3673
            include_bundle=include_bundle, message=message,
 
3674
            base_revision_id=base_revision_id)
3618
3675
        if mail_to is None:
3619
3676
            if sign:
3620
3677
                self.outf.write(directive.to_signed(branch))
3626
3683
            s.send_email(message)
3627
3684
 
3628
3685
 
 
3686
class cmd_submit(Command):
 
3687
    """Create a merge-directive for submiting changes.
 
3688
 
 
3689
    A merge directive provides many things needed for requesting merges:
 
3690
    - A machine-readable description of the merge to perform
 
3691
    - An optional patch that is a preview of the changes requested
 
3692
    - An optional bundle of revision data, so that the changes can be applied
 
3693
      directly from the merge directive, without retrieving data from a
 
3694
      branch.
 
3695
 
 
3696
    If --no-bundle is specified, then public_branch is needed (and must be
 
3697
    up-to-date), so that the receiver can perform the merge using the
 
3698
    public_branch.  The public_branch is always included if known, so that
 
3699
    people can check it later.
 
3700
 
 
3701
    The submit branch defaults to the parent, but can be overridden.  Both
 
3702
    submit branch and public branch will be remembered if supplied.
 
3703
 
 
3704
    If a public_branch is known for the submit_branch, that public submit
 
3705
    branch is used in the merge instructions.  This means that a local mirror
 
3706
    can be used as your actual submit branch, once you have set public_branch
 
3707
    for that mirror.
 
3708
    """
 
3709
 
 
3710
    encoding_type = 'exact'
 
3711
 
 
3712
    aliases = ['bundle', 'bundle-revisions']
 
3713
 
 
3714
    _see_also = ['merge']
 
3715
 
 
3716
    takes_args = ['submit_branch?', 'public_branch?']
 
3717
    takes_options = [
 
3718
        Option('no-bundle',
 
3719
               help='Do not include a bundle in the merge directive.'),
 
3720
        Option('no-patch', help='Do not include a preview patch in the merge'
 
3721
               ' directive.'),
 
3722
        Option('remember',
 
3723
               help='Remember submit and public branch.'),
 
3724
        Option('from',
 
3725
               help='Branch to generate the submission from, '
 
3726
               'rather than the one containing the working directory.',
 
3727
               short_name='f',
 
3728
               type=unicode),
 
3729
        Option('output', short_name='o', help='Write directive to this file.',
 
3730
               type=unicode),
 
3731
        'revision',
 
3732
        ]
 
3733
 
 
3734
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
 
3735
            no_patch=False, revision=None, remember=False, output=None,
 
3736
            **kwargs):
 
3737
        from bzrlib.revision import ensure_null, NULL_REVISION
 
3738
        if output is None:
 
3739
            outfile = self.outf
 
3740
        else:
 
3741
            outfile = open(output, 'wb')
 
3742
        try:
 
3743
            from_ = kwargs.get('from', '.')
 
3744
            branch = Branch.open_containing(from_)[0]
 
3745
            if remember and submit_branch is None:
 
3746
                raise errors.BzrCommandError(
 
3747
                    '--remember requires a branch to be specified.')
 
3748
            stored_submit_branch = branch.get_submit_branch()
 
3749
            remembered_submit_branch = False
 
3750
            if submit_branch is None:
 
3751
                submit_branch = stored_submit_branch
 
3752
                remembered_submit_branch = True
 
3753
            else:
 
3754
                if stored_submit_branch is None or remember:
 
3755
                    branch.set_submit_branch(submit_branch)
 
3756
            if submit_branch is None:
 
3757
                submit_branch = branch.get_parent()
 
3758
                remembered_submit_branch = True
 
3759
            if submit_branch is None:
 
3760
                raise errors.BzrCommandError('No submit branch known or'
 
3761
                                             ' specified')
 
3762
            if remembered_submit_branch:
 
3763
                note('Using saved location: %s', submit_branch)
 
3764
 
 
3765
            stored_public_branch = branch.get_public_branch()
 
3766
            if public_branch is None:
 
3767
                public_branch = stored_public_branch
 
3768
            elif stored_public_branch is None or remember:
 
3769
                branch.set_public_branch(public_branch)
 
3770
            if no_bundle and public_branch is None:
 
3771
                raise errors.BzrCommandError('No public branch specified or'
 
3772
                                             ' known')
 
3773
            base_revision_id = None
 
3774
            if revision is not None:
 
3775
                if len(revision) > 2:
 
3776
                    raise errors.BzrCommandError('bzr submit takes '
 
3777
                        'at most two one revision identifiers')
 
3778
                revision_id = revision[-1].in_history(branch).rev_id
 
3779
                if len(revision) == 2:
 
3780
                    base_revision_id = revision[0].in_history(branch).rev_id
 
3781
                    base_revision_id = ensure_null(base_revision_id)
 
3782
            else:
 
3783
                revision_id = branch.last_revision()
 
3784
            revision_id = ensure_null(revision_id)
 
3785
            if revision_id == NULL_REVISION:
 
3786
                raise errors.BzrCommandError('No revisions to submit.')
 
3787
            directive = merge_directive.MergeDirective2.from_objects(
 
3788
                branch.repository, revision_id, time.time(),
 
3789
                osutils.local_time_offset(), submit_branch,
 
3790
                public_branch=public_branch, include_patch=not no_patch,
 
3791
                include_bundle=not no_bundle, message=None,
 
3792
                base_revision_id=base_revision_id)
 
3793
            outfile.writelines(directive.to_lines())
 
3794
        finally:
 
3795
            if output is not None:
 
3796
                outfile.close()
 
3797
 
3629
3798
class cmd_tag(Command):
3630
3799
    """Create a tag naming a revision.
3631
3800
    
3719
3888
                  pull=False,
3720
3889
                  pb=DummyProgress(),
3721
3890
                  change_reporter=None,
3722
 
                  other_rev_id=None):
 
3891
                  other_rev_id=None, base_rev_id=None,
 
3892
                  possible_transports=None):
3723
3893
    """Merge changes into a tree.
3724
3894
 
3725
3895
    base_revision
3778
3948
        if other_rev_id is not None:
3779
3949
            merger.set_other_revision(other_rev_id, this_tree.branch)
3780
3950
        else:
3781
 
            merger.set_other(other_revision)
 
3951
            merger.set_other(other_revision, possible_transports)
3782
3952
        merger.pp.next_phase()
3783
 
        merger.set_base(base_revision)
 
3953
        if base_rev_id is not None:
 
3954
            merger.set_base_revision(base_rev_id, this_tree.branch)
 
3955
        elif base_revision is not None:
 
3956
            merger.set_base(base_revision)
 
3957
        else:
 
3958
            merger.find_base()
3784
3959
        if merger.base_rev_id == merger.other_rev_id:
3785
3960
            note('Nothing to do.')
3786
3961
            return 0
3829
4004
        cur_transport.ensure_base()
3830
4005
 
3831
4006
 
 
4007
def _get_bundle_helper(location):
 
4008
    """Get a bundle if 'location' points to one.
 
4009
 
 
4010
    Try try to identify a bundle and returns its mergeable form. If it's not,
 
4011
    we return the tried transport anyway so that it can reused to access the
 
4012
    branch
 
4013
 
 
4014
    :param location: can point to a bundle or a branch.
 
4015
 
 
4016
    :return: mergeable, transport
 
4017
    """
 
4018
    mergeable = None
 
4019
    url = urlutils.normalize_url(location)
 
4020
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
 
4021
    location_transport = transport.get_transport(url)
 
4022
    if filename:
 
4023
        try:
 
4024
            # There may be redirections but we ignore the intermediate
 
4025
            # and final transports used
 
4026
            read = bundle.read_mergeable_from_transport
 
4027
            mergeable, t = read(location_transport, filename)
 
4028
        except errors.NotABundle:
 
4029
            # Continue on considering this url a Branch but adjust the
 
4030
            # location_transport
 
4031
            location_transport = location_transport.clone(filename)
 
4032
    return mergeable, location_transport
 
4033
 
 
4034
 
3832
4035
# Compatibility
3833
4036
merge = _merge_helper
3834
4037
 
3840
4043
# details were needed.
3841
4044
from bzrlib.cmd_version_info import cmd_version_info
3842
4045
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3843
 
from bzrlib.bundle.commands import cmd_bundle_revisions
 
4046
from bzrlib.bundle.commands import (
 
4047
    cmd_bundle_info,
 
4048
    )
3844
4049
from bzrlib.sign_my_commits import cmd_sign_my_commits
3845
4050
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3846
4051
        cmd_weave_plan_merge, cmd_weave_merge_text