~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Vincent Ladeuil
  • Date: 2008-01-03 08:49:38 UTC
  • mfrom: (3111.1.31 175524)
  • mto: This revision was merged to the branch mainline in revision 3158.
  • Revision ID: v.ladeuil+lp@free.fr-20080103084938-7kvurk5uvde2ui54
Fix bug #175524, http test servers are 1.1 compliant

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from bzrlib.lazy_import import lazy_import
23
23
lazy_import(globals(), """
24
24
import codecs
25
 
import errno
26
 
import smtplib
27
25
import sys
28
 
import tempfile
29
26
import time
30
27
 
31
28
import bzrlib
32
29
from bzrlib import (
33
 
    branch,
34
30
    bugtracker,
35
31
    bundle,
36
32
    bzrdir,
43
39
    merge as _mod_merge,
44
40
    merge_directive,
45
41
    osutils,
46
 
    registry,
47
 
    repository,
48
 
    revisionspec,
 
42
    reconfigure,
 
43
    revision as _mod_revision,
49
44
    symbol_versioning,
50
45
    transport,
51
46
    tree as _mod_tree,
53
48
    urlutils,
54
49
    )
55
50
from bzrlib.branch import Branch
56
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
57
51
from bzrlib.conflicts import ConflictList
58
 
from bzrlib.revision import common_ancestor
59
52
from bzrlib.revisionspec import RevisionSpec
 
53
from bzrlib.smtp_connection import SMTPConnection
60
54
from bzrlib.workingtree import WorkingTree
61
55
""")
62
56
 
63
57
from bzrlib.commands import Command, display_command
64
 
from bzrlib.option import ListOption, Option, RegistryOption
65
 
from bzrlib.progress import DummyProgress, ProgressPhase
66
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
 
58
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
 
59
from bzrlib.trace import mutter, note, warning, is_quiet, info
67
60
 
68
61
 
69
62
def tree_files(file_list, default_branch=u'.'):
153
146
    To see ignored files use 'bzr ignored'.  For details on the
154
147
    changes to file texts, use 'bzr diff'.
155
148
    
156
 
    --short gives a status flags for each item, similar to the SVN's status
157
 
    command.
158
 
 
159
 
    Column 1: versioning / renames
160
 
      + File versioned
161
 
      - File unversioned
162
 
      R File renamed
163
 
      ? File unknown
164
 
      C File has conflicts
165
 
      P Entry for a pending merge (not a file)
166
 
 
167
 
    Column 2: Contents
168
 
      N File created
169
 
      D File deleted
170
 
      K File kind changed
171
 
      M File modified
172
 
 
173
 
    Column 3: Execute
174
 
      * The execute bit was changed
 
149
    Note that --short or -S gives status flags for each item, similar
 
150
    to Subversion's status command. To get output similar to svn -q,
 
151
    use bzr -SV.
175
152
 
176
153
    If no arguments are specified, the status of the entire working
177
154
    directory is shown.  Otherwise, only the status of the specified
185
162
    # TODO: --no-recurse, --recurse options
186
163
    
187
164
    takes_args = ['file*']
188
 
    takes_options = ['show-ids', 'revision',
189
 
                     Option('short', help='Give short SVN-style status lines'),
190
 
                     Option('versioned', help='Only show versioned files')]
 
165
    takes_options = ['show-ids', 'revision', 'change',
 
166
                     Option('short', help='Use short status indicators.',
 
167
                            short_name='S'),
 
168
                     Option('versioned', help='Only show versioned files.',
 
169
                            short_name='V')
 
170
                     ]
191
171
    aliases = ['st', 'stat']
192
172
 
193
173
    encoding_type = 'replace'
194
 
    _see_also = ['diff', 'revert']
 
174
    _see_also = ['diff', 'revert', 'status-flags']
195
175
    
196
176
    @display_command
197
177
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
198
178
            versioned=False):
199
179
        from bzrlib.status import show_tree_status
200
180
 
 
181
        if revision and len(revision) > 2:
 
182
            raise errors.BzrCommandError('bzr status --revision takes exactly'
 
183
                                         ' one or two revision specifiers')
 
184
 
201
185
        tree, file_list = tree_files(file_list)
202
186
            
203
187
        show_tree_status(tree, show_ids=show_ids,
220
204
    
221
205
    @display_command
222
206
    def run(self, revision_id=None, revision=None):
223
 
 
224
 
        revision_id = osutils.safe_revision_id(revision_id, warn=False)
225
207
        if revision_id is not None and revision is not None:
226
208
            raise errors.BzrCommandError('You can only supply one of'
227
209
                                         ' revision_id or --revision')
232
214
 
233
215
        # TODO: jam 20060112 should cat-revision always output utf-8?
234
216
        if revision_id is not None:
 
217
            revision_id = osutils.safe_revision_id(revision_id, warn=False)
235
218
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
236
219
        elif revision is not None:
237
220
            for rev in revision:
356
339
    into a subdirectory of this one.
357
340
    """
358
341
    takes_args = ['file*']
359
 
    takes_options = ['no-recurse', 'dry-run', 'verbose',
360
 
                     Option('file-ids-from', type=unicode,
361
 
                            help='Lookup file ids from here')]
 
342
    takes_options = [
 
343
        Option('no-recurse',
 
344
               help="Don't recursively add the contents of directories."),
 
345
        Option('dry-run',
 
346
               help="Show what would be done, but don't actually do anything."),
 
347
        'verbose',
 
348
        Option('file-ids-from',
 
349
               type=unicode,
 
350
               help='Lookup file ids from this tree.'),
 
351
        ]
362
352
    encoding_type = 'replace'
363
353
    _see_also = ['remove']
364
354
 
385
375
        if base_tree:
386
376
            base_tree.lock_read()
387
377
        try:
388
 
            added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
389
 
                action=action, save=not dry_run)
 
378
            file_list = self._maybe_expand_globs(file_list)
 
379
            if file_list:
 
380
                tree = WorkingTree.open_containing(file_list[0])[0]
 
381
            else:
 
382
                tree = WorkingTree.open_containing(u'.')[0]
 
383
            added, ignored = tree.smart_add(file_list, not
 
384
                no_recurse, action=action, save=not dry_run)
390
385
        finally:
391
386
            if base_tree is not None:
392
387
                base_tree.unlock()
449
444
 
450
445
    hidden = True
451
446
    _see_also = ['ls']
452
 
    takes_options = ['revision', 'show-ids', 'kind']
 
447
    takes_options = [
 
448
        'revision',
 
449
        'show-ids',
 
450
        Option('kind',
 
451
               help='List entries of a particular kind: file, directory, symlink.',
 
452
               type=unicode),
 
453
        ]
453
454
    takes_args = ['file*']
454
455
 
455
456
    @display_command
456
457
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
457
458
        if kind and kind not in ['file', 'directory', 'symlink']:
458
 
            raise errors.BzrCommandError('invalid kind specified')
 
459
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
459
460
 
460
461
        work_tree, file_list = tree_files(file_list)
461
462
        work_tree.lock_read()
501
502
class cmd_mv(Command):
502
503
    """Move or rename a file.
503
504
 
504
 
    usage:
 
505
    :Usage:
505
506
        bzr mv OLDNAME NEWNAME
 
507
 
506
508
        bzr mv SOURCE... DESTINATION
507
509
 
508
510
    If the last argument is a versioned directory, all the other names
519
521
    """
520
522
 
521
523
    takes_args = ['names*']
522
 
    takes_options = [Option("after", help="move only the bzr identifier"
523
 
        " of the file (file has already been moved). Use this flag if"
524
 
        " bzr is not able to detect this itself.")]
 
524
    takes_options = [Option("after", help="Move only the bzr identifier"
 
525
        " of the file, because the file has already been moved."),
 
526
        ]
525
527
    aliases = ['move', 'rename']
526
528
    encoding_type = 'replace'
527
529
 
566
568
    location can be accessed.
567
569
    """
568
570
 
569
 
    _see_also = ['push', 'update']
570
 
    takes_options = ['remember', 'overwrite', 'revision', 'verbose',
 
571
    _see_also = ['push', 'update', 'status-flags']
 
572
    takes_options = ['remember', 'overwrite', 'revision',
 
573
        custom_help('verbose',
 
574
            help='Show logs of pulled revisions.'),
571
575
        Option('directory',
572
 
            help='branch to pull into, '
573
 
                 'rather than the one containing the working directory',
 
576
            help='Branch to pull into, '
 
577
                 'rather than the one containing the working directory.',
574
578
            short_name='d',
575
579
            type=unicode,
576
580
            ),
581
585
    def run(self, location=None, remember=False, overwrite=False,
582
586
            revision=None, verbose=False,
583
587
            directory=None):
584
 
        from bzrlib.tag import _merge_tags_if_possible
585
588
        # FIXME: too much stuff is in the command class
586
589
        revision_id = None
587
590
        mergeable = None
594
597
            tree_to = None
595
598
            branch_to = Branch.open_containing(directory)[0]
596
599
 
597
 
        reader = None
 
600
        possible_transports = []
598
601
        if location is not None:
599
 
            try:
600
 
                mergeable = bundle.read_mergeable_from_url(
601
 
                    location)
602
 
            except errors.NotABundle:
603
 
                pass # Continue on considering this url a Branch
 
602
            mergeable, location_transport = _get_mergeable_helper(location)
 
603
            possible_transports.append(location_transport)
604
604
 
605
605
        stored_loc = branch_to.get_parent()
606
606
        if location is None:
612
612
                        self.outf.encoding)
613
613
                self.outf.write("Using saved location: %s\n" % display_url)
614
614
                location = stored_loc
 
615
                location_transport = transport.get_transport(
 
616
                    location, possible_transports=possible_transports)
615
617
 
616
618
        if mergeable is not None:
617
619
            if revision is not None:
618
620
                raise errors.BzrCommandError(
619
621
                    'Cannot use -r with merge directives or bundles')
620
 
            revision_id = mergeable.install_revisions(branch_to.repository)
 
622
            mergeable.install_revisions(branch_to.repository)
 
623
            base_revision_id, revision_id, verified = \
 
624
                mergeable.get_merge_request(branch_to.repository)
621
625
            branch_from = branch_to
622
626
        else:
623
 
            branch_from = Branch.open(location)
 
627
            branch_from = Branch.open_from_transport(location_transport)
624
628
 
625
629
            if branch_to.get_parent() is None or remember:
626
630
                branch_to.set_parent(branch_from.base)
632
636
                raise errors.BzrCommandError(
633
637
                    'bzr pull --revision takes one value.')
634
638
 
635
 
        old_rh = branch_to.revision_history()
 
639
        if verbose:
 
640
            old_rh = branch_to.revision_history()
636
641
        if tree_to is not None:
 
642
            change_reporter = delta._ChangeReporter(
 
643
                unversioned_filter=tree_to.is_ignored)
637
644
            result = tree_to.pull(branch_from, overwrite, revision_id,
638
 
                delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
 
645
                                  change_reporter,
 
646
                                  possible_transports=possible_transports)
639
647
        else:
640
648
            result = branch_to.pull(branch_from, overwrite, revision_id)
641
649
 
642
650
        result.report(self.outf)
643
651
        if verbose:
644
 
            from bzrlib.log import show_changed_revisions
645
652
            new_rh = branch_to.revision_history()
646
 
            show_changed_revisions(branch_to, old_rh, new_rh,
647
 
                                   to_file=self.outf)
 
653
            log.show_changed_revisions(branch_to, old_rh, new_rh,
 
654
                                       to_file=self.outf)
648
655
 
649
656
 
650
657
class cmd_push(Command):
677
684
    takes_options = ['remember', 'overwrite', 'verbose',
678
685
        Option('create-prefix',
679
686
               help='Create the path leading up to the branch '
680
 
                    'if it does not already exist'),
 
687
                    'if it does not already exist.'),
681
688
        Option('directory',
682
 
            help='branch to push from, '
683
 
                 'rather than the one containing the working directory',
 
689
            help='Branch to push from, '
 
690
                 'rather than the one containing the working directory.',
684
691
            short_name='d',
685
692
            type=unicode,
686
693
            ),
687
694
        Option('use-existing-dir',
688
695
               help='By default push will fail if the target'
689
696
                    ' directory exists, but does not already'
690
 
                    ' have a control directory. This flag will'
 
697
                    ' have a control directory.  This flag will'
691
698
                    ' allow push to proceed.'),
692
699
        ]
693
700
    takes_args = ['location?']
734
741
                # Found a branch, so we must have found a repository
735
742
                repository_to = br_to.repository
736
743
        push_result = None
737
 
        old_rh = []
 
744
        if verbose:
 
745
            old_rh = []
738
746
        if dir_to is None:
739
747
            # The destination doesn't exist; create it.
740
748
            # XXX: Refactor the create_prefix/no_create_prefix code into a
741
749
            #      common helper function
 
750
 
 
751
            def make_directory(transport):
 
752
                transport.mkdir('.')
 
753
                return transport
 
754
 
 
755
            def redirected(redirected_transport, e, redirection_notice):
 
756
                return transport.get_transport(e.get_target_url())
 
757
 
742
758
            try:
743
 
                to_transport.mkdir('.')
 
759
                to_transport = transport.do_catching_redirections(
 
760
                    make_directory, to_transport, redirected)
744
761
            except errors.FileExists:
745
762
                if not use_existing_dir:
746
763
                    raise errors.BzrCommandError("Target directory %s"
754
771
                        "\nYou may supply --create-prefix to create all"
755
772
                        " leading parent directories."
756
773
                        % location)
757
 
 
758
774
                _create_prefix(to_transport)
 
775
            except errors.TooManyRedirections:
 
776
                raise errors.BzrCommandError("Too many redirections trying "
 
777
                                             "to make %s." % location)
759
778
 
760
779
            # Now the target directory exists, but doesn't have a .bzr
761
780
            # directory. So we need to create it, along with any work to create
791
810
            # we don't need to successfully push because of possible divergence.
792
811
            if br_from.get_push_location() is None or remember:
793
812
                br_from.set_push_location(br_to.base)
794
 
            old_rh = br_to.revision_history()
 
813
            if verbose:
 
814
                old_rh = br_to.revision_history()
795
815
            try:
796
816
                try:
797
817
                    tree_to = dir_to.open_workingtree()
854
874
            raise errors.BzrCommandError(
855
875
                'bzr branch --revision takes exactly 1 revision value')
856
876
 
857
 
        br_from = Branch.open(from_location)
 
877
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
 
878
            from_location)
858
879
        br_from.lock_read()
859
880
        try:
860
881
            if len(revision) == 1 and revision[0] is not None:
881
902
                                             % to_location)
882
903
            try:
883
904
                # preserve whatever source format we have.
884
 
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id)
 
905
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
906
                                            possible_transports=[to_transport],
 
907
                                            accelerator_tree=accelerator_tree)
885
908
                branch = dir.open_branch()
886
909
            except errors.NoSuchRevision:
887
910
                to_transport.delete_tree('.')
920
943
    takes_args = ['branch_location?', 'to_location?']
921
944
    takes_options = ['revision',
922
945
                     Option('lightweight',
923
 
                            help="perform a lightweight checkout. Lightweight "
 
946
                            help="Perform a lightweight checkout.  Lightweight "
924
947
                                 "checkouts depend on access to the branch for "
925
 
                                 "every operation. Normal checkouts can perform "
 
948
                                 "every operation.  Normal checkouts can perform "
926
949
                                 "common operations like diff and status without "
927
950
                                 "such access, and also support local commits."
928
951
                            ),
 
952
                     Option('files-from',
 
953
                            help="Get file contents from this tree.", type=str)
929
954
                     ]
930
955
    aliases = ['co']
931
956
 
932
957
    def run(self, branch_location=None, to_location=None, revision=None,
933
 
            lightweight=False):
 
958
            lightweight=False, files_from=None):
934
959
        if revision is None:
935
960
            revision = [None]
936
961
        elif len(revision) > 1:
939
964
        if branch_location is None:
940
965
            branch_location = osutils.getcwd()
941
966
            to_location = branch_location
942
 
        source = Branch.open(branch_location)
 
967
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
 
968
            branch_location)
 
969
        if files_from is not None:
 
970
            accelerator_tree = WorkingTree.open(files_from)
943
971
        if len(revision) == 1 and revision[0] is not None:
944
 
            revision_id = revision[0].in_history(source)[1]
 
972
            revision_id = _mod_revision.ensure_null(
 
973
                revision[0].in_history(source)[1])
945
974
        else:
946
975
            revision_id = None
947
976
        if to_location is None:
954
983
            try:
955
984
                source.bzrdir.open_workingtree()
956
985
            except errors.NoWorkingTree:
957
 
                source.bzrdir.create_workingtree()
 
986
                source.bzrdir.create_workingtree(revision_id)
958
987
                return
959
 
        try:
960
 
            os.mkdir(to_location)
961
 
        except OSError, e:
962
 
            if e.errno == errno.EEXIST:
963
 
                raise errors.BzrCommandError('Target directory "%s" already'
964
 
                                             ' exists.' % to_location)
965
 
            if e.errno == errno.ENOENT:
966
 
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
967
 
                                             % to_location)
968
 
            else:
969
 
                raise
970
 
        source.create_checkout(to_location, revision_id, lightweight)
 
988
        source.create_checkout(to_location, revision_id, lightweight,
 
989
                               accelerator_tree)
971
990
 
972
991
 
973
992
class cmd_renames(Command):
1010
1029
    'bzr revert' instead of 'bzr commit' after the update.
1011
1030
    """
1012
1031
 
1013
 
    _see_also = ['pull', 'working-trees']
 
1032
    _see_also = ['pull', 'working-trees', 'status-flags']
1014
1033
    takes_args = ['dir?']
1015
1034
    aliases = ['up']
1016
1035
 
1017
1036
    def run(self, dir='.'):
1018
1037
        tree = WorkingTree.open_containing(dir)[0]
1019
 
        master = tree.branch.get_master_branch()
 
1038
        possible_transports = []
 
1039
        master = tree.branch.get_master_branch(
 
1040
            possible_transports=possible_transports)
1020
1041
        if master is not None:
1021
1042
            tree.lock_write()
1022
1043
        else:
1023
1044
            tree.lock_tree_write()
1024
1045
        try:
1025
1046
            existing_pending_merges = tree.get_parent_ids()[1:]
1026
 
            last_rev = tree.last_revision()
1027
 
            if last_rev == tree.branch.last_revision():
 
1047
            last_rev = _mod_revision.ensure_null(tree.last_revision())
 
1048
            if last_rev == _mod_revision.ensure_null(
 
1049
                tree.branch.last_revision()):
1028
1050
                # may be up to date, check master too.
1029
 
                master = tree.branch.get_master_branch()
1030
 
                if master is None or last_rev == master.last_revision():
 
1051
                if master is None or last_rev == _mod_revision.ensure_null(
 
1052
                    master.last_revision()):
1031
1053
                    revno = tree.branch.revision_id_to_revno(last_rev)
1032
1054
                    note("Tree is up to date at revision %d." % (revno,))
1033
1055
                    return 0
1034
 
            conflicts = tree.update()
1035
 
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
 
1056
            conflicts = tree.update(
 
1057
                delta._ChangeReporter(unversioned_filter=tree.is_ignored),
 
1058
                possible_transports=possible_transports)
 
1059
            revno = tree.branch.revision_id_to_revno(
 
1060
                _mod_revision.ensure_null(tree.last_revision()))
1036
1061
            note('Updated to revision %d.' % (revno,))
1037
1062
            if tree.get_parent_ids()[1:] != existing_pending_merges:
1038
1063
                note('Your local commits will now show as pending merges with '
1057
1082
    _see_also = ['revno', 'working-trees', 'repositories']
1058
1083
    takes_args = ['location?']
1059
1084
    takes_options = ['verbose']
 
1085
    encoding_type = 'replace'
1060
1086
 
1061
1087
    @display_command
1062
 
    def run(self, location=None, verbose=0):
 
1088
    def run(self, location=None, verbose=False):
 
1089
        if verbose:
 
1090
            noise_level = 2
 
1091
        else:
 
1092
            noise_level = 0
1063
1093
        from bzrlib.info import show_bzrdir_info
1064
1094
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1065
 
                         verbose=verbose)
 
1095
                         verbose=noise_level, outfile=self.outf)
1066
1096
 
1067
1097
 
1068
1098
class cmd_remove(Command):
1078
1108
    """
1079
1109
    takes_args = ['file*']
1080
1110
    takes_options = ['verbose',
1081
 
        Option('new', help='remove newly-added files'),
 
1111
        Option('new', help='Remove newly-added files.'),
1082
1112
        RegistryOption.from_kwargs('file-deletion-strategy',
1083
 
            'The file deletion mode to be used',
 
1113
            'The file deletion mode to be used.',
1084
1114
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1085
1115
            safe='Only delete files if they can be'
1086
1116
                 ' safely recovered (default).',
1095
1125
        tree, file_list = tree_files(file_list)
1096
1126
 
1097
1127
        if file_list is not None:
1098
 
            file_list = [f for f in file_list if f != '']
 
1128
            file_list = [f for f in file_list]
1099
1129
        elif not new:
1100
1130
            raise errors.BzrCommandError('Specify one or more files to'
1101
1131
            ' remove, or use --new.')
1239
1269
    If there is already a branch at the location but it has no working tree,
1240
1270
    the tree can be populated with 'bzr checkout'.
1241
1271
 
1242
 
    Recipe for importing a tree of files:
 
1272
    Recipe for importing a tree of files::
 
1273
 
1243
1274
        cd ~/project
1244
1275
        bzr init
1245
1276
        bzr add .
1246
1277
        bzr status
1247
 
        bzr commit -m 'imported project'
 
1278
        bzr commit -m "imported project"
1248
1279
    """
1249
1280
 
1250
 
    _see_also = ['init-repo', 'branch', 'checkout']
 
1281
    _see_also = ['init-repository', 'branch', 'checkout']
1251
1282
    takes_args = ['location?']
1252
1283
    takes_options = [
1253
1284
        Option('create-prefix',
1254
1285
               help='Create the path leading up to the branch '
1255
 
                    'if it does not already exist'),
 
1286
                    'if it does not already exist.'),
1256
1287
         RegistryOption('format',
1257
1288
                help='Specify a format for this branch. '
1258
1289
                'See "help formats".',
1291
1322
            _create_prefix(to_transport)
1292
1323
 
1293
1324
        try:
1294
 
            existing_bzrdir = bzrdir.BzrDir.open(location)
 
1325
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1295
1326
        except errors.NotBranchError:
1296
1327
            # really a NotBzrDir error...
1297
 
            branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1298
 
                                                             format=format)
 
1328
            create_branch = bzrdir.BzrDir.create_branch_convenience
 
1329
            branch = create_branch(to_transport.base, format=format,
 
1330
                                   possible_transports=[to_transport])
1299
1331
        else:
1300
1332
            from bzrlib.transport.local import LocalTransport
1301
1333
            if existing_bzrdir.has_branch():
1323
1355
    If the --no-trees option is used then the branches in the repository
1324
1356
    will not have working trees by default.
1325
1357
 
1326
 
    example:
1327
 
        bzr init-repo --no-trees repo
1328
 
        bzr init repo/trunk
1329
 
        bzr checkout --lightweight repo/trunk trunk-checkout
1330
 
        cd trunk-checkout
1331
 
        (add files here)
1332
 
 
1333
 
    See 'bzr help repositories' for more information.
 
1358
    :Examples:
 
1359
        Create a shared repositories holding just branches::
 
1360
 
 
1361
            bzr init-repo --no-trees repo
 
1362
            bzr init repo/trunk
 
1363
 
 
1364
        Make a lightweight checkout elsewhere::
 
1365
 
 
1366
            bzr checkout --lightweight repo/trunk trunk-checkout
 
1367
            cd trunk-checkout
 
1368
            (add files here)
1334
1369
    """
1335
1370
 
1336
 
    _see_also = ['init', 'branch', 'checkout']
 
1371
    _see_also = ['init', 'branch', 'checkout', 'repositories']
1337
1372
    takes_args = ["location"]
1338
1373
    takes_options = [RegistryOption('format',
1339
1374
                            help='Specify a format for this repository. See'
1340
 
                                 ' "bzr help formats" for details',
 
1375
                                 ' "bzr help formats" for details.',
1341
1376
                            registry=bzrdir.format_registry,
1342
1377
                            converter=bzrdir.format_registry.make_bzrdir,
1343
1378
                            value_switches=True, title='Repository format'),
1344
1379
                     Option('no-trees',
1345
1380
                             help='Branches in the repository will default to'
1346
 
                                  ' not having a working tree'),
 
1381
                                  ' not having a working tree.'),
1347
1382
                    ]
1348
1383
    aliases = ["init-repo"]
1349
1384
 
1363
1398
 
1364
1399
 
1365
1400
class cmd_diff(Command):
1366
 
    """Show differences in the working tree or between revisions.
 
1401
    """Show differences in the working tree, between revisions or branches.
1367
1402
    
1368
 
    If files are listed, only the changes in those files are listed.
1369
 
    Otherwise, all changes for the tree are listed.
 
1403
    If no arguments are given, all changes for the current tree are listed.
 
1404
    If files are given, only the changes in those files are listed.
 
1405
    Remote and multiple branches can be compared by using the --old and
 
1406
    --new options. If not provided, the default for both is derived from
 
1407
    the first argument, if any, or the current tree if no arguments are
 
1408
    given.
1370
1409
 
1371
1410
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1372
1411
    produces patches suitable for "patch -p1".
1373
1412
 
1374
 
    examples:
1375
 
        bzr diff
1376
 
            Shows the difference in the working tree versus the last commit
1377
 
        bzr diff -r1
1378
 
            Difference between the working tree and revision 1
1379
 
        bzr diff -r1..2
1380
 
            Difference between revision 2 and revision 1
1381
 
        bzr diff --prefix old/:new/
1382
 
            Same as 'bzr diff' but prefix paths with old/ and new/
1383
 
        bzr diff bzr.mine bzr.dev
1384
 
            Show the differences between the two working trees
1385
 
        bzr diff foo.c
1386
 
            Show just the differences for 'foo.c'
 
1413
    :Exit values:
 
1414
        1 - changed
 
1415
        2 - unrepresentable changes
 
1416
        3 - error
 
1417
        0 - no change
 
1418
 
 
1419
    :Examples:
 
1420
        Shows the difference in the working tree versus the last commit::
 
1421
 
 
1422
            bzr diff
 
1423
 
 
1424
        Difference between the working tree and revision 1::
 
1425
 
 
1426
            bzr diff -r1
 
1427
 
 
1428
        Difference between revision 2 and revision 1::
 
1429
 
 
1430
            bzr diff -r1..2
 
1431
 
 
1432
        Difference between revision 2 and revision 1 for branch xxx::
 
1433
 
 
1434
            bzr diff -r1..2 xxx
 
1435
 
 
1436
        Show just the differences for file NEWS::
 
1437
 
 
1438
            bzr diff NEWS
 
1439
 
 
1440
        Show the differences in working tree xxx for file NEWS::
 
1441
 
 
1442
            bzr diff xxx/NEWS
 
1443
 
 
1444
        Show the differences from branch xxx to this working tree:
 
1445
 
 
1446
            bzr diff --old xxx
 
1447
 
 
1448
        Show the differences between two branches for file NEWS::
 
1449
 
 
1450
            bzr diff --old xxx --new yyy NEWS
 
1451
 
 
1452
        Same as 'bzr diff' but prefix paths with old/ and new/::
 
1453
 
 
1454
            bzr diff --prefix old/:new/
1387
1455
    """
1388
 
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1389
 
    #       or a graphical diff.
1390
 
 
1391
 
    # TODO: Python difflib is not exactly the same as unidiff; should
1392
 
    #       either fix it up or prefer to use an external diff.
1393
 
 
1394
 
    # TODO: Selected-file diff is inefficient and doesn't show you
1395
 
    #       deleted files.
1396
 
 
1397
 
    # TODO: This probably handles non-Unix newlines poorly.
1398
 
 
1399
1456
    _see_also = ['status']
1400
1457
    takes_args = ['file*']
1401
 
    takes_options = ['revision', 'diff-options',
 
1458
    takes_options = [
 
1459
        Option('diff-options', type=str,
 
1460
               help='Pass these options to the external diff program.'),
1402
1461
        Option('prefix', type=str,
1403
1462
               short_name='p',
1404
 
               help='Set prefixes to added to old and new filenames, as '
1405
 
                    'two values separated by a colon. (eg "old/:new/")'),
 
1463
               help='Set prefixes added to old and new filenames, as '
 
1464
                    'two values separated by a colon. (eg "old/:new/").'),
 
1465
        Option('old',
 
1466
            help='Branch/tree to compare from.',
 
1467
            type=unicode,
 
1468
            ),
 
1469
        Option('new',
 
1470
            help='Branch/tree to compare to.',
 
1471
            type=unicode,
 
1472
            ),
 
1473
        'revision',
 
1474
        'change',
 
1475
        Option('using',
 
1476
            help='Use this command to compare files.',
 
1477
            type=unicode,
 
1478
            ),
1406
1479
        ]
1407
1480
    aliases = ['di', 'dif']
1408
1481
    encoding_type = 'exact'
1409
1482
 
1410
1483
    @display_command
1411
1484
    def run(self, revision=None, file_list=None, diff_options=None,
1412
 
            prefix=None):
1413
 
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
 
1485
            prefix=None, old=None, new=None, using=None):
 
1486
        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1414
1487
 
1415
1488
        if (prefix is None) or (prefix == '0'):
1416
1489
            # diff -p0 format
1430
1503
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1431
1504
                                         ' one or two revision specifiers')
1432
1505
 
1433
 
        try:
1434
 
            tree1, file_list = internal_tree_files(file_list)
1435
 
            tree2 = None
1436
 
            b = None
1437
 
            b2 = None
1438
 
        except errors.FileInWrongBranch:
1439
 
            if len(file_list) != 2:
1440
 
                raise errors.BzrCommandError("Files are in different branches")
1441
 
 
1442
 
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1443
 
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1444
 
            if file1 != "" or file2 != "":
1445
 
                # FIXME diff those two files. rbc 20051123
1446
 
                raise errors.BzrCommandError("Files are in different branches")
1447
 
            file_list = None
1448
 
        except errors.NotBranchError:
1449
 
            if (revision is not None and len(revision) == 2
1450
 
                and not revision[0].needs_branch()
1451
 
                and not revision[1].needs_branch()):
1452
 
                # If both revision specs include a branch, we can
1453
 
                # diff them without needing a local working tree
1454
 
                tree1, tree2 = None, None
1455
 
            else:
1456
 
                raise
1457
 
 
1458
 
        if tree2 is not None:
1459
 
            if revision is not None:
1460
 
                # FIXME: but there should be a clean way to diff between
1461
 
                # non-default versions of two trees, it's not hard to do
1462
 
                # internally...
1463
 
                raise errors.BzrCommandError(
1464
 
                        "Sorry, diffing arbitrary revisions across branches "
1465
 
                        "is not implemented yet")
1466
 
            return show_diff_trees(tree1, tree2, sys.stdout, 
1467
 
                                   specific_files=file_list,
1468
 
                                   external_diff_options=diff_options,
1469
 
                                   old_label=old_label, new_label=new_label)
1470
 
 
1471
 
        return diff_cmd_helper(tree1, file_list, diff_options,
1472
 
                               revision_specs=revision,
1473
 
                               old_label=old_label, new_label=new_label)
 
1506
        old_tree, new_tree, specific_files, extra_trees = \
 
1507
                _get_trees_to_diff(file_list, revision, old, new)
 
1508
        return show_diff_trees(old_tree, new_tree, sys.stdout, 
 
1509
                               specific_files=specific_files,
 
1510
                               external_diff_options=diff_options,
 
1511
                               old_label=old_label, new_label=new_label,
 
1512
                               extra_trees=extra_trees, using=using)
1474
1513
 
1475
1514
 
1476
1515
class cmd_deleted(Command):
1584
1623
    -r revision requests a specific revision, -r ..end or -r begin.. are
1585
1624
    also valid.
1586
1625
 
1587
 
    examples:
1588
 
        bzr log
1589
 
        bzr log foo.c
1590
 
        bzr log -r -10.. http://server/branch
 
1626
    :Examples:
 
1627
        Log the current branch::
 
1628
 
 
1629
            bzr log
 
1630
 
 
1631
        Log a file::
 
1632
 
 
1633
            bzr log foo.c
 
1634
 
 
1635
        Log the last 10 revisions of a branch::
 
1636
 
 
1637
            bzr log -r -10.. http://server/branch
1591
1638
    """
1592
1639
 
1593
1640
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1594
1641
 
1595
1642
    takes_args = ['location?']
1596
 
    takes_options = [Option('forward', 
1597
 
                            help='show from oldest to newest'),
1598
 
                     'timezone', 
1599
 
                     Option('verbose', 
1600
 
                             short_name='v',
1601
 
                             help='show files changed in each revision'),
1602
 
                     'show-ids', 'revision',
1603
 
                     'log-format',
1604
 
                     Option('message',
1605
 
                            short_name='m',
1606
 
                            help='show revisions whose message matches this regexp',
1607
 
                            type=str),
1608
 
                     Option('limit', 
1609
 
                            help='limit the output to the first N revisions',
1610
 
                            type=_parse_limit),
1611
 
                     ]
 
1643
    takes_options = [
 
1644
            Option('forward',
 
1645
                   help='Show from oldest to newest.'),
 
1646
            Option('timezone',
 
1647
                   type=str,
 
1648
                   help='Display timezone as local, original, or utc.'),
 
1649
            custom_help('verbose',
 
1650
                   help='Show files changed in each revision.'),
 
1651
            'show-ids',
 
1652
            'revision',
 
1653
            'log-format',
 
1654
            Option('message',
 
1655
                   short_name='m',
 
1656
                   help='Show revisions whose message matches this '
 
1657
                        'regular expression.',
 
1658
                   type=str),
 
1659
            Option('limit',
 
1660
                   short_name='l',
 
1661
                   help='Limit the output to the first N revisions.',
 
1662
                   argname='N',
 
1663
                   type=_parse_limit),
 
1664
            ]
1612
1665
    encoding_type = 'replace'
1613
1666
 
1614
1667
    @display_command
1657
1710
                rev1 = None
1658
1711
                rev2 = None
1659
1712
            elif len(revision) == 1:
1660
 
                rev1 = rev2 = revision[0].in_history(b).revno
 
1713
                rev1 = rev2 = revision[0].in_history(b)
1661
1714
            elif len(revision) == 2:
1662
1715
                if revision[1].get_branch() != revision[0].get_branch():
1663
1716
                    # b is taken from revision[0].get_branch(), and
1666
1719
                    raise errors.BzrCommandError(
1667
1720
                        "Log doesn't accept two revisions in different"
1668
1721
                        " branches.")
1669
 
                if revision[0].spec is None:
1670
 
                    # missing begin-range means first revision
1671
 
                    rev1 = 1
1672
 
                else:
1673
 
                    rev1 = revision[0].in_history(b).revno
1674
 
 
1675
 
                if revision[1].spec is None:
1676
 
                    # missing end-range means last known revision
1677
 
                    rev2 = b.revno()
1678
 
                else:
1679
 
                    rev2 = revision[1].in_history(b).revno
 
1722
                rev1 = revision[0].in_history(b)
 
1723
                rev2 = revision[1].in_history(b)
1680
1724
            else:
1681
1725
                raise errors.BzrCommandError(
1682
1726
                    'bzr log --revision takes one or two values.')
1683
1727
 
1684
 
            # By this point, the revision numbers are converted to the +ve
1685
 
            # form if they were supplied in the -ve form, so we can do
1686
 
            # this comparison in relative safety
1687
 
            if rev1 > rev2:
1688
 
                (rev2, rev1) = (rev1, rev2)
1689
 
 
1690
1728
            if log_format is None:
1691
1729
                log_format = log.log_formatter_registry.get_default(b)
1692
1730
 
1742
1780
    _see_also = ['status', 'cat']
1743
1781
    takes_args = ['path?']
1744
1782
    # TODO: Take a revision or remote path and list that tree instead.
1745
 
    takes_options = ['verbose', 'revision',
1746
 
                     Option('non-recursive',
1747
 
                            help='don\'t recurse into sub-directories'),
1748
 
                     Option('from-root',
1749
 
                            help='Print all paths from the root of the branch.'),
1750
 
                     Option('unknown', help='Print unknown files'),
1751
 
                     Option('versioned', help='Print versioned files'),
1752
 
                     Option('ignored', help='Print ignored files'),
1753
 
 
1754
 
                     Option('null', help='Null separate the files'),
1755
 
                     'kind', 'show-ids'
1756
 
                    ]
 
1783
    takes_options = [
 
1784
            'verbose',
 
1785
            'revision',
 
1786
            Option('non-recursive',
 
1787
                   help='Don\'t recurse into subdirectories.'),
 
1788
            Option('from-root',
 
1789
                   help='Print paths relative to the root of the branch.'),
 
1790
            Option('unknown', help='Print unknown files.'),
 
1791
            Option('versioned', help='Print versioned files.'),
 
1792
            Option('ignored', help='Print ignored files.'),
 
1793
            Option('null',
 
1794
                   help='Write an ascii NUL (\\0) separator '
 
1795
                   'between files rather than a newline.'),
 
1796
            Option('kind',
 
1797
                   help='List entries of a particular kind: file, directory, symlink.',
 
1798
                   type=unicode),
 
1799
            'show-ids',
 
1800
            ]
1757
1801
    @display_command
1758
 
    def run(self, revision=None, verbose=False, 
 
1802
    def run(self, revision=None, verbose=False,
1759
1803
            non_recursive=False, from_root=False,
1760
1804
            unknown=False, versioned=False, ignored=False,
1761
1805
            null=False, kind=None, show_ids=False, path=None):
1853
1897
 
1854
1898
    Ignore patterns specifying absolute paths are not allowed.
1855
1899
 
1856
 
    Ignore patterns may include globbing wildcards such as:
 
1900
    Ignore patterns may include globbing wildcards such as::
 
1901
 
1857
1902
      ? - Matches any single character except '/'
1858
1903
      * - Matches 0 or more characters except '/'
1859
1904
      /**/ - Matches 0 or more directories in a path
1867
1912
    Note: ignore patterns containing shell wildcards must be quoted from 
1868
1913
    the shell on Unix.
1869
1914
 
1870
 
    examples:
1871
 
        bzr ignore ./Makefile
1872
 
        bzr ignore '*.class'
1873
 
        bzr ignore 'lib/**/*.o'
1874
 
        bzr ignore 'RE:lib/.*\.o'
 
1915
    :Examples:
 
1916
        Ignore the top level Makefile::
 
1917
 
 
1918
            bzr ignore ./Makefile
 
1919
 
 
1920
        Ignore class files in all directories::
 
1921
 
 
1922
            bzr ignore "*.class"
 
1923
 
 
1924
        Ignore .o files under the lib directory::
 
1925
 
 
1926
            bzr ignore "lib/**/*.o"
 
1927
 
 
1928
        Ignore .o files under the lib directory::
 
1929
 
 
1930
            bzr ignore "RE:lib/.*\.o"
1875
1931
    """
1876
1932
 
1877
1933
    _see_also = ['status', 'ignored']
1878
1934
    takes_args = ['name_pattern*']
1879
1935
    takes_options = [
1880
 
                     Option('old-default-rules',
1881
 
                            help='Out the ignore rules bzr < 0.9 always used.')
1882
 
                     ]
 
1936
        Option('old-default-rules',
 
1937
               help='Write out the ignore rules bzr < 0.9 always used.')
 
1938
        ]
1883
1939
    
1884
1940
    def run(self, name_pattern_list=None, old_default_rules=None):
1885
1941
        from bzrlib.atomicfile import AtomicFile
1927
1983
        if not tree.path2id('.bzrignore'):
1928
1984
            tree.add(['.bzrignore'])
1929
1985
 
 
1986
        ignored = globbing.Globster(name_pattern_list)
 
1987
        matches = []
 
1988
        tree.lock_read()
 
1989
        for entry in tree.list_files():
 
1990
            id = entry[3]
 
1991
            if id is not None:
 
1992
                filename = entry[0]
 
1993
                if ignored.match(filename):
 
1994
                    matches.append(filename.encode('utf-8'))
 
1995
        tree.unlock()
 
1996
        if len(matches) > 0:
 
1997
            print "Warning: the following files are version controlled and" \
 
1998
                  " match your ignore pattern:\n%s" % ("\n".join(matches),)
1930
1999
 
1931
2000
class cmd_ignored(Command):
1932
2001
    """List ignored files and the patterns that matched them.
1933
2002
    """
1934
2003
 
 
2004
    encoding_type = 'replace'
1935
2005
    _see_also = ['ignore']
 
2006
 
1936
2007
    @display_command
1937
2008
    def run(self):
1938
2009
        tree = WorkingTree.open_containing(u'.')[0]
1943
2014
                    continue
1944
2015
                ## XXX: Slightly inefficient since this was already calculated
1945
2016
                pat = tree.is_ignored(path)
1946
 
                print '%-50s %s' % (path, pat)
 
2017
                self.outf.write('%-50s %s\n' % (path, pat))
1947
2018
        finally:
1948
2019
            tree.unlock()
1949
2020
 
1951
2022
class cmd_lookup_revision(Command):
1952
2023
    """Lookup the revision-id from a revision-number
1953
2024
 
1954
 
    example:
 
2025
    :Examples:
1955
2026
        bzr lookup-revision 33
1956
2027
    """
1957
2028
    hidden = True
1985
2056
 
1986
2057
    Note: Export of tree with non-ASCII filenames to zip is not supported.
1987
2058
 
1988
 
     Supported formats       Autodetected by extension
1989
 
     -----------------       -------------------------
1990
 
         dir                            -
 
2059
      =================       =========================
 
2060
      Supported formats       Autodetected by extension
 
2061
      =================       =========================
 
2062
         dir                         (none)
1991
2063
         tar                          .tar
1992
2064
         tbz2                    .tar.bz2, .tbz2
1993
2065
         tgz                      .tar.gz, .tgz
1994
2066
         zip                          .zip
 
2067
      =================       =========================
1995
2068
    """
1996
2069
    takes_args = ['dest', 'branch?']
1997
 
    takes_options = ['revision', 'format', 'root']
 
2070
    takes_options = [
 
2071
        Option('format',
 
2072
               help="Type of file to export to.",
 
2073
               type=unicode),
 
2074
        'revision',
 
2075
        Option('root',
 
2076
               type=str,
 
2077
               help="Name of the root directory inside the exported file."),
 
2078
        ]
1998
2079
    def run(self, dest, branch=None, revision=None, format=None, root=None):
1999
2080
        from bzrlib.export import export
2000
2081
 
2028
2109
    """
2029
2110
 
2030
2111
    _see_also = ['ls']
2031
 
    takes_options = ['revision', 'name-from-revision']
 
2112
    takes_options = [
 
2113
        Option('name-from-revision', help='The path name in the old tree.'),
 
2114
        'revision',
 
2115
        ]
2032
2116
    takes_args = ['filename']
2033
2117
    encoding_type = 'exact'
2034
2118
 
2036
2120
    def run(self, filename, revision=None, name_from_revision=False):
2037
2121
        if revision is not None and len(revision) != 1:
2038
2122
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2039
 
                                        " one number")
2040
 
 
2041
 
        tree = None
 
2123
                                         " one revision specifier")
 
2124
        tree, branch, relpath = \
 
2125
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
2126
        branch.lock_read()
2042
2127
        try:
2043
 
            tree, b, relpath = \
2044
 
                    bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2045
 
        except errors.NotBranchError:
2046
 
            pass
 
2128
            return self._run(tree, branch, relpath, filename, revision,
 
2129
                             name_from_revision)
 
2130
        finally:
 
2131
            branch.unlock()
2047
2132
 
2048
 
        if revision is not None and revision[0].get_branch() is not None:
2049
 
            b = Branch.open(revision[0].get_branch())
 
2133
    def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2050
2134
        if tree is None:
2051
2135
            tree = b.basis_tree()
2052
2136
        if revision is None:
2091
2175
    committed.  If a directory is specified then the directory and everything 
2092
2176
    within it is committed.
2093
2177
 
 
2178
    If author of the change is not the same person as the committer, you can
 
2179
    specify the author's name using the --author option. The name should be
 
2180
    in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
 
2181
 
2094
2182
    A selected-file commit may fail in some cases where the committed
2095
2183
    tree would be invalid. Consider::
2096
2184
 
2121
2209
 
2122
2210
    _see_also = ['bugs', 'uncommit']
2123
2211
    takes_args = ['selected*']
2124
 
    takes_options = ['message', 'verbose', 
2125
 
                     Option('unchanged',
2126
 
                            help='commit even if nothing has changed'),
2127
 
                     Option('file', type=str, 
2128
 
                            short_name='F',
2129
 
                            argname='msgfile',
2130
 
                            help='file containing commit message'),
2131
 
                     Option('strict',
2132
 
                            help="refuse to commit if there are unknown "
2133
 
                            "files in the working tree."),
2134
 
                     ListOption('fixes', type=str,
2135
 
                                help="mark a bug as being fixed by this "
2136
 
                                     "revision."),
2137
 
                     Option('local',
2138
 
                            help="perform a local only commit in a bound "
2139
 
                                 "branch. Such commits are not pushed to "
2140
 
                                 "the master branch until a normal commit "
2141
 
                                 "is performed."
2142
 
                            ),
2143
 
                     ]
 
2212
    takes_options = [
 
2213
            Option('message', type=unicode,
 
2214
                   short_name='m',
 
2215
                   help="Description of the new revision."),
 
2216
            'verbose',
 
2217
             Option('unchanged',
 
2218
                    help='Commit even if nothing has changed.'),
 
2219
             Option('file', type=str,
 
2220
                    short_name='F',
 
2221
                    argname='msgfile',
 
2222
                    help='Take commit message from this file.'),
 
2223
             Option('strict',
 
2224
                    help="Refuse to commit if there are unknown "
 
2225
                    "files in the working tree."),
 
2226
             ListOption('fixes', type=str,
 
2227
                    help="Mark a bug as being fixed by this revision."),
 
2228
             Option('author', type=unicode,
 
2229
                    help="Set the author's name, if it's different "
 
2230
                         "from the committer."),
 
2231
             Option('local',
 
2232
                    help="Perform a local commit in a bound "
 
2233
                         "branch.  Local commits are not pushed to "
 
2234
                         "the master branch until a normal commit "
 
2235
                         "is performed."
 
2236
                    ),
 
2237
              Option('show-diff',
 
2238
                     help='When no message is supplied, show the diff along'
 
2239
                     ' with the status summary in the message editor.'),
 
2240
             ]
2144
2241
    aliases = ['ci', 'checkin']
2145
2242
 
2146
2243
    def _get_bug_fix_properties(self, fixes, branch):
2165
2262
            properties.append('%s fixed' % bug_url)
2166
2263
        return '\n'.join(properties)
2167
2264
 
2168
 
    def run(self, message=None, file=None, verbose=True, selected_list=None,
2169
 
            unchanged=False, strict=False, local=False, fixes=None):
2170
 
        from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2171
 
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2172
 
                StrictCommitFailed)
2173
 
        from bzrlib.msgeditor import edit_commit_message, \
2174
 
                make_commit_message_template
 
2265
    def run(self, message=None, file=None, verbose=False, selected_list=None,
 
2266
            unchanged=False, strict=False, local=False, fixes=None,
 
2267
            author=None, show_diff=False):
 
2268
        from bzrlib.errors import (
 
2269
            PointlessCommit,
 
2270
            ConflictsInTree,
 
2271
            StrictCommitFailed
 
2272
        )
 
2273
        from bzrlib.msgeditor import (
 
2274
            edit_commit_message_encoded,
 
2275
            make_commit_message_template_encoded
 
2276
        )
2175
2277
 
2176
2278
        # TODO: Need a blackbox test for invoking the external editor; may be
2177
2279
        # slightly problematic to run this cross-platform.
2188
2290
            # selected-file merge commit is not done yet
2189
2291
            selected_list = []
2190
2292
 
 
2293
        if fixes is None:
 
2294
            fixes = []
2191
2295
        bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2192
2296
        if bug_property:
2193
2297
            properties['bugs'] = bug_property
2199
2303
            """Callback to get commit message"""
2200
2304
            my_message = message
2201
2305
            if my_message is None and not file:
2202
 
                template = make_commit_message_template(tree, selected_list)
2203
 
                my_message = edit_commit_message(template)
 
2306
                t = make_commit_message_template_encoded(tree,
 
2307
                        selected_list, diff=show_diff,
 
2308
                        output_encoding=bzrlib.user_encoding)
 
2309
                my_message = edit_commit_message_encoded(t)
2204
2310
                if my_message is None:
2205
2311
                    raise errors.BzrCommandError("please specify a commit"
2206
2312
                        " message with either --message or --file")
2214
2320
                raise errors.BzrCommandError("empty commit message specified")
2215
2321
            return my_message
2216
2322
 
2217
 
        if verbose:
2218
 
            reporter = ReportCommitToLog()
2219
 
        else:
2220
 
            reporter = NullCommitReporter()
2221
 
 
2222
2323
        try:
2223
2324
            tree.commit(message_callback=get_message,
2224
2325
                        specific_files=selected_list,
2225
2326
                        allow_pointless=unchanged, strict=strict, local=local,
2226
 
                        reporter=reporter, revprops=properties)
 
2327
                        reporter=None, verbose=verbose, revprops=properties,
 
2328
                        author=author)
2227
2329
        except PointlessCommit:
2228
2330
            # FIXME: This should really happen before the file is read in;
2229
2331
            # perhaps prepare the commit; get the message; then actually commit
2248
2350
 
2249
2351
    This command checks various invariants about the branch storage to
2250
2352
    detect data corruption or bzr bugs.
 
2353
 
 
2354
    Output fields:
 
2355
 
 
2356
        revisions: This is just the number of revisions checked.  It doesn't
 
2357
            indicate a problem.
 
2358
        versionedfiles: This is just the number of versionedfiles checked.  It
 
2359
            doesn't indicate a problem.
 
2360
        unreferenced ancestors: Texts that are ancestors of other texts, but
 
2361
            are not properly referenced by the revision ancestry.  This is a
 
2362
            subtle problem that Bazaar can work around.
 
2363
        unique file texts: This is the total number of unique file contents
 
2364
            seen in the checked revisions.  It does not indicate a problem.
 
2365
        repeated file texts: This is the total number of repeated texts seen
 
2366
            in the checked revisions.  Texts can be repeated when their file
 
2367
            entries are modified, but the file contents are not.  It does not
 
2368
            indicate a problem.
2251
2369
    """
2252
2370
 
2253
2371
    _see_also = ['reconcile']
2257
2375
    def run(self, branch=None, verbose=False):
2258
2376
        from bzrlib.check import check
2259
2377
        if branch is None:
2260
 
            tree = WorkingTree.open_containing()[0]
2261
 
            branch = tree.branch
2262
 
        else:
2263
 
            branch = Branch.open(branch)
2264
 
        check(branch, verbose)
 
2378
            branch_obj = Branch.open_containing('.')[0]
 
2379
        else:
 
2380
            branch_obj = Branch.open(branch)
 
2381
        check(branch_obj, verbose)
 
2382
        # bit hacky, check the tree parent is accurate
 
2383
        try:
 
2384
            if branch is None:
 
2385
                tree = WorkingTree.open_containing('.')[0]
 
2386
            else:
 
2387
                tree = WorkingTree.open(branch)
 
2388
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
2389
            pass
 
2390
        else:
 
2391
            # This is a primitive 'check' for tree state. Currently this is not
 
2392
            # integrated into the main check logic as yet.
 
2393
            tree.lock_read()
 
2394
            try:
 
2395
                tree_basis = tree.basis_tree()
 
2396
                tree_basis.lock_read()
 
2397
                try:
 
2398
                    repo_basis = tree.branch.repository.revision_tree(
 
2399
                        tree.last_revision())
 
2400
                    if len(list(repo_basis._iter_changes(tree_basis))):
 
2401
                        raise errors.BzrCheckError(
 
2402
                            "Mismatched basis inventory content.")
 
2403
                    tree._validate()
 
2404
                finally:
 
2405
                    tree_basis.unlock()
 
2406
            finally:
 
2407
                tree.unlock()
2265
2408
 
2266
2409
 
2267
2410
class cmd_upgrade(Command):
2277
2420
    takes_options = [
2278
2421
                    RegistryOption('format',
2279
2422
                        help='Upgrade to a specific format.  See "bzr help'
2280
 
                             ' formats" for details',
 
2423
                             ' formats" for details.',
2281
2424
                        registry=bzrdir.format_registry,
2282
2425
                        converter=bzrdir.format_registry.make_bzrdir,
2283
2426
                        value_switches=True, title='Branch format'),
2293
2436
class cmd_whoami(Command):
2294
2437
    """Show or set bzr user id.
2295
2438
    
2296
 
    examples:
2297
 
        bzr whoami --email
2298
 
        bzr whoami 'Frank Chu <fchu@example.com>'
 
2439
    :Examples:
 
2440
        Show the email of the current user::
 
2441
 
 
2442
            bzr whoami --email
 
2443
 
 
2444
        Set the current user::
 
2445
 
 
2446
            bzr whoami "Frank Chu <fchu@example.com>"
2299
2447
    """
2300
2448
    takes_options = [ Option('email',
2301
 
                             help='display email address only'),
 
2449
                             help='Display email address only.'),
2302
2450
                      Option('branch',
2303
 
                             help='set identity for the current branch instead of '
2304
 
                                  'globally'),
 
2451
                             help='Set identity for the current branch instead of '
 
2452
                                  'globally.'),
2305
2453
                    ]
2306
2454
    takes_args = ['name?']
2307
2455
    encoding_type = 'replace'
2387
2535
    modified by plugins will not be tested, and tests provided by plugins will
2388
2536
    not be run.
2389
2537
 
2390
 
    examples::
2391
 
        bzr selftest ignore
2392
 
            run only tests relating to 'ignore'
2393
 
        bzr --no-plugins selftest -v
2394
 
            disable plugins and list tests as they're run
2395
 
 
2396
 
    For each test, that needs actual disk access, bzr create their own
2397
 
    subdirectory in the temporary testing directory (testXXXX.tmp).
2398
 
    By default the name of such subdirectory is based on the name of the test.
2399
 
    If option '--numbered-dirs' is given, bzr will use sequent numbers
2400
 
    of running tests to create such subdirectories. This is default behavior
2401
 
    on Windows because of path length limitation.
 
2538
    Tests that need working space on disk use a common temporary directory, 
 
2539
    typically inside $TMPDIR or /tmp.
 
2540
 
 
2541
    :Examples:
 
2542
        Run only tests relating to 'ignore'::
 
2543
 
 
2544
            bzr selftest ignore
 
2545
 
 
2546
        Disable plugins and list tests as they're run::
 
2547
 
 
2548
            bzr --no-plugins selftest -v
2402
2549
    """
2403
2550
    # NB: this is used from the class without creating an instance, which is
2404
2551
    # why it does not have a self parameter.
2421
2568
    takes_args = ['testspecs*']
2422
2569
    takes_options = ['verbose',
2423
2570
                     Option('one',
2424
 
                             help='stop when one test fails',
 
2571
                             help='Stop when one test fails.',
2425
2572
                             short_name='1',
2426
2573
                             ),
2427
 
                     Option('keep-output',
2428
 
                            help='keep output directories when tests fail'),
2429
2574
                     Option('transport',
2430
2575
                            help='Use a different transport by default '
2431
2576
                                 'throughout the test suite.',
2432
2577
                            type=get_transport_type),
2433
 
                     Option('benchmark', help='run the bzr benchmarks.'),
 
2578
                     Option('benchmark',
 
2579
                            help='Run the benchmarks rather than selftests.'),
2434
2580
                     Option('lsprof-timed',
2435
 
                            help='generate lsprof output for benchmarked'
 
2581
                            help='Generate lsprof output for benchmarked'
2436
2582
                                 ' sections of code.'),
2437
2583
                     Option('cache-dir', type=str,
2438
 
                            help='a directory to cache intermediate'
2439
 
                                 ' benchmark steps'),
2440
 
                     Option('clean-output',
2441
 
                            help='clean temporary tests directories'
2442
 
                                 ' without running tests'),
 
2584
                            help='Cache intermediate benchmark output in this '
 
2585
                                 'directory.'),
2443
2586
                     Option('first',
2444
 
                            help='run all tests, but run specified tests first',
 
2587
                            help='Run all tests, but run specified tests first.',
2445
2588
                            short_name='f',
2446
2589
                            ),
2447
 
                     Option('numbered-dirs',
2448
 
                            help='use numbered dirs for TestCaseInTempDir'),
2449
2590
                     Option('list-only',
2450
 
                            help='list the tests instead of running them'),
 
2591
                            help='List the tests instead of running them.'),
2451
2592
                     Option('randomize', type=str, argname="SEED",
2452
 
                            help='randomize the order of tests using the given'
2453
 
                                 ' seed or "now" for the current time'),
 
2593
                            help='Randomize the order of tests using the given'
 
2594
                                 ' seed or "now" for the current time.'),
2454
2595
                     Option('exclude', type=str, argname="PATTERN",
2455
2596
                            short_name='x',
2456
 
                            help='exclude tests that match this regular'
2457
 
                                 ' expression'),
 
2597
                            help='Exclude tests that match this regular'
 
2598
                                 ' expression.'),
 
2599
                     Option('strict', help='Fail on missing dependencies or '
 
2600
                            'known failures.'),
 
2601
                     Option('coverage', type=str, argname="DIRECTORY",
 
2602
                            help='Generate line coverage report in this '
 
2603
                                 'directory.'),
2458
2604
                     ]
2459
2605
    encoding_type = 'replace'
2460
2606
 
2461
 
    def run(self, testspecs_list=None, verbose=None, one=False,
2462
 
            keep_output=False, transport=None, benchmark=None,
2463
 
            lsprof_timed=None, cache_dir=None, clean_output=False,
2464
 
            first=False, numbered_dirs=None, list_only=False,
2465
 
            randomize=None, exclude=None):
 
2607
    def run(self, testspecs_list=None, verbose=False, one=False,
 
2608
            transport=None, benchmark=None,
 
2609
            lsprof_timed=None, cache_dir=None,
 
2610
            first=False, list_only=False,
 
2611
            randomize=None, exclude=None, strict=False, coverage=None):
2466
2612
        import bzrlib.ui
2467
2613
        from bzrlib.tests import selftest
2468
2614
        import bzrlib.benchmarks as benchmarks
2469
2615
        from bzrlib.benchmarks import tree_creator
2470
2616
 
2471
 
        if clean_output:
2472
 
            from bzrlib.tests import clean_selftest_output
2473
 
            clean_selftest_output()
2474
 
            return 0
2475
 
        if keep_output:
2476
 
            trace.warning("notice: selftest --keep-output "
2477
 
                          "is no longer supported; "
2478
 
                          "test output is always removed")
2479
 
 
2480
 
        if numbered_dirs is None and sys.platform == 'win32':
2481
 
            numbered_dirs = True
2482
 
 
2483
2617
        if cache_dir is not None:
2484
2618
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2485
 
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2486
 
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
 
2619
        if not list_only:
 
2620
            print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
 
2621
            print '   %s (%s python%s)' % (
 
2622
                    bzrlib.__path__[0],
 
2623
                    bzrlib.version_string,
 
2624
                    '.'.join(map(str, sys.version_info)),
 
2625
                    )
2487
2626
        print
2488
2627
        if testspecs_list is not None:
2489
2628
            pattern = '|'.join(testspecs_list)
2491
2630
            pattern = ".*"
2492
2631
        if benchmark:
2493
2632
            test_suite_factory = benchmarks.test_suite
2494
 
            if verbose is None:
2495
 
                verbose = True
 
2633
            # Unless user explicitly asks for quiet, be verbose in benchmarks
 
2634
            verbose = not is_quiet()
2496
2635
            # TODO: should possibly lock the history file...
2497
2636
            benchfile = open(".perf_history", "at", buffering=1)
2498
2637
        else:
2499
2638
            test_suite_factory = None
2500
 
            if verbose is None:
2501
 
                verbose = False
2502
2639
            benchfile = None
2503
2640
        try:
2504
 
            result = selftest(verbose=verbose, 
 
2641
            result = selftest(verbose=verbose,
2505
2642
                              pattern=pattern,
2506
 
                              stop_on_failure=one, 
 
2643
                              stop_on_failure=one,
2507
2644
                              transport=transport,
2508
2645
                              test_suite_factory=test_suite_factory,
2509
2646
                              lsprof_timed=lsprof_timed,
2510
2647
                              bench_history=benchfile,
2511
2648
                              matching_tests_first=first,
2512
 
                              numbered_dirs=numbered_dirs,
2513
2649
                              list_only=list_only,
2514
2650
                              random_seed=randomize,
2515
 
                              exclude_pattern=exclude
 
2651
                              exclude_pattern=exclude,
 
2652
                              strict=strict,
 
2653
                              coverage_dir=coverage,
2516
2654
                              )
2517
2655
        finally:
2518
2656
            if benchfile is not None:
2527
2665
class cmd_version(Command):
2528
2666
    """Show version of bzr."""
2529
2667
 
 
2668
    encoding_type = 'replace'
 
2669
 
2530
2670
    @display_command
2531
2671
    def run(self):
2532
2672
        from bzrlib.version import show_version
2533
 
        show_version()
 
2673
        show_version(to_file=self.outf)
2534
2674
 
2535
2675
 
2536
2676
class cmd_rocks(Command):
2552
2692
    
2553
2693
    @display_command
2554
2694
    def run(self, branch, other):
2555
 
        from bzrlib.revision import MultipleRevisionSources
 
2695
        from bzrlib.revision import ensure_null
2556
2696
        
2557
2697
        branch1 = Branch.open_containing(branch)[0]
2558
2698
        branch2 = Branch.open_containing(other)[0]
2559
 
 
2560
 
        last1 = branch1.last_revision()
2561
 
        last2 = branch2.last_revision()
2562
 
 
2563
 
        source = MultipleRevisionSources(branch1.repository, 
2564
 
                                         branch2.repository)
2565
 
        
2566
 
        base_rev_id = common_ancestor(last1, last2, source)
2567
 
 
2568
 
        print 'merge base is revision %s' % base_rev_id
 
2699
        branch1.lock_read()
 
2700
        try:
 
2701
            branch2.lock_read()
 
2702
            try:
 
2703
                last1 = ensure_null(branch1.last_revision())
 
2704
                last2 = ensure_null(branch2.last_revision())
 
2705
 
 
2706
                graph = branch1.repository.get_graph(branch2.repository)
 
2707
                base_rev_id = graph.find_unique_lca(last1, last2)
 
2708
 
 
2709
                print 'merge base is revision %s' % base_rev_id
 
2710
            finally:
 
2711
                branch2.unlock()
 
2712
        finally:
 
2713
            branch1.unlock()
2569
2714
 
2570
2715
 
2571
2716
class cmd_merge(Command):
2596
2741
    The results of the merge are placed into the destination working
2597
2742
    directory, where they can be reviewed (with bzr diff), tested, and then
2598
2743
    committed to record the result of the merge.
2599
 
 
2600
 
    Examples:
2601
 
 
2602
 
    To merge the latest revision from bzr.dev:
2603
 
        bzr merge ../bzr.dev
2604
 
 
2605
 
    To merge changes up to and including revision 82 from bzr.dev:
2606
 
        bzr merge -r 82 ../bzr.dev
2607
 
 
2608
 
    To merge the changes introduced by 82, without previous changes:
2609
 
        bzr merge -r 81..82 ../bzr.dev
2610
2744
    
2611
2745
    merge refuses to run if there are any uncommitted changes, unless
2612
2746
    --force is given.
 
2747
 
 
2748
    :Examples:
 
2749
        To merge the latest revision from bzr.dev::
 
2750
 
 
2751
            bzr merge ../bzr.dev
 
2752
 
 
2753
        To merge changes up to and including revision 82 from bzr.dev::
 
2754
 
 
2755
            bzr merge -r 82 ../bzr.dev
 
2756
 
 
2757
        To merge the changes introduced by 82, without previous changes::
 
2758
 
 
2759
            bzr merge -r 81..82 ../bzr.dev
2613
2760
    """
2614
2761
 
2615
 
    _see_also = ['update', 'remerge']
 
2762
    _see_also = ['update', 'remerge', 'status-flags']
2616
2763
    takes_args = ['branch?']
2617
 
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
 
2764
    takes_options = [
 
2765
        'change',
 
2766
        'revision',
 
2767
        Option('force',
 
2768
               help='Merge even if the destination tree has uncommitted changes.'),
 
2769
        'merge-type',
 
2770
        'reprocess',
 
2771
        'remember',
2618
2772
        Option('show-base', help="Show base revision text in "
2619
 
               "conflicts"),
 
2773
               "conflicts."),
2620
2774
        Option('uncommitted', help='Apply uncommitted changes'
2621
 
               ' from a working copy, instead of branch changes'),
 
2775
               ' from a working copy, instead of branch changes.'),
2622
2776
        Option('pull', help='If the destination is already'
2623
2777
                ' completely merged into the source, pull from the'
2624
 
                ' source rather than merging. When this happens,'
 
2778
                ' source rather than merging.  When this happens,'
2625
2779
                ' you do not need to commit the result.'),
2626
2780
        Option('directory',
2627
 
            help='Branch to merge into, '
2628
 
                 'rather than the one containing the working directory',
2629
 
            short_name='d',
2630
 
            type=unicode,
2631
 
            ),
 
2781
               help='Branch to merge into, '
 
2782
                    'rather than the one containing the working directory.',
 
2783
               short_name='d',
 
2784
               type=unicode,
 
2785
               ),
2632
2786
    ]
2633
2787
 
2634
2788
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2636
2790
            uncommitted=False, pull=False,
2637
2791
            directory=None,
2638
2792
            ):
2639
 
        from bzrlib.tag import _merge_tags_if_possible
2640
 
        other_revision_id = None
 
2793
        # This is actually a branch (or merge-directive) *location*.
 
2794
        location = branch
 
2795
        del branch
 
2796
 
2641
2797
        if merge_type is None:
2642
2798
            merge_type = _mod_merge.Merge3Merger
2643
2799
 
2644
2800
        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?)
 
2801
        possible_transports = []
 
2802
        merger = None
 
2803
        allow_pending = True
 
2804
        verified = 'inapplicable'
2652
2805
        tree = WorkingTree.open_containing(directory)[0]
2653
2806
        change_reporter = delta._ChangeReporter(
2654
2807
            unversioned_filter=tree.is_ignored)
2655
 
 
2656
 
        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:
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)]
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]
2679
 
            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)
2696
 
                    revno = revision[0].in_history(other_branch).revno
2697
 
                    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
 
 
 
2808
        cleanups = []
 
2809
        try:
 
2810
            pb = ui.ui_factory.nested_progress_bar()
 
2811
            cleanups.append(pb.finished)
 
2812
            tree.lock_write()
 
2813
            cleanups.append(tree.unlock)
 
2814
            if location is not None:
 
2815
                mergeable, other_transport = _get_mergeable_helper(location)
 
2816
                if mergeable:
 
2817
                    if uncommitted:
 
2818
                        raise errors.BzrCommandError('Cannot use --uncommitted'
 
2819
                            ' with bundles or merge directives.')
 
2820
 
 
2821
                    if revision is not None:
 
2822
                        raise errors.BzrCommandError(
 
2823
                            'Cannot use -r with merge directives or bundles')
 
2824
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
 
2825
                       mergeable, pb)
 
2826
                possible_transports.append(other_transport)
 
2827
 
 
2828
            if merger is None and uncommitted:
 
2829
                if revision is not None and len(revision) > 0:
 
2830
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2831
                        ' --revision at the same time.')
 
2832
                location = self._select_branch_location(tree, location)[0]
 
2833
                other_tree, other_path = WorkingTree.open_containing(location)
 
2834
                merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
 
2835
                    pb)
 
2836
                allow_pending = False
 
2837
                if other_path != '':
 
2838
                    merger.interesting_files = [other_path]
 
2839
 
 
2840
            if merger is None:
 
2841
                merger, allow_pending = self._get_merger_from_branch(tree,
 
2842
                    location, revision, remember, possible_transports, pb)
 
2843
 
 
2844
            merger.merge_type = merge_type
 
2845
            merger.reprocess = reprocess
 
2846
            merger.show_base = show_base
 
2847
            merger.change_reporter = change_reporter
 
2848
            self.sanity_check_merger(merger)
 
2849
            if (merger.base_rev_id == merger.other_rev_id and
 
2850
                merger.other_rev_id != None):
 
2851
                note('Nothing to do.')
 
2852
                return 0
 
2853
            if pull:
 
2854
                if merger.interesting_files is not None:
 
2855
                    raise errors.BzrCommandError('Cannot pull individual files')
 
2856
                if (merger.base_rev_id == tree.last_revision()):
 
2857
                    result = tree.pull(merger.other_branch, False,
 
2858
                                       merger.other_rev_id)
 
2859
                    result.report(self.outf)
 
2860
                    return 0
 
2861
            merger.check_basis(not force)
 
2862
            conflict_count = merger.do_merge()
 
2863
            if allow_pending:
 
2864
                merger.set_pending()
 
2865
            if verified == 'failed':
 
2866
                warning('Preview patch does not match changes')
 
2867
            if conflict_count != 0:
 
2868
                return 1
 
2869
            else:
 
2870
                return 0
 
2871
        finally:
 
2872
            for cleanup in reversed(cleanups):
 
2873
                cleanup()
 
2874
 
 
2875
    def sanity_check_merger(self, merger):
 
2876
        if (merger.show_base and
 
2877
            not merger.merge_type is _mod_merge.Merge3Merger):
 
2878
            raise errors.BzrCommandError("Show-base is not supported for this"
 
2879
                                         " merge type. %s" % merger.merge_type)
 
2880
        if merger.reprocess and not merger.merge_type.supports_reprocess:
 
2881
            raise errors.BzrCommandError("Conflict reduction is not supported"
 
2882
                                         " for merge type %s." %
 
2883
                                         merger.merge_type)
 
2884
        if merger.reprocess and merger.show_base:
 
2885
            raise errors.BzrCommandError("Cannot do conflict reduction and"
 
2886
                                         " show base.")
 
2887
 
 
2888
    def _get_merger_from_branch(self, tree, location, revision, remember,
 
2889
                                possible_transports, pb):
 
2890
        """Produce a merger from a location, assuming it refers to a branch."""
 
2891
        from bzrlib.tag import _merge_tags_if_possible
 
2892
        assert revision is None or len(revision) < 3
 
2893
        # find the branch locations
 
2894
        other_loc, location = self._select_branch_location(tree, location,
 
2895
            revision, -1)
 
2896
        if revision is not None and len(revision) == 2:
 
2897
            base_loc, location = self._select_branch_location(tree, location,
 
2898
                                                              revision, 0)
 
2899
        else:
 
2900
            base_loc = other_loc
 
2901
        # Open the branches
 
2902
        other_branch, other_path = Branch.open_containing(other_loc,
 
2903
            possible_transports)
 
2904
        if base_loc == other_loc:
 
2905
            base_branch = other_branch
 
2906
        else:
 
2907
            base_branch, base_path = Branch.open_containing(base_loc,
 
2908
                possible_transports)
 
2909
        # Find the revision ids
 
2910
        if revision is None or len(revision) < 1 or revision[-1] is None:
 
2911
            other_revision_id = _mod_revision.ensure_null(
 
2912
                other_branch.last_revision())
 
2913
        else:
 
2914
            other_revision_id = \
 
2915
                _mod_revision.ensure_null(
 
2916
                    revision[-1].in_history(other_branch).rev_id)
 
2917
        if (revision is not None and len(revision) == 2
 
2918
            and revision[0] is not None):
 
2919
            base_revision_id = \
 
2920
                _mod_revision.ensure_null(
 
2921
                    revision[0].in_history(base_branch).rev_id)
 
2922
        else:
 
2923
            base_revision_id = None
 
2924
        # Remember where we merge from
2713
2925
        if ((tree.branch.get_parent() is None or remember) and
2714
2926
            other_branch is not None):
2715
2927
            tree.branch.set_parent(other_branch.base)
2716
 
 
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)
2721
 
 
2722
 
        if path != "":
2723
 
            interesting_files = [path]
 
2928
        _merge_tags_if_possible(other_branch, tree.branch)
 
2929
        merger = _mod_merge.Merger.from_revision_ids(pb, tree,
 
2930
            other_revision_id, base_revision_id, other_branch, base_branch)
 
2931
        if other_path != '':
 
2932
            allow_pending = False
 
2933
            merger.interesting_files = [other_path]
2724
2934
        else:
2725
 
            interesting_files = None
2726
 
        pb = ui.ui_factory.nested_progress_bar()
2727
 
        try:
2728
 
            try:
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,
2735
 
                    pull=pull,
2736
 
                    this_dir=directory,
2737
 
                    pb=pb, file_list=interesting_files,
2738
 
                    change_reporter=change_reporter)
2739
 
            finally:
2740
 
                pb.finished()
2741
 
            if conflict_count != 0:
2742
 
                return 1
2743
 
            else:
2744
 
                return 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)
2749
 
                 + "\n"
2750
 
                 "please specify an explicit base with -r,\n"
2751
 
                 "and (if you want) report this to the bzr developers\n")
2752
 
            log_error(m)
 
2935
            allow_pending = True
 
2936
        return merger, allow_pending
 
2937
 
 
2938
    def _select_branch_location(self, tree, location, revision=None,
 
2939
                                index=None):
 
2940
        """Select a branch location, according to possible inputs.
 
2941
 
 
2942
        If provided, branches from ``revision`` are preferred.  (Both
 
2943
        ``revision`` and ``index`` must be supplied.)
 
2944
 
 
2945
        Otherwise, the ``location`` parameter is used.  If it is None, then the
 
2946
        ``parent`` location is used, and a note is printed.
 
2947
 
 
2948
        :param tree: The working tree to select a branch for merging into
 
2949
        :param location: The location entered by the user
 
2950
        :param revision: The revision parameter to the command
 
2951
        :param index: The index to use for the revision parameter.  Negative
 
2952
            indices are permitted.
 
2953
        :return: (selected_location, default_location).  The default location
 
2954
            will be the user-entered location, if any, or else the remembered
 
2955
            location.
 
2956
        """
 
2957
        if (revision is not None and index is not None
 
2958
            and revision[index] is not None):
 
2959
            branch = revision[index].get_branch()
 
2960
            if branch is not None:
 
2961
                return branch, location
 
2962
        location = self._get_remembered_parent(tree, location, 'Merging from')
 
2963
        return location, location
2753
2964
 
2754
2965
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2755
2966
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2763
2974
        mutter("%s", stored_location)
2764
2975
        if stored_location is None:
2765
2976
            raise errors.BzrCommandError("No location specified or remembered")
2766
 
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2767
 
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
 
2977
        display_url = urlutils.unescape_for_display(stored_location,
 
2978
            self.outf.encoding)
 
2979
        self.outf.write("%s remembered location %s\n" % (verb_string,
 
2980
            display_url))
2768
2981
        return stored_location
2769
2982
 
2770
2983
 
2779
2992
    merge.  The difference is that remerge can (only) be run when there is a
2780
2993
    pending merge, and it lets you specify particular files.
2781
2994
 
2782
 
    Examples:
2783
 
 
2784
 
    $ bzr remerge --show-base
 
2995
    :Examples:
2785
2996
        Re-do the merge of all conflicted files, and show the base text in
2786
 
        conflict regions, in addition to the usual THIS and OTHER texts.
 
2997
        conflict regions, in addition to the usual THIS and OTHER texts::
 
2998
      
 
2999
            bzr remerge --show-base
2787
3000
 
2788
 
    $ bzr remerge --merge-type weave --reprocess foobar
2789
3001
        Re-do the merge of "foobar", using the weave merge algorithm, with
2790
 
        additional processing to reduce the size of conflict regions.
 
3002
        additional processing to reduce the size of conflict regions::
 
3003
      
 
3004
            bzr remerge --merge-type weave --reprocess foobar
2791
3005
    """
2792
3006
    takes_args = ['file*']
2793
 
    takes_options = ['merge-type', 'reprocess',
2794
 
                     Option('show-base', help="Show base revision text in "
2795
 
                            "conflicts")]
 
3007
    takes_options = [
 
3008
            'merge-type',
 
3009
            'reprocess',
 
3010
            Option('show-base',
 
3011
                   help="Show base revision text in conflicts."),
 
3012
            ]
2796
3013
 
2797
3014
    def run(self, file_list=None, merge_type=None, show_base=False,
2798
3015
            reprocess=False):
2807
3024
                                             " merges.  Not cherrypicking or"
2808
3025
                                             " multi-merges.")
2809
3026
            repository = tree.branch.repository
2810
 
            base_revision = common_ancestor(parents[0],
2811
 
                                            parents[1], repository)
2812
 
            base_tree = repository.revision_tree(base_revision)
2813
 
            other_tree = repository.revision_tree(parents[1])
2814
3027
            interesting_ids = None
2815
3028
            new_conflicts = []
2816
3029
            conflicts = tree.conflicts()
2841
3054
                    restore(tree.abspath(filename))
2842
3055
                except errors.NotConflicted:
2843
3056
                    pass
2844
 
            conflicts = _mod_merge.merge_inner(
2845
 
                                      tree.branch, other_tree, base_tree,
2846
 
                                      this_tree=tree,
2847
 
                                      interesting_ids=interesting_ids,
2848
 
                                      other_rev_id=parents[1],
2849
 
                                      merge_type=merge_type,
2850
 
                                      show_base=show_base,
2851
 
                                      reprocess=reprocess)
 
3057
            # Disable pending merges, because the file texts we are remerging
 
3058
            # have not had those merges performed.  If we use the wrong parents
 
3059
            # list, we imply that the working tree text has seen and rejected
 
3060
            # all the changes from the other tree, when in fact those changes
 
3061
            # have not yet been seen.
 
3062
            pb = ui.ui_factory.nested_progress_bar()
 
3063
            tree.set_parent_ids(parents[:1])
 
3064
            try:
 
3065
                merger = _mod_merge.Merger.from_revision_ids(pb,
 
3066
                                                             tree, parents[1])
 
3067
                merger.interesting_ids = interesting_ids
 
3068
                merger.merge_type = merge_type
 
3069
                merger.show_base = show_base
 
3070
                merger.reprocess = reprocess
 
3071
                conflicts = merger.do_merge()
 
3072
            finally:
 
3073
                tree.set_parent_ids(parents)
 
3074
                pb.finished()
2852
3075
        finally:
2853
3076
            tree.unlock()
2854
3077
        if conflicts > 0:
2865
3088
    last committed revision is used.
2866
3089
 
2867
3090
    To remove only some changes, without reverting to a prior version, use
2868
 
    merge instead.  For example, "merge . --r-2..-3" will remove the changes
2869
 
    introduced by -2, without affecting the changes introduced by -1.  Or
2870
 
    to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
 
3091
    merge instead.  For example, "merge . --revision -2..-3" will remove the
 
3092
    changes introduced by -2, without affecting the changes introduced by -1.
 
3093
    Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2871
3094
    
2872
3095
    By default, any files that have been manually changed will be backed up
2873
3096
    first.  (Files changed only by merge are not backed up.)  Backup files have
2877
3100
    from the target revision.  So you can use revert to "undelete" a file by
2878
3101
    name.  If you name a directory, all the contents of that directory will be
2879
3102
    reverted.
 
3103
 
 
3104
    Any files that have been newly added since that revision will be deleted,
 
3105
    with a backup kept if appropriate.  Directories containing unknown files
 
3106
    will not be deleted.
 
3107
 
 
3108
    The working tree contains a list of pending merged revisions, which will
 
3109
    be included as parents in the next commit.  Normally, revert clears that
 
3110
    list as well as reverting the files.  If any files are specified, revert
 
3111
    leaves the pending merge list alone and reverts only the files.  Use "bzr
 
3112
    revert ." in the tree root to revert all files but keep the merge record,
 
3113
    and "bzr revert --forget-merges" to clear the pending merge list without
 
3114
    reverting any files.
2880
3115
    """
2881
3116
 
2882
3117
    _see_also = ['cat', 'export']
2883
 
    takes_options = ['revision', 'no-backup']
 
3118
    takes_options = [
 
3119
        'revision',
 
3120
        Option('no-backup', "Do not save backups of reverted files."),
 
3121
        Option('forget-merges',
 
3122
               'Remove pending merge marker, without changing any files.'),
 
3123
        ]
2884
3124
    takes_args = ['file*']
2885
3125
 
2886
 
    def run(self, revision=None, no_backup=False, file_list=None):
2887
 
        if file_list is not None:
2888
 
            if len(file_list) == 0:
2889
 
                raise errors.BzrCommandError("No files specified")
 
3126
    def run(self, revision=None, no_backup=False, file_list=None,
 
3127
            forget_merges=None):
 
3128
        tree, file_list = tree_files(file_list)
 
3129
        if forget_merges:
 
3130
            tree.set_parent_ids(tree.get_parent_ids()[:1])
2890
3131
        else:
2891
 
            file_list = []
2892
 
        
2893
 
        tree, file_list = tree_files(file_list)
 
3132
            self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
3133
 
 
3134
    @staticmethod
 
3135
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
2894
3136
        if revision is None:
2895
 
            # FIXME should be tree.last_revision
2896
3137
            rev_id = tree.last_revision()
2897
3138
        elif len(revision) != 1:
2898
3139
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2900
3141
            rev_id = revision[0].in_history(tree.branch).rev_id
2901
3142
        pb = ui.ui_factory.nested_progress_bar()
2902
3143
        try:
2903
 
            tree.revert(file_list, 
 
3144
            tree.revert(file_list,
2904
3145
                        tree.branch.repository.revision_tree(rev_id),
2905
3146
                        not no_backup, pb, report_changes=True)
2906
3147
        finally:
2922
3163
    """
2923
3164
 
2924
3165
    _see_also = ['topics']
2925
 
    takes_options = [Option('long', 'show help on all commands')]
 
3166
    takes_options = [
 
3167
            Option('long', 'Show help on all commands.'),
 
3168
            ]
2926
3169
    takes_args = ['topic?']
2927
3170
    aliases = ['?', '--help', '-?', '-h']
2928
3171
    
2971
3214
 
2972
3215
    _see_also = ['merge', 'pull']
2973
3216
    takes_args = ['other_branch?']
2974
 
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
2975
 
                     Option('mine-only', 
2976
 
                            'Display changes in the local branch only'),
2977
 
                     Option('this' , 'same as --mine-only'),
2978
 
                     Option('theirs-only', 
2979
 
                            'Display changes in the remote branch only'),
2980
 
                     Option('other', 'same as --theirs-only'),
2981
 
                     'log-format',
2982
 
                     'show-ids',
2983
 
                     'verbose'
2984
 
                     ]
 
3217
    takes_options = [
 
3218
            Option('reverse', 'Reverse the order of revisions.'),
 
3219
            Option('mine-only',
 
3220
                   'Display changes in the local branch only.'),
 
3221
            Option('this' , 'Same as --mine-only.'),
 
3222
            Option('theirs-only',
 
3223
                   'Display changes in the remote branch only.'),
 
3224
            Option('other', 'Same as --theirs-only.'),
 
3225
            'log-format',
 
3226
            'show-ids',
 
3227
            'verbose'
 
3228
            ]
2985
3229
    encoding_type = 'replace'
2986
3230
 
2987
3231
    @display_command
2989
3233
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
2990
3234
            show_ids=False, verbose=False, this=False, other=False):
2991
3235
        from bzrlib.missing import find_unmerged, iter_log_revisions
2992
 
        from bzrlib.log import log_formatter
2993
3236
 
2994
3237
        if this:
2995
3238
          mine_only = this
3001
3244
        if other_branch is None:
3002
3245
            other_branch = parent
3003
3246
            if other_branch is None:
3004
 
                raise errors.BzrCommandError("No peer location known or specified.")
 
3247
                raise errors.BzrCommandError("No peer location known"
 
3248
                                             " or specified.")
3005
3249
            display_url = urlutils.unescape_for_display(parent,
3006
3250
                                                        self.outf.encoding)
3007
 
            print "Using last location: " + display_url
 
3251
            self.outf.write("Using last location: " + display_url + "\n")
3008
3252
 
3009
3253
        remote_branch = Branch.open(other_branch)
3010
3254
        if remote_branch.base == local_branch.base:
3013
3257
        try:
3014
3258
            remote_branch.lock_read()
3015
3259
            try:
3016
 
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
3017
 
                if (log_format is None):
3018
 
                    log_format = log.log_formatter_registry.get_default(
3019
 
                        local_branch)
 
3260
                local_extra, remote_extra = find_unmerged(local_branch,
 
3261
                                                          remote_branch)
 
3262
                if log_format is None:
 
3263
                    registry = log.log_formatter_registry
 
3264
                    log_format = registry.get_default(local_branch)
3020
3265
                lf = log_format(to_file=self.outf,
3021
3266
                                show_ids=show_ids,
3022
3267
                                show_timezone='original')
3024
3269
                    local_extra.reverse()
3025
3270
                    remote_extra.reverse()
3026
3271
                if local_extra and not theirs_only:
3027
 
                    print "You have %d extra revision(s):" % len(local_extra)
3028
 
                    for revision in iter_log_revisions(local_extra, 
 
3272
                    self.outf.write("You have %d extra revision(s):\n" %
 
3273
                                    len(local_extra))
 
3274
                    for revision in iter_log_revisions(local_extra,
3029
3275
                                        local_branch.repository,
3030
3276
                                        verbose):
3031
3277
                        lf.log_revision(revision)
3034
3280
                    printed_local = False
3035
3281
                if remote_extra and not mine_only:
3036
3282
                    if printed_local is True:
3037
 
                        print "\n\n"
3038
 
                    print "You are missing %d revision(s):" % len(remote_extra)
3039
 
                    for revision in iter_log_revisions(remote_extra, 
3040
 
                                        remote_branch.repository, 
 
3283
                        self.outf.write("\n\n\n")
 
3284
                    self.outf.write("You are missing %d revision(s):\n" %
 
3285
                                    len(remote_extra))
 
3286
                    for revision in iter_log_revisions(remote_extra,
 
3287
                                        remote_branch.repository,
3041
3288
                                        verbose):
3042
3289
                        lf.log_revision(revision)
3043
3290
                if not remote_extra and not local_extra:
3044
3291
                    status_code = 0
3045
 
                    print "Branches are up to date."
 
3292
                    self.outf.write("Branches are up to date.\n")
3046
3293
                else:
3047
3294
                    status_code = 1
3048
3295
            finally:
3060
3307
        return status_code
3061
3308
 
3062
3309
 
 
3310
class cmd_pack(Command):
 
3311
    """Compress the data within a repository."""
 
3312
 
 
3313
    _see_also = ['repositories']
 
3314
    takes_args = ['branch_or_repo?']
 
3315
 
 
3316
    def run(self, branch_or_repo='.'):
 
3317
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
 
3318
        try:
 
3319
            branch = dir.open_branch()
 
3320
            repository = branch.repository
 
3321
        except errors.NotBranchError:
 
3322
            repository = dir.open_repository()
 
3323
        repository.pack()
 
3324
 
 
3325
 
3063
3326
class cmd_plugins(Command):
3064
 
    """List plugins"""
3065
 
    hidden = True
 
3327
    """List the installed plugins.
 
3328
    
 
3329
    This command displays the list of installed plugins including the
 
3330
    path where each one is located and a short description of each.
 
3331
 
 
3332
    A plugin is an external component for Bazaar that extends the
 
3333
    revision control system, by adding or replacing code in Bazaar.
 
3334
    Plugins can do a variety of things, including overriding commands,
 
3335
    adding new commands, providing additional network transports and
 
3336
    customizing log output.
 
3337
 
 
3338
    See the Bazaar web site, http://bazaar-vcs.org, for further
 
3339
    information on plugins including where to find them and how to
 
3340
    install them. Instructions are also provided there on how to
 
3341
    write new plugins using the Python programming language.
 
3342
    """
 
3343
 
3066
3344
    @display_command
3067
3345
    def run(self):
3068
3346
        import bzrlib.plugin
3069
3347
        from inspect import getdoc
3070
 
        for name, plugin in bzrlib.plugin.all_plugins().items():
3071
 
            if getattr(plugin, '__path__', None) is not None:
3072
 
                print plugin.__path__[0]
3073
 
            elif getattr(plugin, '__file__', None) is not None:
3074
 
                print plugin.__file__
3075
 
            else:
3076
 
                print repr(plugin)
3077
 
                
3078
 
            d = getdoc(plugin)
 
3348
        for name, plugin in bzrlib.plugin.plugins().items():
 
3349
            print plugin.path(), "[%s]" % plugin.__version__
 
3350
            d = getdoc(plugin.module)
3079
3351
            if d:
3080
3352
                print '\t', d.split('\n')[0]
3081
3353
 
3082
3354
 
3083
3355
class cmd_testament(Command):
3084
3356
    """Show testament (signing-form) of a revision."""
3085
 
    takes_options = ['revision',
3086
 
                     Option('long', help='Produce long-format testament'), 
3087
 
                     Option('strict', help='Produce a strict-format'
3088
 
                            ' testament')]
 
3357
    takes_options = [
 
3358
            'revision',
 
3359
            Option('long', help='Produce long-format testament.'),
 
3360
            Option('strict',
 
3361
                   help='Produce a strict-format testament.')]
3089
3362
    takes_args = ['branch?']
3090
3363
    @display_command
3091
3364
    def run(self, branch=u'.', revision=None, long=False, strict=False):
3124
3397
    #       with new uncommitted lines marked
3125
3398
    aliases = ['ann', 'blame', 'praise']
3126
3399
    takes_args = ['filename']
3127
 
    takes_options = [Option('all', help='show annotations on all lines'),
3128
 
                     Option('long', help='show date in annotations'),
 
3400
    takes_options = [Option('all', help='Show annotations on all lines.'),
 
3401
                     Option('long', help='Show commit date in annotations.'),
3129
3402
                     'revision',
3130
3403
                     'show-ids',
3131
3404
                     ]
 
3405
    encoding_type = 'exact'
3132
3406
 
3133
3407
    @display_command
3134
3408
    def run(self, filename, all=False, long=False, revision=None,
3145
3419
            else:
3146
3420
                revision_id = revision[0].in_history(branch).rev_id
3147
3421
            file_id = tree.path2id(relpath)
 
3422
            if file_id is None:
 
3423
                raise errors.NotVersionedError(filename)
3148
3424
            tree = branch.repository.revision_tree(revision_id)
3149
3425
            file_version = tree.inventory[file_id].revision
3150
 
            annotate_file(branch, file_version, file_id, long, all, sys.stdout,
 
3426
            annotate_file(branch, file_version, file_id, long, all, self.outf,
3151
3427
                          show_ids=show_ids)
3152
3428
        finally:
3153
3429
            branch.unlock()
3162
3438
    takes_options = ['revision']
3163
3439
    
3164
3440
    def run(self, revision_id_list=None, revision=None):
3165
 
        import bzrlib.gpg as gpg
3166
3441
        if revision_id_list is not None and revision is not None:
3167
3442
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3168
3443
        if revision_id_list is None and revision is None:
3169
3444
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3170
3445
        b = WorkingTree.open_containing(u'.')[0].branch
 
3446
        b.lock_write()
 
3447
        try:
 
3448
            return self._run(b, revision_id_list, revision)
 
3449
        finally:
 
3450
            b.unlock()
 
3451
 
 
3452
    def _run(self, b, revision_id_list, revision):
 
3453
        import bzrlib.gpg as gpg
3171
3454
        gpg_strategy = gpg.GPGStrategy(b.get_config())
3172
3455
        if revision_id_list is not None:
3173
 
            for revision_id in revision_id_list:
3174
 
                b.repository.sign_revision(revision_id, gpg_strategy)
 
3456
            b.repository.start_write_group()
 
3457
            try:
 
3458
                for revision_id in revision_id_list:
 
3459
                    b.repository.sign_revision(revision_id, gpg_strategy)
 
3460
            except:
 
3461
                b.repository.abort_write_group()
 
3462
                raise
 
3463
            else:
 
3464
                b.repository.commit_write_group()
3175
3465
        elif revision is not None:
3176
3466
            if len(revision) == 1:
3177
3467
                revno, rev_id = revision[0].in_history(b)
3178
 
                b.repository.sign_revision(rev_id, gpg_strategy)
 
3468
                b.repository.start_write_group()
 
3469
                try:
 
3470
                    b.repository.sign_revision(rev_id, gpg_strategy)
 
3471
                except:
 
3472
                    b.repository.abort_write_group()
 
3473
                    raise
 
3474
                else:
 
3475
                    b.repository.commit_write_group()
3179
3476
            elif len(revision) == 2:
3180
3477
                # are they both on rh- if so we can walk between them
3181
3478
                # might be nice to have a range helper for arbitrary
3186
3483
                    to_revno = b.revno()
3187
3484
                if from_revno is None or to_revno is None:
3188
3485
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3189
 
                for revno in range(from_revno, to_revno + 1):
3190
 
                    b.repository.sign_revision(b.get_rev_id(revno), 
3191
 
                                               gpg_strategy)
 
3486
                b.repository.start_write_group()
 
3487
                try:
 
3488
                    for revno in range(from_revno, to_revno + 1):
 
3489
                        b.repository.sign_revision(b.get_rev_id(revno),
 
3490
                                                   gpg_strategy)
 
3491
                except:
 
3492
                    b.repository.abort_write_group()
 
3493
                    raise
 
3494
                else:
 
3495
                    b.repository.commit_write_group()
3192
3496
            else:
3193
3497
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
3194
3498
 
3247
3551
    --verbose will print out what is being removed.
3248
3552
    --dry-run will go through all the motions, but not actually
3249
3553
    remove anything.
3250
 
    
 
3554
 
 
3555
    If --revision is specified, uncommit revisions to leave the branch at the
 
3556
    specified revision.  For example, "bzr uncommit -r 15" will leave the
 
3557
    branch at revision 15.
 
3558
 
3251
3559
    In the future, uncommit will create a revision bundle, which can then
3252
3560
    be re-applied.
3253
3561
    """
3258
3566
    # information in shared branches as well.
3259
3567
    _see_also = ['commit']
3260
3568
    takes_options = ['verbose', 'revision',
3261
 
                    Option('dry-run', help='Don\'t actually make changes'),
 
3569
                    Option('dry-run', help='Don\'t actually make changes.'),
3262
3570
                    Option('force', help='Say yes to all questions.')]
3263
3571
    takes_args = ['location?']
3264
3572
    aliases = []
 
3573
    encoding_type = 'replace'
3265
3574
 
3266
3575
    def run(self, location=None,
3267
3576
            dry_run=False, verbose=False,
3268
3577
            revision=None, force=False):
3269
 
        from bzrlib.log import log_formatter, show_log
3270
 
        import sys
3271
 
        from bzrlib.uncommit import uncommit
3272
 
 
3273
3578
        if location is None:
3274
3579
            location = u'.'
3275
3580
        control, relpath = bzrdir.BzrDir.open_containing(location)
3280
3585
            tree = None
3281
3586
            b = control.open_branch()
3282
3587
 
 
3588
        if tree is not None:
 
3589
            tree.lock_write()
 
3590
        else:
 
3591
            b.lock_write()
 
3592
        try:
 
3593
            return self._run(b, tree, dry_run, verbose, revision, force)
 
3594
        finally:
 
3595
            if tree is not None:
 
3596
                tree.unlock()
 
3597
            else:
 
3598
                b.unlock()
 
3599
 
 
3600
    def _run(self, b, tree, dry_run, verbose, revision, force):
 
3601
        from bzrlib.log import log_formatter, show_log
 
3602
        from bzrlib.uncommit import uncommit
 
3603
 
 
3604
        last_revno, last_rev_id = b.last_revision_info()
 
3605
 
3283
3606
        rev_id = None
3284
3607
        if revision is None:
3285
 
            revno = b.revno()
 
3608
            revno = last_revno
 
3609
            rev_id = last_rev_id
3286
3610
        else:
3287
3611
            # 'bzr uncommit -r 10' actually means uncommit
3288
3612
            # so that the final tree is at revno 10.
3289
3613
            # but bzrlib.uncommit.uncommit() actually uncommits
3290
3614
            # the revisions that are supplied.
3291
3615
            # So we need to offset it by one
3292
 
            revno = revision[0].in_history(b).revno+1
 
3616
            revno = revision[0].in_history(b).revno + 1
 
3617
            if revno <= last_revno:
 
3618
                rev_id = b.get_rev_id(revno)
3293
3619
 
3294
 
        if revno <= b.revno():
3295
 
            rev_id = b.get_rev_id(revno)
3296
 
        if rev_id is None:
 
3620
        if rev_id is None or _mod_revision.is_null(rev_id):
3297
3621
            self.outf.write('No revisions to uncommit.\n')
3298
3622
            return 1
3299
3623
 
3306
3630
                 verbose=False,
3307
3631
                 direction='forward',
3308
3632
                 start_revision=revno,
3309
 
                 end_revision=b.revno())
 
3633
                 end_revision=last_revno)
3310
3634
 
3311
3635
        if dry_run:
3312
3636
            print 'Dry-run, pretending to remove the above revisions.'
3321
3645
                    return 0
3322
3646
 
3323
3647
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3324
 
                revno=revno)
 
3648
                 revno=revno)
3325
3649
 
3326
3650
 
3327
3651
class cmd_break_lock(Command):
3332
3656
 
3333
3657
    You can get information on what locks are open via the 'bzr info' command.
3334
3658
    
3335
 
    example:
 
3659
    :Examples:
3336
3660
        bzr break-lock
3337
3661
    """
3338
3662
    takes_args = ['location?']
3368
3692
 
3369
3693
    takes_options = [
3370
3694
        Option('inet',
3371
 
               help='serve on stdin/out for use from inetd or sshd'),
 
3695
               help='Serve on stdin/out for use from inetd or sshd.'),
3372
3696
        Option('port',
3373
 
               help='listen for connections on nominated port of the form '
3374
 
                    '[hostname:]portnumber. Passing 0 as the port number will '
3375
 
                    'result in a dynamically allocated port. Default port is '
 
3697
               help='Listen for connections on nominated port of the form '
 
3698
                    '[hostname:]portnumber.  Passing 0 as the port number will '
 
3699
                    'result in a dynamically allocated port.  The default port is '
3376
3700
                    '4155.',
3377
3701
               type=str),
3378
3702
        Option('directory',
3379
 
               help='serve contents of directory',
 
3703
               help='Serve contents of this directory.',
3380
3704
               type=unicode),
3381
3705
        Option('allow-writes',
3382
 
               help='By default the server is a readonly server. Supplying '
 
3706
               help='By default the server is a readonly server.  Supplying '
3383
3707
                    '--allow-writes enables write access to the contents of '
3384
 
                    'the served directory and below. '
 
3708
                    'the served directory and below.'
3385
3709
                ),
3386
3710
        ]
3387
3711
 
3388
3712
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
3713
        from bzrlib import lockdir
3389
3714
        from bzrlib.smart import medium, server
3390
3715
        from bzrlib.transport import get_transport
3391
3716
        from bzrlib.transport.chroot import ChrootServer
3392
 
        from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3393
3717
        if directory is None:
3394
3718
            directory = os.getcwd()
3395
3719
        url = urlutils.local_path_to_url(directory)
3402
3726
            smart_server = medium.SmartServerPipeStreamMedium(
3403
3727
                sys.stdin, sys.stdout, t)
3404
3728
        else:
3405
 
            host = BZR_DEFAULT_INTERFACE
 
3729
            host = medium.BZR_DEFAULT_INTERFACE
3406
3730
            if port is None:
3407
 
                port = BZR_DEFAULT_PORT
 
3731
                port = medium.BZR_DEFAULT_PORT
3408
3732
            else:
3409
3733
                if ':' in port:
3410
3734
                    host, port = port.split(':')
3417
3741
        # be changed with care though, as we dont want to use bandwidth sending
3418
3742
        # progress over stderr to smart server clients!
3419
3743
        old_factory = ui.ui_factory
 
3744
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3420
3745
        try:
3421
3746
            ui.ui_factory = ui.SilentUIFactory()
 
3747
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3422
3748
            smart_server.serve()
3423
3749
        finally:
3424
3750
            ui.ui_factory = old_factory
 
3751
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
3425
3752
 
3426
3753
 
3427
3754
class cmd_join(Command):
3447
3774
 
3448
3775
    _see_also = ['split']
3449
3776
    takes_args = ['tree']
3450
 
    takes_options = [Option('reference', 'join by reference')]
 
3777
    takes_options = [
 
3778
            Option('reference', help='Join by reference.'),
 
3779
            ]
3451
3780
    hidden = True
3452
3781
 
3453
3782
    def run(self, tree, reference=False):
3477
3806
 
3478
3807
 
3479
3808
class cmd_split(Command):
3480
 
    """Split a tree into two trees.
 
3809
    """Split a subdirectory of a tree into a separate tree.
3481
3810
 
3482
 
    This command is for experimental use only.  It requires the target tree
3483
 
    to be in dirstate-with-subtree format, which cannot be converted into
3484
 
    earlier formats.
 
3811
    This command will produce a target tree in a format that supports
 
3812
    rich roots, like 'rich-root' or 'rich-root-pack'.  These formats cannot be
 
3813
    converted into earlier formats like 'dirstate-tags'.
3485
3814
 
3486
3815
    The TREE argument should be a subdirectory of a working tree.  That
3487
3816
    subdirectory will be converted into an independent tree, with its own
3488
3817
    branch.  Commits in the top-level tree will not apply to the new subtree.
3489
 
    If you want that behavior, do "bzr join --reference TREE".
3490
3818
    """
3491
3819
 
3492
 
    _see_also = ['join']
 
3820
    # join is not un-hidden yet
 
3821
    #_see_also = ['join']
3493
3822
    takes_args = ['tree']
3494
3823
 
3495
 
    hidden = True
3496
 
 
3497
3824
    def run(self, tree):
3498
3825
        containing_tree, subdir = WorkingTree.open_containing(tree)
3499
3826
        sub_id = containing_tree.path2id(subdir)
3505
3832
            raise errors.UpgradeRequired(containing_tree.branch.base)
3506
3833
 
3507
3834
 
3508
 
 
3509
3835
class cmd_merge_directive(Command):
3510
3836
    """Generate a merge directive for auto-merge tools.
3511
3837
 
3525
3851
 
3526
3852
    takes_args = ['submit_branch?', 'public_branch?']
3527
3853
 
 
3854
    hidden = True
 
3855
 
 
3856
    _see_also = ['send']
 
3857
 
3528
3858
    takes_options = [
3529
3859
        RegistryOption.from_kwargs('patch-type',
3530
 
            'The type of patch to include in the directive',
3531
 
            title='Patch type', value_switches=True, enum_switch=False,
3532
 
            bundle='Bazaar revision bundle (default)',
3533
 
            diff='Normal unified diff',
3534
 
            plain='No patch, just directive'),
3535
 
        Option('sign', help='GPG-sign the directive'), 'revision',
 
3860
            'The type of patch to include in the directive.',
 
3861
            title='Patch type',
 
3862
            value_switches=True,
 
3863
            enum_switch=False,
 
3864
            bundle='Bazaar revision bundle (default).',
 
3865
            diff='Normal unified diff.',
 
3866
            plain='No patch, just directive.'),
 
3867
        Option('sign', help='GPG-sign the directive.'), 'revision',
3536
3868
        Option('mail-to', type=str,
3537
 
            help='Instead of printing the directive, email to this address'),
 
3869
            help='Instead of printing the directive, email to this address.'),
3538
3870
        Option('message', type=str, short_name='m',
3539
 
            help='Message to use when committing this merge')
 
3871
            help='Message to use when committing this merge.')
3540
3872
        ]
3541
3873
 
 
3874
    encoding_type = 'exact'
 
3875
 
3542
3876
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3543
3877
            sign=False, revision=None, mail_to=None, message=None):
3544
 
        if patch_type == 'plain':
3545
 
            patch_type = None
 
3878
        from bzrlib.revision import ensure_null, NULL_REVISION
 
3879
        include_patch, include_bundle = {
 
3880
            'plain': (False, False),
 
3881
            'diff': (True, False),
 
3882
            'bundle': (True, True),
 
3883
            }[patch_type]
3546
3884
        branch = Branch.open('.')
3547
3885
        stored_submit_branch = branch.get_submit_branch()
3548
3886
        if submit_branch is None:
3560
3898
            public_branch = stored_public_branch
3561
3899
        elif stored_public_branch is None:
3562
3900
            branch.set_public_branch(public_branch)
3563
 
        if patch_type != "bundle" and public_branch is None:
 
3901
        if not include_bundle and public_branch is None:
3564
3902
            raise errors.BzrCommandError('No public branch specified or'
3565
3903
                                         ' known')
 
3904
        base_revision_id = None
3566
3905
        if revision is not None:
3567
 
            if len(revision) != 1:
 
3906
            if len(revision) > 2:
3568
3907
                raise errors.BzrCommandError('bzr merge-directive takes '
3569
 
                    'exactly one revision identifier')
3570
 
            else:
3571
 
                revision_id = revision[0].in_history(branch).rev_id
 
3908
                    'at most two one revision identifiers')
 
3909
            revision_id = revision[-1].in_history(branch).rev_id
 
3910
            if len(revision) == 2:
 
3911
                base_revision_id = revision[0].in_history(branch).rev_id
 
3912
                base_revision_id = ensure_null(base_revision_id)
3572
3913
        else:
3573
3914
            revision_id = branch.last_revision()
3574
 
        directive = merge_directive.MergeDirective.from_objects(
 
3915
        revision_id = ensure_null(revision_id)
 
3916
        if revision_id == NULL_REVISION:
 
3917
            raise errors.BzrCommandError('No revisions to bundle.')
 
3918
        directive = merge_directive.MergeDirective2.from_objects(
3575
3919
            branch.repository, revision_id, time.time(),
3576
3920
            osutils.local_time_offset(), submit_branch,
3577
 
            public_branch=public_branch, patch_type=patch_type,
3578
 
            message=message)
 
3921
            public_branch=public_branch, include_patch=include_patch,
 
3922
            include_bundle=include_bundle, message=message,
 
3923
            base_revision_id=base_revision_id)
3579
3924
        if mail_to is None:
3580
3925
            if sign:
3581
3926
                self.outf.write(directive.to_signed(branch))
3583
3928
                self.outf.writelines(directive.to_lines())
3584
3929
        else:
3585
3930
            message = directive.to_email(mail_to, branch, sign)
3586
 
            s = smtplib.SMTP()
3587
 
            server = branch.get_config().get_user_option('smtp_server')
3588
 
            if not server:
3589
 
                server = 'localhost'
3590
 
            s.connect(server)
3591
 
            s.sendmail(message['From'], message['To'], message.as_string())
 
3931
            s = SMTPConnection(branch.get_config())
 
3932
            s.send_email(message)
 
3933
 
 
3934
 
 
3935
class cmd_send(Command):
 
3936
    """Mail or create a merge-directive for submiting changes.
 
3937
 
 
3938
    A merge directive provides many things needed for requesting merges:
 
3939
 
 
3940
    * A machine-readable description of the merge to perform
 
3941
 
 
3942
    * An optional patch that is a preview of the changes requested
 
3943
 
 
3944
    * An optional bundle of revision data, so that the changes can be applied
 
3945
      directly from the merge directive, without retrieving data from a
 
3946
      branch.
 
3947
 
 
3948
    If --no-bundle is specified, then public_branch is needed (and must be
 
3949
    up-to-date), so that the receiver can perform the merge using the
 
3950
    public_branch.  The public_branch is always included if known, so that
 
3951
    people can check it later.
 
3952
 
 
3953
    The submit branch defaults to the parent, but can be overridden.  Both
 
3954
    submit branch and public branch will be remembered if supplied.
 
3955
 
 
3956
    If a public_branch is known for the submit_branch, that public submit
 
3957
    branch is used in the merge instructions.  This means that a local mirror
 
3958
    can be used as your actual submit branch, once you have set public_branch
 
3959
    for that mirror.
 
3960
 
 
3961
    Mail is sent using your preferred mail program.  This should be transparent
 
3962
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
 
3963
    If the preferred client can't be found (or used), your editor will be used.
 
3964
    
 
3965
    To use a specific mail program, set the mail_client configuration option.
 
3966
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
 
3967
    specific clients are "evolution", "kmail", "mutt", and "thunderbird";
 
3968
    generic options are "default", "editor", "mapi", and "xdg-email".
 
3969
 
 
3970
    If mail is being sent, a to address is required.  This can be supplied
 
3971
    either on the commandline, or by setting the submit_to configuration
 
3972
    option.
 
3973
 
 
3974
    Two formats are currently supported: "4" uses revision bundle format 4 and
 
3975
    merge directive format 2.  It is significantly faster and smaller than
 
3976
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
 
3977
    default.  "0.9" uses revision bundle format 0.9 and merge directive
 
3978
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
 
3979
    """
 
3980
 
 
3981
    encoding_type = 'exact'
 
3982
 
 
3983
    _see_also = ['merge']
 
3984
 
 
3985
    takes_args = ['submit_branch?', 'public_branch?']
 
3986
 
 
3987
    takes_options = [
 
3988
        Option('no-bundle',
 
3989
               help='Do not include a bundle in the merge directive.'),
 
3990
        Option('no-patch', help='Do not include a preview patch in the merge'
 
3991
               ' directive.'),
 
3992
        Option('remember',
 
3993
               help='Remember submit and public branch.'),
 
3994
        Option('from',
 
3995
               help='Branch to generate the submission from, '
 
3996
               'rather than the one containing the working directory.',
 
3997
               short_name='f',
 
3998
               type=unicode),
 
3999
        Option('output', short_name='o', help='Write directive to this file.',
 
4000
               type=unicode),
 
4001
        Option('mail-to', help='Mail the request to this address.',
 
4002
               type=unicode),
 
4003
        'revision',
 
4004
        'message',
 
4005
        RegistryOption.from_kwargs('format',
 
4006
        'Use the specified output format.',
 
4007
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
 
4008
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
 
4009
        ]
 
4010
 
 
4011
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
 
4012
            no_patch=False, revision=None, remember=False, output=None,
 
4013
            format='4', mail_to=None, message=None, **kwargs):
 
4014
        return self._run(submit_branch, revision, public_branch, remember,
 
4015
                         format, no_bundle, no_patch, output,
 
4016
                         kwargs.get('from', '.'), mail_to, message)
 
4017
 
 
4018
    def _run(self, submit_branch, revision, public_branch, remember, format,
 
4019
             no_bundle, no_patch, output, from_, mail_to, message):
 
4020
        from bzrlib.revision import NULL_REVISION
 
4021
        branch = Branch.open_containing(from_)[0]
 
4022
        if output is None:
 
4023
            outfile = StringIO()
 
4024
        elif output == '-':
 
4025
            outfile = self.outf
 
4026
        else:
 
4027
            outfile = open(output, 'wb')
 
4028
        # we may need to write data into branch's repository to calculate
 
4029
        # the data to send.
 
4030
        branch.lock_write()
 
4031
        try:
 
4032
            if output is None:
 
4033
                config = branch.get_config()
 
4034
                if mail_to is None:
 
4035
                    mail_to = config.get_user_option('submit_to')
 
4036
                mail_client = config.get_mail_client()
 
4037
            if remember and submit_branch is None:
 
4038
                raise errors.BzrCommandError(
 
4039
                    '--remember requires a branch to be specified.')
 
4040
            stored_submit_branch = branch.get_submit_branch()
 
4041
            remembered_submit_branch = False
 
4042
            if submit_branch is None:
 
4043
                submit_branch = stored_submit_branch
 
4044
                remembered_submit_branch = True
 
4045
            else:
 
4046
                if stored_submit_branch is None or remember:
 
4047
                    branch.set_submit_branch(submit_branch)
 
4048
            if submit_branch is None:
 
4049
                submit_branch = branch.get_parent()
 
4050
                remembered_submit_branch = True
 
4051
            if submit_branch is None:
 
4052
                raise errors.BzrCommandError('No submit branch known or'
 
4053
                                             ' specified')
 
4054
            if remembered_submit_branch:
 
4055
                note('Using saved location: %s', submit_branch)
 
4056
 
 
4057
            stored_public_branch = branch.get_public_branch()
 
4058
            if public_branch is None:
 
4059
                public_branch = stored_public_branch
 
4060
            elif stored_public_branch is None or remember:
 
4061
                branch.set_public_branch(public_branch)
 
4062
            if no_bundle and public_branch is None:
 
4063
                raise errors.BzrCommandError('No public branch specified or'
 
4064
                                             ' known')
 
4065
            base_revision_id = None
 
4066
            revision_id = None
 
4067
            if revision is not None:
 
4068
                if len(revision) > 2:
 
4069
                    raise errors.BzrCommandError('bzr send takes '
 
4070
                        'at most two one revision identifiers')
 
4071
                revision_id = revision[-1].in_history(branch).rev_id
 
4072
                if len(revision) == 2:
 
4073
                    base_revision_id = revision[0].in_history(branch).rev_id
 
4074
            if revision_id is None:
 
4075
                revision_id = branch.last_revision()
 
4076
            if revision_id == NULL_REVISION:
 
4077
                raise errors.BzrCommandError('No revisions to submit.')
 
4078
            if format == '4':
 
4079
                directive = merge_directive.MergeDirective2.from_objects(
 
4080
                    branch.repository, revision_id, time.time(),
 
4081
                    osutils.local_time_offset(), submit_branch,
 
4082
                    public_branch=public_branch, include_patch=not no_patch,
 
4083
                    include_bundle=not no_bundle, message=message,
 
4084
                    base_revision_id=base_revision_id)
 
4085
            elif format == '0.9':
 
4086
                if not no_bundle:
 
4087
                    if not no_patch:
 
4088
                        patch_type = 'bundle'
 
4089
                    else:
 
4090
                        raise errors.BzrCommandError('Format 0.9 does not'
 
4091
                            ' permit bundle with no patch')
 
4092
                else:
 
4093
                    if not no_patch:
 
4094
                        patch_type = 'diff'
 
4095
                    else:
 
4096
                        patch_type = None
 
4097
                directive = merge_directive.MergeDirective.from_objects(
 
4098
                    branch.repository, revision_id, time.time(),
 
4099
                    osutils.local_time_offset(), submit_branch,
 
4100
                    public_branch=public_branch, patch_type=patch_type,
 
4101
                    message=message)
 
4102
 
 
4103
            outfile.writelines(directive.to_lines())
 
4104
            if output is None:
 
4105
                subject = '[MERGE] '
 
4106
                if message is not None:
 
4107
                    subject += message
 
4108
                else:
 
4109
                    revision = branch.repository.get_revision(revision_id)
 
4110
                    subject += revision.get_summary()
 
4111
                mail_client.compose_merge_request(mail_to, subject,
 
4112
                                                  outfile.getvalue())
 
4113
        finally:
 
4114
            if output != '-':
 
4115
                outfile.close()
 
4116
            branch.unlock()
 
4117
 
 
4118
 
 
4119
class cmd_bundle_revisions(cmd_send):
 
4120
 
 
4121
    """Create a merge-directive for submiting changes.
 
4122
 
 
4123
    A merge directive provides many things needed for requesting merges:
 
4124
 
 
4125
    * A machine-readable description of the merge to perform
 
4126
 
 
4127
    * An optional patch that is a preview of the changes requested
 
4128
 
 
4129
    * An optional bundle of revision data, so that the changes can be applied
 
4130
      directly from the merge directive, without retrieving data from a
 
4131
      branch.
 
4132
 
 
4133
    If --no-bundle is specified, then public_branch is needed (and must be
 
4134
    up-to-date), so that the receiver can perform the merge using the
 
4135
    public_branch.  The public_branch is always included if known, so that
 
4136
    people can check it later.
 
4137
 
 
4138
    The submit branch defaults to the parent, but can be overridden.  Both
 
4139
    submit branch and public branch will be remembered if supplied.
 
4140
 
 
4141
    If a public_branch is known for the submit_branch, that public submit
 
4142
    branch is used in the merge instructions.  This means that a local mirror
 
4143
    can be used as your actual submit branch, once you have set public_branch
 
4144
    for that mirror.
 
4145
 
 
4146
    Two formats are currently supported: "4" uses revision bundle format 4 and
 
4147
    merge directive format 2.  It is significantly faster and smaller than
 
4148
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
 
4149
    default.  "0.9" uses revision bundle format 0.9 and merge directive
 
4150
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
 
4151
    """
 
4152
 
 
4153
    takes_options = [
 
4154
        Option('no-bundle',
 
4155
               help='Do not include a bundle in the merge directive.'),
 
4156
        Option('no-patch', help='Do not include a preview patch in the merge'
 
4157
               ' directive.'),
 
4158
        Option('remember',
 
4159
               help='Remember submit and public branch.'),
 
4160
        Option('from',
 
4161
               help='Branch to generate the submission from, '
 
4162
               'rather than the one containing the working directory.',
 
4163
               short_name='f',
 
4164
               type=unicode),
 
4165
        Option('output', short_name='o', help='Write directive to this file.',
 
4166
               type=unicode),
 
4167
        'revision',
 
4168
        RegistryOption.from_kwargs('format',
 
4169
        'Use the specified output format.',
 
4170
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
 
4171
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
 
4172
        ]
 
4173
    aliases = ['bundle']
 
4174
 
 
4175
    _see_also = ['send', 'merge']
 
4176
 
 
4177
    hidden = True
 
4178
 
 
4179
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
 
4180
            no_patch=False, revision=None, remember=False, output=None,
 
4181
            format='4', **kwargs):
 
4182
        if output is None:
 
4183
            output = '-'
 
4184
        return self._run(submit_branch, revision, public_branch, remember,
 
4185
                         format, no_bundle, no_patch, output,
 
4186
                         kwargs.get('from', '.'), None, None)
3592
4187
 
3593
4188
 
3594
4189
class cmd_tag(Command):
3595
 
    """Create a tag naming a revision.
 
4190
    """Create, remove or modify a tag naming a revision.
3596
4191
    
3597
4192
    Tags give human-meaningful names to revisions.  Commands that take a -r
3598
4193
    (--revision) option can be given -rtag:X, where X is any previously
3617
4212
            type=unicode,
3618
4213
            ),
3619
4214
        Option('force',
3620
 
            help='Replace existing tags',
 
4215
            help='Replace existing tags.',
3621
4216
            ),
3622
4217
        'revision',
3623
4218
        ]
3654
4249
class cmd_tags(Command):
3655
4250
    """List tags.
3656
4251
 
3657
 
    This tag shows a table of tag names and the revisions they reference.
 
4252
    This command shows a table of tag names and the revisions they reference.
3658
4253
    """
3659
4254
 
3660
4255
    _see_also = ['tag']
3661
4256
    takes_options = [
3662
4257
        Option('directory',
3663
 
            help='Branch whose tags should be displayed',
 
4258
            help='Branch whose tags should be displayed.',
3664
4259
            short_name='d',
3665
4260
            type=unicode,
3666
4261
            ),
 
4262
        RegistryOption.from_kwargs('sort',
 
4263
            'Sort tags by different criteria.', title='Sorting',
 
4264
            alpha='Sort tags lexicographically (default).',
 
4265
            time='Sort tags chronologically.',
 
4266
            ),
 
4267
        'show-ids',
3667
4268
    ]
3668
4269
 
3669
4270
    @display_command
3670
4271
    def run(self,
3671
4272
            directory='.',
 
4273
            sort='alpha',
 
4274
            show_ids=False,
3672
4275
            ):
3673
4276
        branch, relpath = Branch.open_containing(directory)
3674
 
        for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3675
 
            self.outf.write('%-20s %s\n' % (tag_name, target))
3676
 
 
3677
 
 
3678
 
# command-line interpretation helper for merge-related commands
3679
 
def _merge_helper(other_revision, base_revision,
3680
 
                  check_clean=True, ignore_zero=False,
3681
 
                  this_dir=None, backup_files=False,
3682
 
                  merge_type=None,
3683
 
                  file_list=None, show_base=False, reprocess=False,
3684
 
                  pull=False,
3685
 
                  pb=DummyProgress(),
3686
 
                  change_reporter=None,
3687
 
                  other_rev_id=None):
3688
 
    """Merge changes into a tree.
3689
 
 
3690
 
    base_revision
3691
 
        list(path, revno) Base for three-way merge.  
3692
 
        If [None, None] then a base will be automatically determined.
3693
 
    other_revision
3694
 
        list(path, revno) Other revision for three-way merge.
3695
 
    this_dir
3696
 
        Directory to merge changes into; '.' by default.
3697
 
    check_clean
3698
 
        If true, this_dir must have no uncommitted changes before the
3699
 
        merge begins.
3700
 
    ignore_zero - If true, suppress the "zero conflicts" message when 
3701
 
        there are no conflicts; should be set when doing something we expect
3702
 
        to complete perfectly.
3703
 
    file_list - If supplied, merge only changes to selected files.
3704
 
 
3705
 
    All available ancestors of other_revision and base_revision are
3706
 
    automatically pulled into the branch.
3707
 
 
3708
 
    The revno may be -1 to indicate the last revision on the branch, which is
3709
 
    the typical case.
3710
 
 
3711
 
    This function is intended for use from the command line; programmatic
3712
 
    clients might prefer to call merge.merge_inner(), which has less magic 
3713
 
    behavior.
3714
 
    """
3715
 
    # Loading it late, so that we don't always have to import bzrlib.merge
3716
 
    if merge_type is None:
3717
 
        merge_type = _mod_merge.Merge3Merger
3718
 
    if this_dir is None:
3719
 
        this_dir = u'.'
3720
 
    this_tree = WorkingTree.open_containing(this_dir)[0]
3721
 
    if show_base and not merge_type is _mod_merge.Merge3Merger:
3722
 
        raise errors.BzrCommandError("Show-base is not supported for this merge"
3723
 
                                     " type. %s" % merge_type)
3724
 
    if reprocess and not merge_type.supports_reprocess:
3725
 
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3726
 
                                     " type %s." % merge_type)
3727
 
    if reprocess and show_base:
3728
 
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3729
 
    # TODO: jam 20070226 We should really lock these trees earlier. However, we
3730
 
    #       only want to take out a lock_tree_write() if we don't have to pull
3731
 
    #       any ancestry. But merge might fetch ancestry in the middle, in
3732
 
    #       which case we would need a lock_write().
3733
 
    #       Because we cannot upgrade locks, for now we live with the fact that
3734
 
    #       the tree will be locked multiple times during a merge. (Maybe
3735
 
    #       read-only some of the time, but it means things will get read
3736
 
    #       multiple times.)
3737
 
    try:
3738
 
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3739
 
                                   pb=pb, change_reporter=change_reporter)
3740
 
        merger.pp = ProgressPhase("Merge phase", 5, pb)
3741
 
        merger.pp.next_phase()
3742
 
        merger.check_basis(check_clean)
3743
 
        if other_rev_id is not None:
3744
 
            merger.set_other_revision(other_rev_id, this_tree.branch)
3745
 
        else:
3746
 
            merger.set_other(other_revision)
3747
 
        merger.pp.next_phase()
3748
 
        merger.set_base(base_revision)
3749
 
        if merger.base_rev_id == merger.other_rev_id:
3750
 
            note('Nothing to do.')
3751
 
            return 0
3752
 
        if file_list is None:
3753
 
            if pull and merger.base_rev_id == merger.this_rev_id:
3754
 
                # FIXME: deduplicate with pull
3755
 
                result = merger.this_tree.pull(merger.this_branch,
3756
 
                        False, merger.other_rev_id)
3757
 
                if result.old_revid == result.new_revid:
3758
 
                    note('No revisions to pull.')
 
4277
        tags = branch.tags.get_tag_dict().items()
 
4278
        if sort == 'alpha':
 
4279
            tags.sort()
 
4280
        elif sort == 'time':
 
4281
            timestamps = {}
 
4282
            for tag, revid in tags:
 
4283
                try:
 
4284
                    revobj = branch.repository.get_revision(revid)
 
4285
                except errors.NoSuchRevision:
 
4286
                    timestamp = sys.maxint # place them at the end
3759
4287
                else:
3760
 
                    note('Now on revision %d.' % result.new_revno)
3761
 
                return 0
3762
 
        merger.backup_files = backup_files
3763
 
        merger.merge_type = merge_type 
3764
 
        merger.set_interesting_files(file_list)
3765
 
        merger.show_base = show_base 
3766
 
        merger.reprocess = reprocess
3767
 
        conflicts = merger.do_merge()
3768
 
        if file_list is None:
3769
 
            merger.set_pending()
3770
 
    finally:
3771
 
        pb.clear()
3772
 
    return conflicts
 
4288
                    timestamp = revobj.timestamp
 
4289
                timestamps[revid] = timestamp
 
4290
            tags.sort(key=lambda x: timestamps[x[1]])
 
4291
        if not show_ids:
 
4292
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
 
4293
            revno_map = branch.get_revision_id_to_revno_map()
 
4294
            tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
 
4295
                        for tag, revid in tags ]
 
4296
        for tag, revspec in tags:
 
4297
            self.outf.write('%-20s %s\n' % (tag, revspec))
 
4298
 
 
4299
 
 
4300
class cmd_reconfigure(Command):
 
4301
    """Reconfigure the type of a bzr directory.
 
4302
 
 
4303
    A target configuration must be specified.
 
4304
 
 
4305
    For checkouts, the bind-to location will be auto-detected if not specified.
 
4306
    The order of preference is
 
4307
    1. For a lightweight checkout, the current bound location.
 
4308
    2. For branches that used to be checkouts, the previously-bound location.
 
4309
    3. The push location.
 
4310
    4. The parent location.
 
4311
    If none of these is available, --bind-to must be specified.
 
4312
    """
 
4313
 
 
4314
    takes_args = ['location?']
 
4315
    takes_options = [RegistryOption.from_kwargs('target_type',
 
4316
                     title='Target type',
 
4317
                     help='The type to reconfigure the directory to.',
 
4318
                     value_switches=True, enum_switch=False,
 
4319
                     branch='Reconfigure to a branch.',
 
4320
                     tree='Reconfigure to a tree.',
 
4321
                     checkout='Reconfigure to a checkout.',
 
4322
                     lightweight_checkout='Reconfigure to a lightweight'
 
4323
                     ' checkout.'),
 
4324
                     Option('bind-to', help='Branch to bind checkout to.',
 
4325
                            type=str),
 
4326
                     Option('force',
 
4327
                        help='Perform reconfiguration even if local changes'
 
4328
                        ' will be lost.')
 
4329
                     ]
 
4330
 
 
4331
    def run(self, location=None, target_type=None, bind_to=None, force=False):
 
4332
        directory = bzrdir.BzrDir.open(location)
 
4333
        if target_type is None:
 
4334
            raise errors.BzrCommandError('No target configuration specified')
 
4335
        elif target_type == 'branch':
 
4336
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
 
4337
        elif target_type == 'tree':
 
4338
            reconfiguration = reconfigure.Reconfigure.to_tree(directory)
 
4339
        elif target_type == 'checkout':
 
4340
            reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
 
4341
                                                                  bind_to)
 
4342
        elif target_type == 'lightweight-checkout':
 
4343
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
 
4344
                directory, bind_to)
 
4345
        reconfiguration.apply(force)
 
4346
 
 
4347
 
 
4348
class cmd_switch(Command):
 
4349
    """Set the branch of a checkout and update.
 
4350
    
 
4351
    For lightweight checkouts, this changes the branch being referenced.
 
4352
    For heavyweight checkouts, this checks that there are no local commits
 
4353
    versus the current bound branch, then it makes the local branch a mirror
 
4354
    of the new location and binds to it.
 
4355
    
 
4356
    In both cases, the working tree is updated and uncommitted changes
 
4357
    are merged. The user can commit or revert these as they desire.
 
4358
 
 
4359
    Pending merges need to be committed or reverted before using switch.
 
4360
    """
 
4361
 
 
4362
    takes_args = ['to_location']
 
4363
    takes_options = [Option('force',
 
4364
                        help='Switch even if local commits will be lost.')
 
4365
                     ]
 
4366
 
 
4367
    def run(self, to_location, force=False):
 
4368
        from bzrlib import switch
 
4369
        to_branch = Branch.open(to_location)
 
4370
        tree_location = '.'
 
4371
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
4372
        switch.switch(control_dir, to_branch, force)
 
4373
        note('Switched to branch: %s',
 
4374
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
3773
4375
 
3774
4376
 
3775
4377
def _create_prefix(cur_transport):
3778
4380
    while True:
3779
4381
        new_transport = cur_transport.clone('..')
3780
4382
        if new_transport.base == cur_transport.base:
3781
 
            raise errors.BzrCommandError("Failed to create path"
3782
 
                                         " prefix for %s."
3783
 
                                         % location)
 
4383
            raise errors.BzrCommandError(
 
4384
                "Failed to create path prefix for %s."
 
4385
                % cur_transport.base)
3784
4386
        try:
3785
4387
            new_transport.mkdir('.')
3786
4388
        except errors.NoSuchFile:
3788
4390
            cur_transport = new_transport
3789
4391
        else:
3790
4392
            break
3791
 
 
3792
4393
    # Now we only need to create child directories
3793
4394
    while needed:
3794
4395
        cur_transport = needed.pop()
3795
4396
        cur_transport.ensure_base()
3796
4397
 
3797
 
# Compatibility
3798
 
merge = _merge_helper
 
4398
 
 
4399
def _get_mergeable_helper(location):
 
4400
    """Get a merge directive or bundle if 'location' points to one.
 
4401
 
 
4402
    Try try to identify a bundle and returns its mergeable form. If it's not,
 
4403
    we return the tried transport anyway so that it can reused to access the
 
4404
    branch
 
4405
 
 
4406
    :param location: can point to a bundle or a branch.
 
4407
 
 
4408
    :return: mergeable, transport
 
4409
    """
 
4410
    mergeable = None
 
4411
    url = urlutils.normalize_url(location)
 
4412
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
 
4413
    location_transport = transport.get_transport(url)
 
4414
    if filename:
 
4415
        try:
 
4416
            # There may be redirections but we ignore the intermediate
 
4417
            # and final transports used
 
4418
            read = bundle.read_mergeable_from_transport
 
4419
            mergeable, t = read(location_transport, filename)
 
4420
        except errors.NotABundle:
 
4421
            # Continue on considering this url a Branch but adjust the
 
4422
            # location_transport
 
4423
            location_transport = location_transport.clone(filename)
 
4424
    return mergeable, location_transport
3799
4425
 
3800
4426
 
3801
4427
# these get imported and then picked up by the scan for cmd_*
3805
4431
# details were needed.
3806
4432
from bzrlib.cmd_version_info import cmd_version_info
3807
4433
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3808
 
from bzrlib.bundle.commands import cmd_bundle_revisions
 
4434
from bzrlib.bundle.commands import (
 
4435
    cmd_bundle_info,
 
4436
    )
3809
4437
from bzrlib.sign_my_commits import cmd_sign_my_commits
3810
4438
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3811
4439
        cmd_weave_plan_merge, cmd_weave_merge_text