/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2008-02-06 04:06:42 UTC
  • mfrom: (3216 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3217.
  • Revision ID: robertc@robertcollins.net-20080206040642-2efx3l4iv5f95lxp
Merge up with bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
610
610
            else:
611
611
                display_url = urlutils.unescape_for_display(stored_loc,
612
612
                        self.outf.encoding)
613
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
613
                if not is_quiet():
 
614
                    self.outf.write("Using saved location: %s\n" % display_url)
614
615
                location = stored_loc
615
616
                location_transport = transport.get_transport(
616
617
                    location, possible_transports=possible_transports)
747
748
            # The destination doesn't exist; create it.
748
749
            # XXX: Refactor the create_prefix/no_create_prefix code into a
749
750
            #      common helper function
 
751
 
 
752
            def make_directory(transport):
 
753
                transport.mkdir('.')
 
754
                return transport
 
755
 
 
756
            def redirected(redirected_transport, e, redirection_notice):
 
757
                return transport.get_transport(e.get_target_url())
 
758
 
750
759
            try:
751
 
                to_transport.mkdir('.')
 
760
                to_transport = transport.do_catching_redirections(
 
761
                    make_directory, to_transport, redirected)
752
762
            except errors.FileExists:
753
763
                if not use_existing_dir:
754
764
                    raise errors.BzrCommandError("Target directory %s"
763
773
                        " leading parent directories."
764
774
                        % location)
765
775
                _create_prefix(to_transport)
 
776
            except errors.TooManyRedirections:
 
777
                raise errors.BzrCommandError("Too many redirections trying "
 
778
                                             "to make %s." % location)
766
779
 
767
780
            # Now the target directory exists, but doesn't have a .bzr
768
781
            # directory. So we need to create it, along with any work to create
862
875
            raise errors.BzrCommandError(
863
876
                'bzr branch --revision takes exactly 1 revision value')
864
877
 
865
 
        br_from = Branch.open(from_location)
 
878
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
 
879
            from_location)
866
880
        br_from.lock_read()
867
881
        try:
868
882
            if len(revision) == 1 and revision[0] is not None:
890
904
            try:
891
905
                # preserve whatever source format we have.
892
906
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
893
 
                                            possible_transports=[to_transport])
 
907
                                            possible_transports=[to_transport],
 
908
                                            accelerator_tree=accelerator_tree)
894
909
                branch = dir.open_branch()
895
910
            except errors.NoSuchRevision:
896
911
                to_transport.delete_tree('.')
935
950
                                 "common operations like diff and status without "
936
951
                                 "such access, and also support local commits."
937
952
                            ),
 
953
                     Option('files-from',
 
954
                            help="Get file contents from this tree.", type=str)
938
955
                     ]
939
956
    aliases = ['co']
940
957
 
941
958
    def run(self, branch_location=None, to_location=None, revision=None,
942
 
            lightweight=False):
 
959
            lightweight=False, files_from=None):
943
960
        if revision is None:
944
961
            revision = [None]
945
962
        elif len(revision) > 1:
948
965
        if branch_location is None:
949
966
            branch_location = osutils.getcwd()
950
967
            to_location = branch_location
951
 
        source = Branch.open(branch_location)
 
968
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
 
969
            branch_location)
 
970
        if files_from is not None:
 
971
            accelerator_tree = WorkingTree.open(files_from)
952
972
        if len(revision) == 1 and revision[0] is not None:
953
973
            revision_id = _mod_revision.ensure_null(
954
974
                revision[0].in_history(source)[1])
966
986
            except errors.NoWorkingTree:
967
987
                source.bzrdir.create_workingtree(revision_id)
968
988
                return
969
 
        source.create_checkout(to_location, revision_id, lightweight)
 
989
        source.create_checkout(to_location, revision_id, lightweight,
 
990
                               accelerator_tree)
970
991
 
971
992
 
972
993
class cmd_renames(Command):
1255
1276
        bzr init
1256
1277
        bzr add .
1257
1278
        bzr status
1258
 
        bzr commit -m 'imported project'
 
1279
        bzr commit -m "imported project"
1259
1280
    """
1260
1281
 
1261
1282
    _see_also = ['init-repository', 'branch', 'checkout']
1378
1399
 
1379
1400
 
1380
1401
class cmd_diff(Command):
1381
 
    """Show differences in the working tree or between revisions.
 
1402
    """Show differences in the working tree, between revisions or branches.
1382
1403
    
1383
 
    If files are listed, only the changes in those files are listed.
1384
 
    Otherwise, all changes for the tree are listed.
 
1404
    If no arguments are given, all changes for the current tree are listed.
 
1405
    If files are given, only the changes in those files are listed.
 
1406
    Remote and multiple branches can be compared by using the --old and
 
1407
    --new options. If not provided, the default for both is derived from
 
1408
    the first argument, if any, or the current tree if no arguments are
 
1409
    given.
1385
1410
 
1386
1411
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1387
1412
    produces patches suitable for "patch -p1".
1405
1430
 
1406
1431
            bzr diff -r1..2
1407
1432
 
 
1433
        Difference between revision 2 and revision 1 for branch xxx::
 
1434
 
 
1435
            bzr diff -r1..2 xxx
 
1436
 
 
1437
        Show just the differences for file NEWS::
 
1438
 
 
1439
            bzr diff NEWS
 
1440
 
 
1441
        Show the differences in working tree xxx for file NEWS::
 
1442
 
 
1443
            bzr diff xxx/NEWS
 
1444
 
 
1445
        Show the differences from branch xxx to this working tree:
 
1446
 
 
1447
            bzr diff --old xxx
 
1448
 
 
1449
        Show the differences between two branches for file NEWS::
 
1450
 
 
1451
            bzr diff --old xxx --new yyy NEWS
 
1452
 
1408
1453
        Same as 'bzr diff' but prefix paths with old/ and new/::
1409
1454
 
1410
1455
            bzr diff --prefix old/:new/
1411
 
 
1412
 
        Show the differences between the two working trees::
1413
 
 
1414
 
            bzr diff bzr.mine bzr.dev
1415
 
 
1416
 
        Show just the differences for 'foo.c'::
1417
 
 
1418
 
            bzr diff foo.c
1419
1456
    """
1420
 
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1421
 
    #       or a graphical diff.
1422
 
 
1423
 
    # TODO: Python difflib is not exactly the same as unidiff; should
1424
 
    #       either fix it up or prefer to use an external diff.
1425
 
 
1426
 
    # TODO: Selected-file diff is inefficient and doesn't show you
1427
 
    #       deleted files.
1428
 
 
1429
 
    # TODO: This probably handles non-Unix newlines poorly.
1430
 
 
1431
1457
    _see_also = ['status']
1432
1458
    takes_args = ['file*']
1433
1459
    takes_options = [
1437
1463
               short_name='p',
1438
1464
               help='Set prefixes added to old and new filenames, as '
1439
1465
                    'two values separated by a colon. (eg "old/:new/").'),
 
1466
        Option('old',
 
1467
            help='Branch/tree to compare from.',
 
1468
            type=unicode,
 
1469
            ),
 
1470
        Option('new',
 
1471
            help='Branch/tree to compare to.',
 
1472
            type=unicode,
 
1473
            ),
1440
1474
        'revision',
1441
1475
        'change',
 
1476
        Option('using',
 
1477
            help='Use this command to compare files.',
 
1478
            type=unicode,
 
1479
            ),
1442
1480
        ]
1443
1481
    aliases = ['di', 'dif']
1444
1482
    encoding_type = 'exact'
1445
1483
 
1446
1484
    @display_command
1447
1485
    def run(self, revision=None, file_list=None, diff_options=None,
1448
 
            prefix=None):
1449
 
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
 
1486
            prefix=None, old=None, new=None, using=None):
 
1487
        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1450
1488
 
1451
1489
        if (prefix is None) or (prefix == '0'):
1452
1490
            # diff -p0 format
1466
1504
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1467
1505
                                         ' one or two revision specifiers')
1468
1506
 
1469
 
        try:
1470
 
            tree1, file_list = internal_tree_files(file_list)
1471
 
            tree2 = None
1472
 
            b = None
1473
 
            b2 = None
1474
 
        except errors.FileInWrongBranch:
1475
 
            if len(file_list) != 2:
1476
 
                raise errors.BzrCommandError("Files are in different branches")
1477
 
 
1478
 
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1479
 
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1480
 
            if file1 != "" or file2 != "":
1481
 
                # FIXME diff those two files. rbc 20051123
1482
 
                raise errors.BzrCommandError("Files are in different branches")
1483
 
            file_list = None
1484
 
        except errors.NotBranchError:
1485
 
            if (revision is not None and len(revision) == 2
1486
 
                and not revision[0].needs_branch()
1487
 
                and not revision[1].needs_branch()):
1488
 
                # If both revision specs include a branch, we can
1489
 
                # diff them without needing a local working tree
1490
 
                tree1, tree2 = None, None
1491
 
            else:
1492
 
                raise
1493
 
 
1494
 
        if tree2 is not None:
1495
 
            if revision is not None:
1496
 
                # FIXME: but there should be a clean way to diff between
1497
 
                # non-default versions of two trees, it's not hard to do
1498
 
                # internally...
1499
 
                raise errors.BzrCommandError(
1500
 
                        "Sorry, diffing arbitrary revisions across branches "
1501
 
                        "is not implemented yet")
1502
 
            return show_diff_trees(tree1, tree2, sys.stdout, 
1503
 
                                   specific_files=file_list,
1504
 
                                   external_diff_options=diff_options,
1505
 
                                   old_label=old_label, new_label=new_label)
1506
 
 
1507
 
        return diff_cmd_helper(tree1, file_list, diff_options,
1508
 
                               revision_specs=revision,
1509
 
                               old_label=old_label, new_label=new_label)
 
1507
        old_tree, new_tree, specific_files, extra_trees = \
 
1508
                _get_trees_to_diff(file_list, revision, old, new)
 
1509
        return show_diff_trees(old_tree, new_tree, sys.stdout, 
 
1510
                               specific_files=specific_files,
 
1511
                               external_diff_options=diff_options,
 
1512
                               old_label=old_label, new_label=new_label,
 
1513
                               extra_trees=extra_trees, using=using)
1510
1514
 
1511
1515
 
1512
1516
class cmd_deleted(Command):
1654
1658
                        'regular expression.',
1655
1659
                   type=str),
1656
1660
            Option('limit',
 
1661
                   short_name='l',
1657
1662
                   help='Limit the output to the first N revisions.',
1658
1663
                   argname='N',
1659
1664
                   type=_parse_limit),
1915
1920
 
1916
1921
        Ignore class files in all directories::
1917
1922
 
1918
 
            bzr ignore '*.class'
1919
 
 
1920
 
        Ignore .o files under the lib directory::
1921
 
 
1922
 
            bzr ignore 'lib/**/*.o'
1923
 
 
1924
 
        Ignore .o files under the lib directory::
1925
 
 
1926
 
            bzr ignore 'RE:lib/.*\.o'
 
1923
            bzr ignore "*.class"
 
1924
 
 
1925
        Ignore .o files under the lib directory::
 
1926
 
 
1927
            bzr ignore "lib/**/*.o"
 
1928
 
 
1929
        Ignore .o files under the lib directory::
 
1930
 
 
1931
            bzr ignore "RE:lib/.*\.o"
1927
1932
    """
1928
1933
 
1929
1934
    _see_also = ['status', 'ignored']
1997
2002
    """List ignored files and the patterns that matched them.
1998
2003
    """
1999
2004
 
 
2005
    encoding_type = 'replace'
2000
2006
    _see_also = ['ignore']
 
2007
 
2001
2008
    @display_command
2002
2009
    def run(self):
2003
2010
        tree = WorkingTree.open_containing(u'.')[0]
2008
2015
                    continue
2009
2016
                ## XXX: Slightly inefficient since this was already calculated
2010
2017
                pat = tree.is_ignored(path)
2011
 
                print '%-50s %s' % (path, pat)
 
2018
                self.outf.write('%-50s %s\n' % (path, pat))
2012
2019
        finally:
2013
2020
            tree.unlock()
2014
2021
 
2114
2121
    def run(self, filename, revision=None, name_from_revision=False):
2115
2122
        if revision is not None and len(revision) != 1:
2116
2123
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2117
 
                                        " one number")
2118
 
        tree = None
2119
 
        try:
2120
 
            tree, b, relpath = \
2121
 
                    bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2122
 
        except errors.NotBranchError:
2123
 
            pass
2124
 
 
2125
 
        if revision is not None and revision[0].get_branch() is not None:
2126
 
            b = Branch.open(revision[0].get_branch())
2127
 
        b.lock_read()
2128
 
        try:
2129
 
            return self._run(tree, b, relpath, filename, revision,
2130
 
                name_from_revision)
 
2124
                                         " one revision specifier")
 
2125
        tree, branch, relpath = \
 
2126
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
2127
        branch.lock_read()
 
2128
        try:
 
2129
            return self._run(tree, branch, relpath, filename, revision,
 
2130
                             name_from_revision)
2131
2131
        finally:
2132
 
            b.unlock()
 
2132
            branch.unlock()
2133
2133
 
2134
2134
    def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2135
2135
        if tree is None:
2226
2226
                    "files in the working tree."),
2227
2227
             ListOption('fixes', type=str,
2228
2228
                    help="Mark a bug as being fixed by this revision."),
2229
 
             Option('author', type=str,
 
2229
             Option('author', type=unicode,
2230
2230
                    help="Set the author's name, if it's different "
2231
2231
                         "from the committer."),
2232
2232
             Option('local',
2444
2444
 
2445
2445
        Set the current user::
2446
2446
 
2447
 
            bzr whoami 'Frank Chu <fchu@example.com>'
 
2447
            bzr whoami "Frank Chu <fchu@example.com>"
2448
2448
    """
2449
2449
    takes_options = [ Option('email',
2450
2450
                             help='Display email address only.'),
2599
2599
                                 ' expression.'),
2600
2600
                     Option('strict', help='Fail on missing dependencies or '
2601
2601
                            'known failures.'),
 
2602
                     Option('load-list', type=str, argname='TESTLISTFILE',
 
2603
                            help='Load a test id list from a text file.'),
2602
2604
                     ]
2603
2605
    encoding_type = 'replace'
2604
2606
 
2606
2608
            transport=None, benchmark=None,
2607
2609
            lsprof_timed=None, cache_dir=None,
2608
2610
            first=False, list_only=False,
2609
 
            randomize=None, exclude=None, strict=False):
 
2611
            randomize=None, exclude=None, strict=False,
 
2612
            load_list=None):
2610
2613
        import bzrlib.ui
2611
2614
        from bzrlib.tests import selftest
2612
2615
        import bzrlib.benchmarks as benchmarks
2648
2651
                              random_seed=randomize,
2649
2652
                              exclude_pattern=exclude,
2650
2653
                              strict=strict,
 
2654
                              load_list=load_list,
2651
2655
                              )
2652
2656
        finally:
2653
2657
            if benchfile is not None:
2756
2760
            bzr merge -r 81..82 ../bzr.dev
2757
2761
    """
2758
2762
 
 
2763
    encoding_type = 'exact'
2759
2764
    _see_also = ['update', 'remerge', 'status-flags']
2760
2765
    takes_args = ['branch?']
2761
2766
    takes_options = [
2780
2785
               short_name='d',
2781
2786
               type=unicode,
2782
2787
               ),
 
2788
        Option('preview', help='Instead of merging, show a diff of the merge.')
2783
2789
    ]
2784
2790
 
2785
2791
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2786
2792
            show_base=False, reprocess=False, remember=False,
2787
2793
            uncommitted=False, pull=False,
2788
2794
            directory=None,
 
2795
            preview=False,
2789
2796
            ):
2790
2797
        # This is actually a branch (or merge-directive) *location*.
2791
2798
        location = branch
2841
2848
            merger.merge_type = merge_type
2842
2849
            merger.reprocess = reprocess
2843
2850
            merger.show_base = show_base
2844
 
            merger.change_reporter = change_reporter
2845
2851
            self.sanity_check_merger(merger)
2846
2852
            if (merger.base_rev_id == merger.other_rev_id and
2847
2853
                merger.other_rev_id != None):
2856
2862
                    result.report(self.outf)
2857
2863
                    return 0
2858
2864
            merger.check_basis(not force)
2859
 
            conflict_count = merger.do_merge()
2860
 
            if allow_pending:
2861
 
                merger.set_pending()
2862
 
            if verified == 'failed':
2863
 
                warning('Preview patch does not match changes')
2864
 
            if conflict_count != 0:
2865
 
                return 1
 
2865
            if preview:
 
2866
                return self._do_preview(merger)
2866
2867
            else:
2867
 
                return 0
 
2868
                return self._do_merge(merger, change_reporter, allow_pending,
 
2869
                                      verified)
2868
2870
        finally:
2869
2871
            for cleanup in reversed(cleanups):
2870
2872
                cleanup()
2871
2873
 
 
2874
    def _do_preview(self, merger):
 
2875
        from bzrlib.diff import show_diff_trees
 
2876
        tree_merger = merger.make_merger()
 
2877
        tt = tree_merger.make_preview_transform()
 
2878
        try:
 
2879
            result_tree = tt.get_preview_tree()
 
2880
            show_diff_trees(merger.this_tree, result_tree, self.outf,
 
2881
                            old_label='', new_label='')
 
2882
        finally:
 
2883
            tt.finalize()
 
2884
 
 
2885
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
 
2886
        merger.change_reporter = change_reporter
 
2887
        conflict_count = merger.do_merge()
 
2888
        if allow_pending:
 
2889
            merger.set_pending()
 
2890
        if verified == 'failed':
 
2891
            warning('Preview patch does not match changes')
 
2892
        if conflict_count != 0:
 
2893
            return 1
 
2894
        else:
 
2895
            return 0
 
2896
 
2872
2897
    def sanity_check_merger(self, merger):
2873
2898
        if (merger.show_base and
2874
2899
            not merger.merge_type is _mod_merge.Merge3Merger):
2888
2913
        from bzrlib.tag import _merge_tags_if_possible
2889
2914
        assert revision is None or len(revision) < 3
2890
2915
        # find the branch locations
2891
 
        other_loc, location = self._select_branch_location(tree, location,
 
2916
        other_loc, user_location = self._select_branch_location(tree, location,
2892
2917
            revision, -1)
2893
2918
        if revision is not None and len(revision) == 2:
2894
 
            base_loc, location = self._select_branch_location(tree, location,
2895
 
                                                              revision, 0)
 
2919
            base_loc, _unused = self._select_branch_location(tree,
 
2920
                location, revision, 0)
2896
2921
        else:
2897
2922
            base_loc = other_loc
2898
2923
        # Open the branches
2919
2944
        else:
2920
2945
            base_revision_id = None
2921
2946
        # Remember where we merge from
2922
 
        if ((tree.branch.get_parent() is None or remember) and
2923
 
            other_branch is not None):
2924
 
            tree.branch.set_parent(other_branch.base)
 
2947
        if ((remember or tree.branch.get_submit_branch() is None) and
 
2948
             user_location is not None):
 
2949
            tree.branch.set_submit_branch(other_branch.base)
2925
2950
        _merge_tags_if_possible(other_branch, tree.branch)
2926
2951
        merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2927
2952
            other_revision_id, base_revision_id, other_branch, base_branch)
2932
2957
            allow_pending = True
2933
2958
        return merger, allow_pending
2934
2959
 
2935
 
    def _select_branch_location(self, tree, location, revision=None,
 
2960
    def _select_branch_location(self, tree, user_location, revision=None,
2936
2961
                                index=None):
2937
2962
        """Select a branch location, according to possible inputs.
2938
2963
 
2940
2965
        ``revision`` and ``index`` must be supplied.)
2941
2966
 
2942
2967
        Otherwise, the ``location`` parameter is used.  If it is None, then the
2943
 
        ``parent`` location is used, and a note is printed.
 
2968
        ``submit`` or ``parent`` location is used, and a note is printed.
2944
2969
 
2945
2970
        :param tree: The working tree to select a branch for merging into
2946
2971
        :param location: The location entered by the user
2947
2972
        :param revision: The revision parameter to the command
2948
2973
        :param index: The index to use for the revision parameter.  Negative
2949
2974
            indices are permitted.
2950
 
        :return: (selected_location, default_location).  The default location
2951
 
            will be the user-entered location, if any, or else the remembered
2952
 
            location.
 
2975
        :return: (selected_location, user_location).  The default location
 
2976
            will be the user-entered location.
2953
2977
        """
2954
2978
        if (revision is not None and index is not None
2955
2979
            and revision[index] is not None):
2956
2980
            branch = revision[index].get_branch()
2957
2981
            if branch is not None:
2958
 
                return branch, location
2959
 
        location = self._get_remembered_parent(tree, location, 'Merging from')
2960
 
        return location, location
 
2982
                return branch, branch
 
2983
        if user_location is None:
 
2984
            location = self._get_remembered(tree, 'Merging from')
 
2985
        else:
 
2986
            location = user_location
 
2987
        return location, user_location
2961
2988
 
2962
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2963
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
 
2989
    def _get_remembered(self, tree, verb_string):
2964
2990
        """Use tree.branch's parent if none was supplied.
2965
2991
 
2966
2992
        Report if the remembered location was used.
2967
2993
        """
2968
 
        if supplied_location is not None:
2969
 
            return supplied_location
2970
 
        stored_location = tree.branch.get_parent()
 
2994
        stored_location = tree.branch.get_submit_branch()
 
2995
        if stored_location is None:
 
2996
            stored_location = tree.branch.get_parent()
2971
2997
        mutter("%s", stored_location)
2972
2998
        if stored_location is None:
2973
2999
            raise errors.BzrCommandError("No location specified or remembered")
3021
3047
                                             " merges.  Not cherrypicking or"
3022
3048
                                             " multi-merges.")
3023
3049
            repository = tree.branch.repository
3024
 
            graph = repository.get_graph()
3025
 
            base_revision = graph.find_unique_lca(parents[0], parents[1])
3026
 
            base_tree = repository.revision_tree(base_revision)
3027
 
            other_tree = repository.revision_tree(parents[1])
3028
3050
            interesting_ids = None
3029
3051
            new_conflicts = []
3030
3052
            conflicts = tree.conflicts()
3060
3082
            # list, we imply that the working tree text has seen and rejected
3061
3083
            # all the changes from the other tree, when in fact those changes
3062
3084
            # have not yet been seen.
 
3085
            pb = ui.ui_factory.nested_progress_bar()
3063
3086
            tree.set_parent_ids(parents[:1])
3064
3087
            try:
3065
 
                conflicts = _mod_merge.merge_inner(
3066
 
                                          tree.branch, other_tree, base_tree,
3067
 
                                          this_tree=tree,
3068
 
                                          interesting_ids=interesting_ids,
3069
 
                                          other_rev_id=parents[1],
3070
 
                                          merge_type=merge_type,
3071
 
                                          show_base=show_base,
3072
 
                                          reprocess=reprocess)
 
3088
                merger = _mod_merge.Merger.from_revision_ids(pb,
 
3089
                                                             tree, parents[1])
 
3090
                merger.interesting_ids = interesting_ids
 
3091
                merger.merge_type = merge_type
 
3092
                merger.show_base = show_base
 
3093
                merger.reprocess = reprocess
 
3094
                conflicts = merger.do_merge()
3073
3095
            finally:
3074
3096
                tree.set_parent_ids(parents)
 
3097
                pb.finished()
3075
3098
        finally:
3076
3099
            tree.unlock()
3077
3100
        if conflicts > 0:
3326
3349
class cmd_plugins(Command):
3327
3350
    """List the installed plugins.
3328
3351
    
3329
 
    This command displays the list of installed plugins including the
3330
 
    path where each one is located and a short description of each.
 
3352
    This command displays the list of installed plugins including
 
3353
    version of plugin and a short description of each.
 
3354
 
 
3355
    --verbose shows the path where each plugin is located.
3331
3356
 
3332
3357
    A plugin is an external component for Bazaar that extends the
3333
3358
    revision control system, by adding or replacing code in Bazaar.
3340
3365
    install them. Instructions are also provided there on how to
3341
3366
    write new plugins using the Python programming language.
3342
3367
    """
 
3368
    takes_options = ['verbose']
3343
3369
 
3344
3370
    @display_command
3345
 
    def run(self):
 
3371
    def run(self, verbose=False):
3346
3372
        import bzrlib.plugin
3347
3373
        from inspect import getdoc
 
3374
        result = []
3348
3375
        for name, plugin in bzrlib.plugin.plugins().items():
3349
 
            print plugin.path(), "[%s]" % plugin.__version__
 
3376
            version = plugin.__version__
 
3377
            if version == 'unknown':
 
3378
                version = ''
 
3379
            name_ver = '%s %s' % (name, version)
3350
3380
            d = getdoc(plugin.module)
3351
3381
            if d:
3352
 
                print '\t', d.split('\n')[0]
 
3382
                doc = d.split('\n')[0]
 
3383
            else:
 
3384
                doc = '(no description)'
 
3385
            result.append((name_ver, doc, plugin.path()))
 
3386
        for name_ver, doc, path in sorted(result):
 
3387
            print name_ver
 
3388
            print '   ', doc
 
3389
            if verbose:
 
3390
                print '   ', path
 
3391
            print
3353
3392
 
3354
3393
 
3355
3394
class cmd_testament(Command):
3408
3447
    def run(self, filename, all=False, long=False, revision=None,
3409
3448
            show_ids=False):
3410
3449
        from bzrlib.annotate import annotate_file
3411
 
        tree, relpath = WorkingTree.open_containing(filename)
3412
 
        branch = tree.branch
3413
 
        branch.lock_read()
 
3450
        wt, branch, relpath = \
 
3451
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
3452
        if wt is not None:
 
3453
            wt.lock_read()
 
3454
        else:
 
3455
            branch.lock_read()
3414
3456
        try:
3415
3457
            if revision is None:
3416
3458
                revision_id = branch.last_revision()
3418
3460
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3419
3461
            else:
3420
3462
                revision_id = revision[0].in_history(branch).rev_id
3421
 
            file_id = tree.path2id(relpath)
 
3463
            tree = branch.repository.revision_tree(revision_id)
 
3464
            if wt is not None:
 
3465
                file_id = wt.path2id(relpath)
 
3466
            else:
 
3467
                file_id = tree.path2id(relpath)
3422
3468
            if file_id is None:
3423
3469
                raise errors.NotVersionedError(filename)
3424
 
            tree = branch.repository.revision_tree(revision_id)
3425
3470
            file_version = tree.inventory[file_id].revision
3426
3471
            annotate_file(branch, file_version, file_id, long, all, self.outf,
3427
3472
                          show_ids=show_ids)
3428
3473
        finally:
3429
 
            branch.unlock()
 
3474
            if wt is not None:
 
3475
                wt.unlock()
 
3476
            else:
 
3477
                branch.unlock()
3430
3478
 
3431
3479
 
3432
3480
class cmd_re_sign(Command):
3570
3618
                    Option('force', help='Say yes to all questions.')]
3571
3619
    takes_args = ['location?']
3572
3620
    aliases = []
 
3621
    encoding_type = 'replace'
3573
3622
 
3574
3623
    def run(self, location=None,
3575
3624
            dry_run=False, verbose=False,
3576
3625
            revision=None, force=False):
3577
 
        from bzrlib.log import log_formatter, show_log
3578
 
        from bzrlib.uncommit import uncommit
3579
 
 
3580
3626
        if location is None:
3581
3627
            location = u'.'
3582
3628
        control, relpath = bzrdir.BzrDir.open_containing(location)
3587
3633
            tree = None
3588
3634
            b = control.open_branch()
3589
3635
 
 
3636
        if tree is not None:
 
3637
            tree.lock_write()
 
3638
        else:
 
3639
            b.lock_write()
 
3640
        try:
 
3641
            return self._run(b, tree, dry_run, verbose, revision, force)
 
3642
        finally:
 
3643
            if tree is not None:
 
3644
                tree.unlock()
 
3645
            else:
 
3646
                b.unlock()
 
3647
 
 
3648
    def _run(self, b, tree, dry_run, verbose, revision, force):
 
3649
        from bzrlib.log import log_formatter, show_log
 
3650
        from bzrlib.uncommit import uncommit
 
3651
 
 
3652
        last_revno, last_rev_id = b.last_revision_info()
 
3653
 
3590
3654
        rev_id = None
3591
3655
        if revision is None:
3592
 
            revno = b.revno()
 
3656
            revno = last_revno
 
3657
            rev_id = last_rev_id
3593
3658
        else:
3594
3659
            # 'bzr uncommit -r 10' actually means uncommit
3595
3660
            # so that the final tree is at revno 10.
3596
3661
            # but bzrlib.uncommit.uncommit() actually uncommits
3597
3662
            # the revisions that are supplied.
3598
3663
            # So we need to offset it by one
3599
 
            revno = revision[0].in_history(b).revno+1
 
3664
            revno = revision[0].in_history(b).revno + 1
 
3665
            if revno <= last_revno:
 
3666
                rev_id = b.get_rev_id(revno)
3600
3667
 
3601
 
        if revno <= b.revno():
3602
 
            rev_id = b.get_rev_id(revno)
3603
3668
        if rev_id is None or _mod_revision.is_null(rev_id):
3604
3669
            self.outf.write('No revisions to uncommit.\n')
3605
3670
            return 1
3613
3678
                 verbose=False,
3614
3679
                 direction='forward',
3615
3680
                 start_revision=revno,
3616
 
                 end_revision=b.revno())
 
3681
                 end_revision=last_revno)
3617
3682
 
3618
3683
        if dry_run:
3619
3684
            print 'Dry-run, pretending to remove the above revisions.'
3628
3693
                    return 0
3629
3694
 
3630
3695
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3631
 
                revno=revno)
 
3696
                 revno=revno)
3632
3697
 
3633
3698
 
3634
3699
class cmd_break_lock(Command):
3693
3758
        ]
3694
3759
 
3695
3760
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
3761
        from bzrlib import lockdir
3696
3762
        from bzrlib.smart import medium, server
3697
3763
        from bzrlib.transport import get_transport
3698
3764
        from bzrlib.transport.chroot import ChrootServer
3723
3789
        # be changed with care though, as we dont want to use bandwidth sending
3724
3790
        # progress over stderr to smart server clients!
3725
3791
        old_factory = ui.ui_factory
 
3792
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3726
3793
        try:
3727
3794
            ui.ui_factory = ui.SilentUIFactory()
 
3795
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3728
3796
            smart_server.serve()
3729
3797
        finally:
3730
3798
            ui.ui_factory = old_factory
 
3799
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
3731
3800
 
3732
3801
 
3733
3802
class cmd_join(Command):
3785
3854
 
3786
3855
 
3787
3856
class cmd_split(Command):
3788
 
    """Split a tree into two trees.
 
3857
    """Split a subdirectory of a tree into a separate tree.
3789
3858
 
3790
 
    This command is for experimental use only.  It requires the target tree
3791
 
    to be in dirstate-with-subtree format, which cannot be converted into
3792
 
    earlier formats.
 
3859
    This command will produce a target tree in a format that supports
 
3860
    rich roots, like 'rich-root' or 'rich-root-pack'.  These formats cannot be
 
3861
    converted into earlier formats like 'dirstate-tags'.
3793
3862
 
3794
3863
    The TREE argument should be a subdirectory of a working tree.  That
3795
3864
    subdirectory will be converted into an independent tree, with its own
3796
3865
    branch.  Commits in the top-level tree will not apply to the new subtree.
3797
 
    If you want that behavior, do "bzr join --reference TREE".
3798
3866
    """
3799
3867
 
3800
 
    _see_also = ['join']
 
3868
    # join is not un-hidden yet
 
3869
    #_see_also = ['join']
3801
3870
    takes_args = ['tree']
3802
3871
 
3803
 
    hidden = True
3804
 
 
3805
3872
    def run(self, tree):
3806
3873
        containing_tree, subdir = WorkingTree.open_containing(tree)
3807
3874
        sub_id = containing_tree.path2id(subdir)
3813
3880
            raise errors.UpgradeRequired(containing_tree.branch.base)
3814
3881
 
3815
3882
 
3816
 
 
3817
3883
class cmd_merge_directive(Command):
3818
3884
    """Generate a merge directive for auto-merge tools.
3819
3885
 
3941
4007
    for that mirror.
3942
4008
 
3943
4009
    Mail is sent using your preferred mail program.  This should be transparent
3944
 
    on Windows (it uses MAPI).  On *nix, it requires the xdg-email utility.  If
3945
 
    the preferred client can't be found (or used), your editor will be used.
 
4010
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
 
4011
    If the preferred client can't be found (or used), your editor will be used.
3946
4012
    
3947
4013
    To use a specific mail program, set the mail_client configuration option.
3948
4014
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
4000
4066
    def _run(self, submit_branch, revision, public_branch, remember, format,
4001
4067
             no_bundle, no_patch, output, from_, mail_to, message):
4002
4068
        from bzrlib.revision import NULL_REVISION
 
4069
        branch = Branch.open_containing(from_)[0]
4003
4070
        if output is None:
4004
4071
            outfile = StringIO()
4005
4072
        elif output == '-':
4006
4073
            outfile = self.outf
4007
4074
        else:
4008
4075
            outfile = open(output, 'wb')
 
4076
        # we may need to write data into branch's repository to calculate
 
4077
        # the data to send.
 
4078
        branch.lock_write()
4009
4079
        try:
4010
 
            branch = Branch.open_containing(from_)[0]
4011
 
            # we may need to write data into branch's repository to calculate
4012
 
            # the data to send.
4013
 
            branch.lock_write()
4014
4080
            if output is None:
4015
4081
                config = branch.get_config()
4016
4082
                if mail_to is None:
4017
4083
                    mail_to = config.get_user_option('submit_to')
4018
 
                if mail_to is None:
4019
 
                    raise errors.BzrCommandError('No mail-to address'
4020
 
                                                 ' specified')
4021
4084
                mail_client = config.get_mail_client()
4022
4085
            if remember and submit_branch is None:
4023
4086
                raise errors.BzrCommandError(
4303
4366
                     value_switches=True, enum_switch=False,
4304
4367
                     branch='Reconfigure to a branch.',
4305
4368
                     tree='Reconfigure to a tree.',
4306
 
                     checkout='Reconfigure to a checkout.'),
 
4369
                     checkout='Reconfigure to a checkout.',
 
4370
                     lightweight_checkout='Reconfigure to a lightweight'
 
4371
                     ' checkout.'),
4307
4372
                     Option('bind-to', help='Branch to bind checkout to.',
4308
4373
                            type=str),
4309
4374
                     Option('force',
4322
4387
        elif target_type == 'checkout':
4323
4388
            reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4324
4389
                                                                  bind_to)
 
4390
        elif target_type == 'lightweight-checkout':
 
4391
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
 
4392
                directory, bind_to)
4325
4393
        reconfiguration.apply(force)
4326
4394
 
4327
4395
 
4328
4396
class cmd_switch(Command):
4329
 
    """Set the branch of a lightweight checkout and update."""
 
4397
    """Set the branch of a checkout and update.
 
4398
    
 
4399
    For lightweight checkouts, this changes the branch being referenced.
 
4400
    For heavyweight checkouts, this checks that there are no local commits
 
4401
    versus the current bound branch, then it makes the local branch a mirror
 
4402
    of the new location and binds to it.
 
4403
    
 
4404
    In both cases, the working tree is updated and uncommitted changes
 
4405
    are merged. The user can commit or revert these as they desire.
 
4406
 
 
4407
    Pending merges need to be committed or reverted before using switch.
 
4408
    """
4330
4409
 
4331
4410
    takes_args = ['to_location']
 
4411
    takes_options = [Option('force',
 
4412
                        help='Switch even if local commits will be lost.')
 
4413
                     ]
4332
4414
 
4333
 
    def run(self, to_location):
 
4415
    def run(self, to_location, force=False):
4334
4416
        from bzrlib import switch
4335
4417
        to_branch = Branch.open(to_location)
4336
4418
        tree_location = '.'
4337
4419
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4338
 
        switch.switch(control_dir, to_branch)
 
4420
        switch.switch(control_dir, to_branch, force)
4339
4421
        note('Switched to branch: %s',
4340
4422
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4341
4423