~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

fix NEWS

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
25
27
import sys
 
28
import tempfile
26
29
import time
27
30
 
28
31
import bzrlib
29
32
from bzrlib import (
 
33
    branch,
30
34
    bugtracker,
31
35
    bundle,
32
36
    bzrdir,
39
43
    merge as _mod_merge,
40
44
    merge_directive,
41
45
    osutils,
42
 
    reconfigure,
43
 
    revision as _mod_revision,
 
46
    registry,
 
47
    repository,
 
48
    revisionspec,
44
49
    symbol_versioning,
45
50
    transport,
46
51
    tree as _mod_tree,
48
53
    urlutils,
49
54
    )
50
55
from bzrlib.branch import Branch
 
56
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
51
57
from bzrlib.conflicts import ConflictList
 
58
from bzrlib.revision import common_ancestor
52
59
from bzrlib.revisionspec import RevisionSpec
53
 
from bzrlib.smtp_connection import SMTPConnection
54
60
from bzrlib.workingtree import WorkingTree
55
61
""")
56
62
 
57
63
from bzrlib.commands import Command, display_command
58
 
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
 
from bzrlib.trace import mutter, note, warning, is_quiet, info
 
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
60
67
 
61
68
 
62
69
def tree_files(file_list, default_branch=u'.'):
146
153
    To see ignored files use 'bzr ignored'.  For details on the
147
154
    changes to file texts, use 'bzr diff'.
148
155
    
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.
 
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
152
175
 
153
176
    If no arguments are specified, the status of the entire working
154
177
    directory is shown.  Otherwise, only the status of the specified
162
185
    # TODO: --no-recurse, --recurse options
163
186
    
164
187
    takes_args = ['file*']
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
 
                     ]
 
188
    takes_options = ['show-ids', 'revision',
 
189
                     Option('short', help='Give short SVN-style status lines'),
 
190
                     Option('versioned', help='Only show versioned files')]
171
191
    aliases = ['st', 'stat']
172
192
 
173
193
    encoding_type = 'replace'
174
 
    _see_also = ['diff', 'revert', 'status-flags']
 
194
    _see_also = ['diff', 'revert']
175
195
    
176
196
    @display_command
177
197
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
178
198
            versioned=False):
179
199
        from bzrlib.status import show_tree_status
180
200
 
181
 
        if revision and len(revision) > 2:
182
 
            raise errors.BzrCommandError('bzr status --revision takes exactly'
183
 
                                         ' one or two revision specifiers')
184
 
 
185
201
        tree, file_list = tree_files(file_list)
186
202
            
187
203
        show_tree_status(tree, show_ids=show_ids,
204
220
    
205
221
    @display_command
206
222
    def run(self, revision_id=None, revision=None):
 
223
 
 
224
        revision_id = osutils.safe_revision_id(revision_id, warn=False)
207
225
        if revision_id is not None and revision is not None:
208
226
            raise errors.BzrCommandError('You can only supply one of'
209
227
                                         ' revision_id or --revision')
214
232
 
215
233
        # TODO: jam 20060112 should cat-revision always output utf-8?
216
234
        if revision_id is not None:
217
 
            revision_id = osutils.safe_revision_id(revision_id, warn=False)
218
235
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
219
236
        elif revision is not None:
220
237
            for rev in revision:
339
356
    into a subdirectory of this one.
340
357
    """
341
358
    takes_args = ['file*']
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
 
        ]
 
359
    takes_options = ['no-recurse', 'dry-run', 'verbose',
 
360
                     Option('file-ids-from', type=unicode,
 
361
                            help='Lookup file ids from here')]
352
362
    encoding_type = 'replace'
353
363
    _see_also = ['remove']
354
364
 
375
385
        if base_tree:
376
386
            base_tree.lock_read()
377
387
        try:
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)
 
388
            added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
 
389
                action=action, save=not dry_run)
385
390
        finally:
386
391
            if base_tree is not None:
387
392
                base_tree.unlock()
444
449
 
445
450
    hidden = True
446
451
    _see_also = ['ls']
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
 
        ]
 
452
    takes_options = ['revision', 'show-ids', 'kind']
454
453
    takes_args = ['file*']
455
454
 
456
455
    @display_command
457
456
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
458
457
        if kind and kind not in ['file', 'directory', 'symlink']:
459
 
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
 
458
            raise errors.BzrCommandError('invalid kind specified')
460
459
 
461
460
        work_tree, file_list = tree_files(file_list)
462
461
        work_tree.lock_read()
502
501
class cmd_mv(Command):
503
502
    """Move or rename a file.
504
503
 
505
 
    :Usage:
 
504
    usage:
506
505
        bzr mv OLDNAME NEWNAME
507
 
 
508
506
        bzr mv SOURCE... DESTINATION
509
507
 
510
508
    If the last argument is a versioned directory, all the other names
521
519
    """
522
520
 
523
521
    takes_args = ['names*']
524
 
    takes_options = [Option("after", help="Move only the bzr identifier"
525
 
        " of the file, because the file has already been moved."),
526
 
        ]
 
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.")]
527
525
    aliases = ['move', 'rename']
528
526
    encoding_type = 'replace'
529
527
 
568
566
    location can be accessed.
569
567
    """
570
568
 
571
 
    _see_also = ['push', 'update', 'status-flags']
572
 
    takes_options = ['remember', 'overwrite', 'revision',
573
 
        custom_help('verbose',
574
 
            help='Show logs of pulled revisions.'),
 
569
    _see_also = ['push', 'update']
 
570
    takes_options = ['remember', 'overwrite', 'revision', 'verbose',
575
571
        Option('directory',
576
 
            help='Branch to pull into, '
577
 
                 'rather than the one containing the working directory.',
 
572
            help='branch to pull into, '
 
573
                 'rather than the one containing the working directory',
578
574
            short_name='d',
579
575
            type=unicode,
580
576
            ),
585
581
    def run(self, location=None, remember=False, overwrite=False,
586
582
            revision=None, verbose=False,
587
583
            directory=None):
 
584
        from bzrlib.tag import _merge_tags_if_possible
588
585
        # FIXME: too much stuff is in the command class
589
586
        revision_id = None
590
587
        mergeable = None
597
594
            tree_to = None
598
595
            branch_to = Branch.open_containing(directory)[0]
599
596
 
600
 
        possible_transports = []
 
597
        reader = None
601
598
        if location is not None:
602
 
            mergeable, location_transport = _get_mergeable_helper(location)
603
 
            possible_transports.append(location_transport)
 
599
            try:
 
600
                mergeable = bundle.read_mergeable_from_url(
 
601
                    location)
 
602
            except errors.NotABundle:
 
603
                pass # Continue on considering this url a Branch
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)
617
615
 
618
616
        if mergeable is not None:
619
617
            if revision is not None:
620
618
                raise errors.BzrCommandError(
621
619
                    'Cannot use -r with merge directives or bundles')
622
 
            mergeable.install_revisions(branch_to.repository)
623
 
            base_revision_id, revision_id, verified = \
624
 
                mergeable.get_merge_request(branch_to.repository)
 
620
            revision_id = mergeable.install_revisions(branch_to.repository)
625
621
            branch_from = branch_to
626
622
        else:
627
 
            branch_from = Branch.open_from_transport(location_transport)
 
623
            branch_from = Branch.open(location)
628
624
 
629
625
            if branch_to.get_parent() is None or remember:
630
626
                branch_to.set_parent(branch_from.base)
636
632
                raise errors.BzrCommandError(
637
633
                    'bzr pull --revision takes one value.')
638
634
 
639
 
        if verbose:
640
 
            old_rh = branch_to.revision_history()
 
635
        old_rh = branch_to.revision_history()
641
636
        if tree_to is not None:
642
 
            change_reporter = delta._ChangeReporter(
643
 
                unversioned_filter=tree_to.is_ignored)
644
637
            result = tree_to.pull(branch_from, overwrite, revision_id,
645
 
                                  change_reporter,
646
 
                                  possible_transports=possible_transports)
 
638
                delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
647
639
        else:
648
640
            result = branch_to.pull(branch_from, overwrite, revision_id)
649
641
 
650
642
        result.report(self.outf)
651
643
        if verbose:
 
644
            from bzrlib.log import show_changed_revisions
652
645
            new_rh = branch_to.revision_history()
653
 
            log.show_changed_revisions(branch_to, old_rh, new_rh,
654
 
                                       to_file=self.outf)
 
646
            show_changed_revisions(branch_to, old_rh, new_rh,
 
647
                                   to_file=self.outf)
655
648
 
656
649
 
657
650
class cmd_push(Command):
684
677
    takes_options = ['remember', 'overwrite', 'verbose',
685
678
        Option('create-prefix',
686
679
               help='Create the path leading up to the branch '
687
 
                    'if it does not already exist.'),
 
680
                    'if it does not already exist'),
688
681
        Option('directory',
689
 
            help='Branch to push from, '
690
 
                 'rather than the one containing the working directory.',
 
682
            help='branch to push from, '
 
683
                 'rather than the one containing the working directory',
691
684
            short_name='d',
692
685
            type=unicode,
693
686
            ),
694
687
        Option('use-existing-dir',
695
688
               help='By default push will fail if the target'
696
689
                    ' directory exists, but does not already'
697
 
                    ' have a control directory.  This flag will'
 
690
                    ' have a control directory. This flag will'
698
691
                    ' allow push to proceed.'),
699
692
        ]
700
693
    takes_args = ['location?']
741
734
                # Found a branch, so we must have found a repository
742
735
                repository_to = br_to.repository
743
736
        push_result = None
744
 
        if verbose:
745
 
            old_rh = []
 
737
        old_rh = []
746
738
        if dir_to is None:
747
739
            # The destination doesn't exist; create it.
748
740
            # XXX: Refactor the create_prefix/no_create_prefix code into a
749
741
            #      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
 
 
758
742
            try:
759
 
                to_transport = transport.do_catching_redirections(
760
 
                    make_directory, to_transport, redirected)
 
743
                to_transport.mkdir('.')
761
744
            except errors.FileExists:
762
745
                if not use_existing_dir:
763
746
                    raise errors.BzrCommandError("Target directory %s"
771
754
                        "\nYou may supply --create-prefix to create all"
772
755
                        " leading parent directories."
773
756
                        % location)
 
757
 
774
758
                _create_prefix(to_transport)
775
 
            except errors.TooManyRedirections:
776
 
                raise errors.BzrCommandError("Too many redirections trying "
777
 
                                             "to make %s." % location)
778
759
 
779
760
            # Now the target directory exists, but doesn't have a .bzr
780
761
            # directory. So we need to create it, along with any work to create
810
791
            # we don't need to successfully push because of possible divergence.
811
792
            if br_from.get_push_location() is None or remember:
812
793
                br_from.set_push_location(br_to.base)
813
 
            if verbose:
814
 
                old_rh = br_to.revision_history()
 
794
            old_rh = br_to.revision_history()
815
795
            try:
816
796
                try:
817
797
                    tree_to = dir_to.open_workingtree()
874
854
            raise errors.BzrCommandError(
875
855
                'bzr branch --revision takes exactly 1 revision value')
876
856
 
877
 
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
878
 
            from_location)
 
857
        br_from = Branch.open(from_location)
879
858
        br_from.lock_read()
880
859
        try:
881
860
            if len(revision) == 1 and revision[0] is not None:
902
881
                                             % to_location)
903
882
            try:
904
883
                # preserve whatever source format we have.
905
 
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
906
 
                                            possible_transports=[to_transport],
907
 
                                            accelerator_tree=accelerator_tree)
 
884
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id)
908
885
                branch = dir.open_branch()
909
886
            except errors.NoSuchRevision:
910
887
                to_transport.delete_tree('.')
943
920
    takes_args = ['branch_location?', 'to_location?']
944
921
    takes_options = ['revision',
945
922
                     Option('lightweight',
946
 
                            help="Perform a lightweight checkout.  Lightweight "
 
923
                            help="perform a lightweight checkout. Lightweight "
947
924
                                 "checkouts depend on access to the branch for "
948
 
                                 "every operation.  Normal checkouts can perform "
 
925
                                 "every operation. Normal checkouts can perform "
949
926
                                 "common operations like diff and status without "
950
927
                                 "such access, and also support local commits."
951
928
                            ),
952
 
                     Option('files-from',
953
 
                            help="Get file contents from this tree.", type=str)
954
929
                     ]
955
930
    aliases = ['co']
956
931
 
957
932
    def run(self, branch_location=None, to_location=None, revision=None,
958
 
            lightweight=False, files_from=None):
 
933
            lightweight=False):
959
934
        if revision is None:
960
935
            revision = [None]
961
936
        elif len(revision) > 1:
964
939
        if branch_location is None:
965
940
            branch_location = osutils.getcwd()
966
941
            to_location = 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)
 
942
        source = Branch.open(branch_location)
971
943
        if len(revision) == 1 and revision[0] is not None:
972
 
            revision_id = _mod_revision.ensure_null(
973
 
                revision[0].in_history(source)[1])
 
944
            revision_id = revision[0].in_history(source)[1]
974
945
        else:
975
946
            revision_id = None
976
947
        if to_location is None:
983
954
            try:
984
955
                source.bzrdir.open_workingtree()
985
956
            except errors.NoWorkingTree:
986
 
                source.bzrdir.create_workingtree(revision_id)
 
957
                source.bzrdir.create_workingtree()
987
958
                return
988
 
        source.create_checkout(to_location, revision_id, lightweight,
989
 
                               accelerator_tree)
 
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)
990
971
 
991
972
 
992
973
class cmd_renames(Command):
1029
1010
    'bzr revert' instead of 'bzr commit' after the update.
1030
1011
    """
1031
1012
 
1032
 
    _see_also = ['pull', 'working-trees', 'status-flags']
 
1013
    _see_also = ['pull', 'working-trees']
1033
1014
    takes_args = ['dir?']
1034
1015
    aliases = ['up']
1035
1016
 
1036
1017
    def run(self, dir='.'):
1037
1018
        tree = WorkingTree.open_containing(dir)[0]
1038
 
        possible_transports = []
1039
 
        master = tree.branch.get_master_branch(
1040
 
            possible_transports=possible_transports)
 
1019
        master = tree.branch.get_master_branch()
1041
1020
        if master is not None:
1042
1021
            tree.lock_write()
1043
1022
        else:
1044
1023
            tree.lock_tree_write()
1045
1024
        try:
1046
1025
            existing_pending_merges = tree.get_parent_ids()[1:]
1047
 
            last_rev = _mod_revision.ensure_null(tree.last_revision())
1048
 
            if last_rev == _mod_revision.ensure_null(
1049
 
                tree.branch.last_revision()):
 
1026
            last_rev = tree.last_revision()
 
1027
            if last_rev == tree.branch.last_revision():
1050
1028
                # may be up to date, check master too.
1051
 
                if master is None or last_rev == _mod_revision.ensure_null(
1052
 
                    master.last_revision()):
 
1029
                master = tree.branch.get_master_branch()
 
1030
                if master is None or last_rev == master.last_revision():
1053
1031
                    revno = tree.branch.revision_id_to_revno(last_rev)
1054
1032
                    note("Tree is up to date at revision %d." % (revno,))
1055
1033
                    return 0
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()))
 
1034
            conflicts = tree.update()
 
1035
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
1061
1036
            note('Updated to revision %d.' % (revno,))
1062
1037
            if tree.get_parent_ids()[1:] != existing_pending_merges:
1063
1038
                note('Your local commits will now show as pending merges with '
1082
1057
    _see_also = ['revno', 'working-trees', 'repositories']
1083
1058
    takes_args = ['location?']
1084
1059
    takes_options = ['verbose']
1085
 
    encoding_type = 'replace'
1086
1060
 
1087
1061
    @display_command
1088
 
    def run(self, location=None, verbose=False):
1089
 
        if verbose:
1090
 
            noise_level = 2
1091
 
        else:
1092
 
            noise_level = 0
 
1062
    def run(self, location=None, verbose=0):
1093
1063
        from bzrlib.info import show_bzrdir_info
1094
1064
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1095
 
                         verbose=noise_level, outfile=self.outf)
 
1065
                         verbose=verbose)
1096
1066
 
1097
1067
 
1098
1068
class cmd_remove(Command):
1108
1078
    """
1109
1079
    takes_args = ['file*']
1110
1080
    takes_options = ['verbose',
1111
 
        Option('new', help='Remove newly-added files.'),
 
1081
        Option('new', help='remove newly-added files'),
1112
1082
        RegistryOption.from_kwargs('file-deletion-strategy',
1113
 
            'The file deletion mode to be used.',
 
1083
            'The file deletion mode to be used',
1114
1084
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1115
1085
            safe='Only delete files if they can be'
1116
1086
                 ' safely recovered (default).',
1125
1095
        tree, file_list = tree_files(file_list)
1126
1096
 
1127
1097
        if file_list is not None:
1128
 
            file_list = [f for f in file_list]
 
1098
            file_list = [f for f in file_list if f != '']
1129
1099
        elif not new:
1130
1100
            raise errors.BzrCommandError('Specify one or more files to'
1131
1101
            ' remove, or use --new.')
1269
1239
    If there is already a branch at the location but it has no working tree,
1270
1240
    the tree can be populated with 'bzr checkout'.
1271
1241
 
1272
 
    Recipe for importing a tree of files::
1273
 
 
 
1242
    Recipe for importing a tree of files:
1274
1243
        cd ~/project
1275
1244
        bzr init
1276
1245
        bzr add .
1277
1246
        bzr status
1278
 
        bzr commit -m "imported project"
 
1247
        bzr commit -m 'imported project'
1279
1248
    """
1280
1249
 
1281
 
    _see_also = ['init-repository', 'branch', 'checkout']
 
1250
    _see_also = ['init-repo', 'branch', 'checkout']
1282
1251
    takes_args = ['location?']
1283
1252
    takes_options = [
1284
1253
        Option('create-prefix',
1285
1254
               help='Create the path leading up to the branch '
1286
 
                    'if it does not already exist.'),
 
1255
                    'if it does not already exist'),
1287
1256
         RegistryOption('format',
1288
1257
                help='Specify a format for this branch. '
1289
1258
                'See "help formats".',
1322
1291
            _create_prefix(to_transport)
1323
1292
 
1324
1293
        try:
1325
 
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
1294
            existing_bzrdir = bzrdir.BzrDir.open(location)
1326
1295
        except errors.NotBranchError:
1327
1296
            # really a NotBzrDir error...
1328
 
            create_branch = bzrdir.BzrDir.create_branch_convenience
1329
 
            branch = create_branch(to_transport.base, format=format,
1330
 
                                   possible_transports=[to_transport])
 
1297
            branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
 
1298
                                                             format=format)
1331
1299
        else:
1332
1300
            from bzrlib.transport.local import LocalTransport
1333
1301
            if existing_bzrdir.has_branch():
1355
1323
    If the --no-trees option is used then the branches in the repository
1356
1324
    will not have working trees by default.
1357
1325
 
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)
 
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.
1369
1334
    """
1370
1335
 
1371
 
    _see_also = ['init', 'branch', 'checkout', 'repositories']
 
1336
    _see_also = ['init', 'branch', 'checkout']
1372
1337
    takes_args = ["location"]
1373
1338
    takes_options = [RegistryOption('format',
1374
1339
                            help='Specify a format for this repository. See'
1375
 
                                 ' "bzr help formats" for details.',
 
1340
                                 ' "bzr help formats" for details',
1376
1341
                            registry=bzrdir.format_registry,
1377
1342
                            converter=bzrdir.format_registry.make_bzrdir,
1378
1343
                            value_switches=True, title='Repository format'),
1379
1344
                     Option('no-trees',
1380
1345
                             help='Branches in the repository will default to'
1381
 
                                  ' not having a working tree.'),
 
1346
                                  ' not having a working tree'),
1382
1347
                    ]
1383
1348
    aliases = ["init-repo"]
1384
1349
 
1398
1363
 
1399
1364
 
1400
1365
class cmd_diff(Command):
1401
 
    """Show differences in the working tree, between revisions or branches.
 
1366
    """Show differences in the working tree or between revisions.
1402
1367
    
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.
 
1368
    If files are listed, only the changes in those files are listed.
 
1369
    Otherwise, all changes for the tree are listed.
1409
1370
 
1410
1371
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1411
1372
    produces patches suitable for "patch -p1".
1412
1373
 
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/
 
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'
1455
1387
    """
 
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
 
1456
1399
    _see_also = ['status']
1457
1400
    takes_args = ['file*']
1458
 
    takes_options = [
1459
 
        Option('diff-options', type=str,
1460
 
               help='Pass these options to the external diff program.'),
 
1401
    takes_options = ['revision', 'diff-options',
1461
1402
        Option('prefix', type=str,
1462
1403
               short_name='p',
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
 
            ),
 
1404
               help='Set prefixes to added to old and new filenames, as '
 
1405
                    'two values separated by a colon. (eg "old/:new/")'),
1479
1406
        ]
1480
1407
    aliases = ['di', 'dif']
1481
1408
    encoding_type = 'exact'
1482
1409
 
1483
1410
    @display_command
1484
1411
    def run(self, revision=None, file_list=None, diff_options=None,
1485
 
            prefix=None, old=None, new=None, using=None):
1486
 
        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
 
1412
            prefix=None):
 
1413
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
1487
1414
 
1488
1415
        if (prefix is None) or (prefix == '0'):
1489
1416
            # diff -p0 format
1503
1430
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1504
1431
                                         ' one or two revision specifiers')
1505
1432
 
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)
 
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)
1513
1474
 
1514
1475
 
1515
1476
class cmd_deleted(Command):
1623
1584
    -r revision requests a specific revision, -r ..end or -r begin.. are
1624
1585
    also valid.
1625
1586
 
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
 
1587
    examples:
 
1588
        bzr log
 
1589
        bzr log foo.c
 
1590
        bzr log -r -10.. http://server/branch
1638
1591
    """
1639
1592
 
1640
1593
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1641
1594
 
1642
1595
    takes_args = ['location?']
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
 
            ]
 
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
                     ]
1665
1612
    encoding_type = 'replace'
1666
1613
 
1667
1614
    @display_command
1710
1657
                rev1 = None
1711
1658
                rev2 = None
1712
1659
            elif len(revision) == 1:
1713
 
                rev1 = rev2 = revision[0].in_history(b)
 
1660
                rev1 = rev2 = revision[0].in_history(b).revno
1714
1661
            elif len(revision) == 2:
1715
1662
                if revision[1].get_branch() != revision[0].get_branch():
1716
1663
                    # b is taken from revision[0].get_branch(), and
1719
1666
                    raise errors.BzrCommandError(
1720
1667
                        "Log doesn't accept two revisions in different"
1721
1668
                        " branches.")
1722
 
                rev1 = revision[0].in_history(b)
1723
 
                rev2 = revision[1].in_history(b)
 
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
1724
1680
            else:
1725
1681
                raise errors.BzrCommandError(
1726
1682
                    'bzr log --revision takes one or two values.')
1727
1683
 
 
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
 
1728
1690
            if log_format is None:
1729
1691
                log_format = log.log_formatter_registry.get_default(b)
1730
1692
 
1780
1742
    _see_also = ['status', 'cat']
1781
1743
    takes_args = ['path?']
1782
1744
    # TODO: Take a revision or remote path and list that tree instead.
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
 
            ]
 
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
                    ]
1801
1757
    @display_command
1802
 
    def run(self, revision=None, verbose=False,
 
1758
    def run(self, revision=None, verbose=False, 
1803
1759
            non_recursive=False, from_root=False,
1804
1760
            unknown=False, versioned=False, ignored=False,
1805
1761
            null=False, kind=None, show_ids=False, path=None):
1897
1853
 
1898
1854
    Ignore patterns specifying absolute paths are not allowed.
1899
1855
 
1900
 
    Ignore patterns may include globbing wildcards such as::
1901
 
 
 
1856
    Ignore patterns may include globbing wildcards such as:
1902
1857
      ? - Matches any single character except '/'
1903
1858
      * - Matches 0 or more characters except '/'
1904
1859
      /**/ - Matches 0 or more directories in a path
1912
1867
    Note: ignore patterns containing shell wildcards must be quoted from 
1913
1868
    the shell on Unix.
1914
1869
 
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"
 
1870
    examples:
 
1871
        bzr ignore ./Makefile
 
1872
        bzr ignore '*.class'
 
1873
        bzr ignore 'lib/**/*.o'
 
1874
        bzr ignore 'RE:lib/.*\.o'
1931
1875
    """
1932
1876
 
1933
1877
    _see_also = ['status', 'ignored']
1934
1878
    takes_args = ['name_pattern*']
1935
1879
    takes_options = [
1936
 
        Option('old-default-rules',
1937
 
               help='Write out the ignore rules bzr < 0.9 always used.')
1938
 
        ]
 
1880
                     Option('old-default-rules',
 
1881
                            help='Out the ignore rules bzr < 0.9 always used.')
 
1882
                     ]
1939
1883
    
1940
1884
    def run(self, name_pattern_list=None, old_default_rules=None):
1941
1885
        from bzrlib.atomicfile import AtomicFile
1983
1927
        if not tree.path2id('.bzrignore'):
1984
1928
            tree.add(['.bzrignore'])
1985
1929
 
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),)
1999
1930
 
2000
1931
class cmd_ignored(Command):
2001
1932
    """List ignored files and the patterns that matched them.
2002
1933
    """
2003
1934
 
2004
 
    encoding_type = 'replace'
2005
1935
    _see_also = ['ignore']
2006
 
 
2007
1936
    @display_command
2008
1937
    def run(self):
2009
1938
        tree = WorkingTree.open_containing(u'.')[0]
2014
1943
                    continue
2015
1944
                ## XXX: Slightly inefficient since this was already calculated
2016
1945
                pat = tree.is_ignored(path)
2017
 
                self.outf.write('%-50s %s\n' % (path, pat))
 
1946
                print '%-50s %s' % (path, pat)
2018
1947
        finally:
2019
1948
            tree.unlock()
2020
1949
 
2022
1951
class cmd_lookup_revision(Command):
2023
1952
    """Lookup the revision-id from a revision-number
2024
1953
 
2025
 
    :Examples:
 
1954
    example:
2026
1955
        bzr lookup-revision 33
2027
1956
    """
2028
1957
    hidden = True
2056
1985
 
2057
1986
    Note: Export of tree with non-ASCII filenames to zip is not supported.
2058
1987
 
2059
 
      =================       =========================
2060
 
      Supported formats       Autodetected by extension
2061
 
      =================       =========================
2062
 
         dir                         (none)
 
1988
     Supported formats       Autodetected by extension
 
1989
     -----------------       -------------------------
 
1990
         dir                            -
2063
1991
         tar                          .tar
2064
1992
         tbz2                    .tar.bz2, .tbz2
2065
1993
         tgz                      .tar.gz, .tgz
2066
1994
         zip                          .zip
2067
 
      =================       =========================
2068
1995
    """
2069
1996
    takes_args = ['dest', 'branch?']
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
 
        ]
 
1997
    takes_options = ['revision', 'format', 'root']
2079
1998
    def run(self, dest, branch=None, revision=None, format=None, root=None):
2080
1999
        from bzrlib.export import export
2081
2000
 
2109
2028
    """
2110
2029
 
2111
2030
    _see_also = ['ls']
2112
 
    takes_options = [
2113
 
        Option('name-from-revision', help='The path name in the old tree.'),
2114
 
        'revision',
2115
 
        ]
 
2031
    takes_options = ['revision', 'name-from-revision']
2116
2032
    takes_args = ['filename']
2117
2033
    encoding_type = 'exact'
2118
2034
 
2120
2036
    def run(self, filename, revision=None, name_from_revision=False):
2121
2037
        if revision is not None and len(revision) != 1:
2122
2038
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2123
 
                                         " one revision specifier")
2124
 
        tree, branch, relpath = \
2125
 
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2126
 
        branch.lock_read()
 
2039
                                        " one number")
 
2040
 
 
2041
        tree = None
2127
2042
        try:
2128
 
            return self._run(tree, branch, relpath, filename, revision,
2129
 
                             name_from_revision)
2130
 
        finally:
2131
 
            branch.unlock()
 
2043
            tree, b, relpath = \
 
2044
                    bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
2045
        except errors.NotBranchError:
 
2046
            pass
2132
2047
 
2133
 
    def _run(self, tree, b, relpath, filename, revision, name_from_revision):
 
2048
        if revision is not None and revision[0].get_branch() is not None:
 
2049
            b = Branch.open(revision[0].get_branch())
2134
2050
        if tree is None:
2135
2051
            tree = b.basis_tree()
2136
2052
        if revision is None:
2175
2091
    committed.  If a directory is specified then the directory and everything 
2176
2092
    within it is committed.
2177
2093
 
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
 
 
2182
2094
    A selected-file commit may fail in some cases where the committed
2183
2095
    tree would be invalid. Consider::
2184
2096
 
2209
2121
 
2210
2122
    _see_also = ['bugs', 'uncommit']
2211
2123
    takes_args = ['selected*']
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
 
             ]
 
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
                     ]
2241
2144
    aliases = ['ci', 'checkin']
2242
2145
 
2243
2146
    def _get_bug_fix_properties(self, fixes, branch):
2262
2165
            properties.append('%s fixed' % bug_url)
2263
2166
        return '\n'.join(properties)
2264
2167
 
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
 
        )
 
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
2277
2175
 
2278
2176
        # TODO: Need a blackbox test for invoking the external editor; may be
2279
2177
        # slightly problematic to run this cross-platform.
2290
2188
            # selected-file merge commit is not done yet
2291
2189
            selected_list = []
2292
2190
 
2293
 
        if fixes is None:
2294
 
            fixes = []
2295
2191
        bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2296
2192
        if bug_property:
2297
2193
            properties['bugs'] = bug_property
2303
2199
            """Callback to get commit message"""
2304
2200
            my_message = message
2305
2201
            if my_message is None and not file:
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)
 
2202
                template = make_commit_message_template(tree, selected_list)
 
2203
                my_message = edit_commit_message(template)
2310
2204
                if my_message is None:
2311
2205
                    raise errors.BzrCommandError("please specify a commit"
2312
2206
                        " message with either --message or --file")
2320
2214
                raise errors.BzrCommandError("empty commit message specified")
2321
2215
            return my_message
2322
2216
 
 
2217
        if verbose:
 
2218
            reporter = ReportCommitToLog()
 
2219
        else:
 
2220
            reporter = NullCommitReporter()
 
2221
 
2323
2222
        try:
2324
2223
            tree.commit(message_callback=get_message,
2325
2224
                        specific_files=selected_list,
2326
2225
                        allow_pointless=unchanged, strict=strict, local=local,
2327
 
                        reporter=None, verbose=verbose, revprops=properties,
2328
 
                        author=author)
 
2226
                        reporter=reporter, revprops=properties)
2329
2227
        except PointlessCommit:
2330
2228
            # FIXME: This should really happen before the file is read in;
2331
2229
            # perhaps prepare the commit; get the message; then actually commit
2350
2248
 
2351
2249
    This command checks various invariants about the branch storage to
2352
2250
    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.
2369
2251
    """
2370
2252
 
2371
2253
    _see_also = ['reconcile']
2375
2257
    def run(self, branch=None, verbose=False):
2376
2258
        from bzrlib.check import check
2377
2259
        if branch is None:
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()
 
2260
            tree = WorkingTree.open_containing()[0]
 
2261
            branch = tree.branch
 
2262
        else:
 
2263
            branch = Branch.open(branch)
 
2264
        check(branch, verbose)
2408
2265
 
2409
2266
 
2410
2267
class cmd_upgrade(Command):
2420
2277
    takes_options = [
2421
2278
                    RegistryOption('format',
2422
2279
                        help='Upgrade to a specific format.  See "bzr help'
2423
 
                             ' formats" for details.',
 
2280
                             ' formats" for details',
2424
2281
                        registry=bzrdir.format_registry,
2425
2282
                        converter=bzrdir.format_registry.make_bzrdir,
2426
2283
                        value_switches=True, title='Branch format'),
2436
2293
class cmd_whoami(Command):
2437
2294
    """Show or set bzr user id.
2438
2295
    
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>"
 
2296
    examples:
 
2297
        bzr whoami --email
 
2298
        bzr whoami 'Frank Chu <fchu@example.com>'
2447
2299
    """
2448
2300
    takes_options = [ Option('email',
2449
 
                             help='Display email address only.'),
 
2301
                             help='display email address only'),
2450
2302
                      Option('branch',
2451
 
                             help='Set identity for the current branch instead of '
2452
 
                                  'globally.'),
 
2303
                             help='set identity for the current branch instead of '
 
2304
                                  'globally'),
2453
2305
                    ]
2454
2306
    takes_args = ['name?']
2455
2307
    encoding_type = 'replace'
2535
2387
    modified by plugins will not be tested, and tests provided by plugins will
2536
2388
    not be run.
2537
2389
 
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
 
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.
2549
2402
    """
2550
2403
    # NB: this is used from the class without creating an instance, which is
2551
2404
    # why it does not have a self parameter.
2568
2421
    takes_args = ['testspecs*']
2569
2422
    takes_options = ['verbose',
2570
2423
                     Option('one',
2571
 
                             help='Stop when one test fails.',
 
2424
                             help='stop when one test fails',
2572
2425
                             short_name='1',
2573
2426
                             ),
 
2427
                     Option('keep-output',
 
2428
                            help='keep output directories when tests fail'),
2574
2429
                     Option('transport',
2575
2430
                            help='Use a different transport by default '
2576
2431
                                 'throughout the test suite.',
2577
2432
                            type=get_transport_type),
2578
 
                     Option('benchmark',
2579
 
                            help='Run the benchmarks rather than selftests.'),
 
2433
                     Option('benchmark', help='run the bzr benchmarks.'),
2580
2434
                     Option('lsprof-timed',
2581
 
                            help='Generate lsprof output for benchmarked'
 
2435
                            help='generate lsprof output for benchmarked'
2582
2436
                                 ' sections of code.'),
2583
2437
                     Option('cache-dir', type=str,
2584
 
                            help='Cache intermediate benchmark output in this '
2585
 
                                 'directory.'),
 
2438
                            help='a directory to cache intermediate'
 
2439
                                 ' benchmark steps'),
 
2440
                     Option('clean-output',
 
2441
                            help='clean temporary tests directories'
 
2442
                                 ' without running tests'),
2586
2443
                     Option('first',
2587
 
                            help='Run all tests, but run specified tests first.',
 
2444
                            help='run all tests, but run specified tests first',
2588
2445
                            short_name='f',
2589
2446
                            ),
 
2447
                     Option('numbered-dirs',
 
2448
                            help='use numbered dirs for TestCaseInTempDir'),
2590
2449
                     Option('list-only',
2591
 
                            help='List the tests instead of running them.'),
 
2450
                            help='list the tests instead of running them'),
2592
2451
                     Option('randomize', type=str, argname="SEED",
2593
 
                            help='Randomize the order of tests using the given'
2594
 
                                 ' seed or "now" for the current time.'),
 
2452
                            help='randomize the order of tests using the given'
 
2453
                                 ' seed or "now" for the current time'),
2595
2454
                     Option('exclude', type=str, argname="PATTERN",
2596
2455
                            short_name='x',
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.'),
 
2456
                            help='exclude tests that match this regular'
 
2457
                                 ' expression'),
2604
2458
                     ]
2605
2459
    encoding_type = 'replace'
2606
2460
 
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):
 
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):
2612
2466
        import bzrlib.ui
2613
2467
        from bzrlib.tests import selftest
2614
2468
        import bzrlib.benchmarks as benchmarks
2615
2469
        from bzrlib.benchmarks import tree_creator
2616
2470
 
 
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
 
2617
2483
        if cache_dir is not None:
2618
2484
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
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
 
                    )
 
2485
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
 
2486
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2626
2487
        print
2627
2488
        if testspecs_list is not None:
2628
2489
            pattern = '|'.join(testspecs_list)
2630
2491
            pattern = ".*"
2631
2492
        if benchmark:
2632
2493
            test_suite_factory = benchmarks.test_suite
2633
 
            # Unless user explicitly asks for quiet, be verbose in benchmarks
2634
 
            verbose = not is_quiet()
 
2494
            if verbose is None:
 
2495
                verbose = True
2635
2496
            # TODO: should possibly lock the history file...
2636
2497
            benchfile = open(".perf_history", "at", buffering=1)
2637
2498
        else:
2638
2499
            test_suite_factory = None
 
2500
            if verbose is None:
 
2501
                verbose = False
2639
2502
            benchfile = None
2640
2503
        try:
2641
 
            result = selftest(verbose=verbose,
 
2504
            result = selftest(verbose=verbose, 
2642
2505
                              pattern=pattern,
2643
 
                              stop_on_failure=one,
 
2506
                              stop_on_failure=one, 
2644
2507
                              transport=transport,
2645
2508
                              test_suite_factory=test_suite_factory,
2646
2509
                              lsprof_timed=lsprof_timed,
2647
2510
                              bench_history=benchfile,
2648
2511
                              matching_tests_first=first,
 
2512
                              numbered_dirs=numbered_dirs,
2649
2513
                              list_only=list_only,
2650
2514
                              random_seed=randomize,
2651
 
                              exclude_pattern=exclude,
2652
 
                              strict=strict,
2653
 
                              coverage_dir=coverage,
 
2515
                              exclude_pattern=exclude
2654
2516
                              )
2655
2517
        finally:
2656
2518
            if benchfile is not None:
2665
2527
class cmd_version(Command):
2666
2528
    """Show version of bzr."""
2667
2529
 
2668
 
    encoding_type = 'replace'
2669
 
 
2670
2530
    @display_command
2671
2531
    def run(self):
2672
2532
        from bzrlib.version import show_version
2673
 
        show_version(to_file=self.outf)
 
2533
        show_version()
2674
2534
 
2675
2535
 
2676
2536
class cmd_rocks(Command):
2692
2552
    
2693
2553
    @display_command
2694
2554
    def run(self, branch, other):
2695
 
        from bzrlib.revision import ensure_null
 
2555
        from bzrlib.revision import MultipleRevisionSources
2696
2556
        
2697
2557
        branch1 = Branch.open_containing(branch)[0]
2698
2558
        branch2 = Branch.open_containing(other)[0]
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()
 
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
2714
2569
 
2715
2570
 
2716
2571
class cmd_merge(Command):
2741
2596
    The results of the merge are placed into the destination working
2742
2597
    directory, where they can be reviewed (with bzr diff), tested, and then
2743
2598
    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
2744
2610
    
2745
2611
    merge refuses to run if there are any uncommitted changes, unless
2746
2612
    --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
2760
2613
    """
2761
2614
 
2762
 
    _see_also = ['update', 'remerge', 'status-flags']
 
2615
    _see_also = ['update', 'remerge']
2763
2616
    takes_args = ['branch?']
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',
 
2617
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2772
2618
        Option('show-base', help="Show base revision text in "
2773
 
               "conflicts."),
 
2619
               "conflicts"),
2774
2620
        Option('uncommitted', help='Apply uncommitted changes'
2775
 
               ' from a working copy, instead of branch changes.'),
 
2621
               ' from a working copy, instead of branch changes'),
2776
2622
        Option('pull', help='If the destination is already'
2777
2623
                ' completely merged into the source, pull from the'
2778
 
                ' source rather than merging.  When this happens,'
 
2624
                ' source rather than merging. When this happens,'
2779
2625
                ' you do not need to commit the result.'),
2780
2626
        Option('directory',
2781
 
               help='Branch to merge into, '
2782
 
                    'rather than the one containing the working directory.',
2783
 
               short_name='d',
2784
 
               type=unicode,
2785
 
               ),
 
2627
            help='Branch to merge into, '
 
2628
                 'rather than the one containing the working directory',
 
2629
            short_name='d',
 
2630
            type=unicode,
 
2631
            ),
2786
2632
    ]
2787
2633
 
2788
2634
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2790
2636
            uncommitted=False, pull=False,
2791
2637
            directory=None,
2792
2638
            ):
2793
 
        # This is actually a branch (or merge-directive) *location*.
2794
 
        location = branch
2795
 
        del branch
2796
 
 
 
2639
        from bzrlib.tag import _merge_tags_if_possible
 
2640
        other_revision_id = None
2797
2641
        if merge_type is None:
2798
2642
            merge_type = _mod_merge.Merge3Merger
2799
2643
 
2800
2644
        if directory is None: directory = u'.'
2801
 
        possible_transports = []
2802
 
        merger = None
2803
 
        allow_pending = True
2804
 
        verified = 'inapplicable'
 
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?)
2805
2652
        tree = WorkingTree.open_containing(directory)[0]
2806
2653
        change_reporter = delta._ChangeReporter(
2807
2654
            unversioned_filter=tree.is_ignored)
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
 
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
 
2925
2713
        if ((tree.branch.get_parent() is None or remember) and
2926
2714
            other_branch is not None):
2927
2715
            tree.branch.set_parent(other_branch.base)
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]
 
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]
2934
2724
        else:
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
 
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)
2964
2753
 
2965
2754
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2966
2755
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2974
2763
        mutter("%s", stored_location)
2975
2764
        if stored_location is None:
2976
2765
            raise errors.BzrCommandError("No location specified or remembered")
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))
 
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))
2981
2768
        return stored_location
2982
2769
 
2983
2770
 
2992
2779
    merge.  The difference is that remerge can (only) be run when there is a
2993
2780
    pending merge, and it lets you specify particular files.
2994
2781
 
2995
 
    :Examples:
 
2782
    Examples:
 
2783
 
 
2784
    $ bzr remerge --show-base
2996
2785
        Re-do the merge of all conflicted files, and show the base text in
2997
 
        conflict regions, in addition to the usual THIS and OTHER texts::
2998
 
      
2999
 
            bzr remerge --show-base
 
2786
        conflict regions, in addition to the usual THIS and OTHER texts.
3000
2787
 
 
2788
    $ bzr remerge --merge-type weave --reprocess foobar
3001
2789
        Re-do the merge of "foobar", using the weave merge algorithm, with
3002
 
        additional processing to reduce the size of conflict regions::
3003
 
      
3004
 
            bzr remerge --merge-type weave --reprocess foobar
 
2790
        additional processing to reduce the size of conflict regions.
3005
2791
    """
3006
2792
    takes_args = ['file*']
3007
 
    takes_options = [
3008
 
            'merge-type',
3009
 
            'reprocess',
3010
 
            Option('show-base',
3011
 
                   help="Show base revision text in conflicts."),
3012
 
            ]
 
2793
    takes_options = ['merge-type', 'reprocess',
 
2794
                     Option('show-base', help="Show base revision text in "
 
2795
                            "conflicts")]
3013
2796
 
3014
2797
    def run(self, file_list=None, merge_type=None, show_base=False,
3015
2798
            reprocess=False):
3024
2807
                                             " merges.  Not cherrypicking or"
3025
2808
                                             " multi-merges.")
3026
2809
            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])
3027
2814
            interesting_ids = None
3028
2815
            new_conflicts = []
3029
2816
            conflicts = tree.conflicts()
3054
2841
                    restore(tree.abspath(filename))
3055
2842
                except errors.NotConflicted:
3056
2843
                    pass
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()
 
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)
3075
2852
        finally:
3076
2853
            tree.unlock()
3077
2854
        if conflicts > 0:
3088
2865
    last committed revision is used.
3089
2866
 
3090
2867
    To remove only some changes, without reverting to a prior version, use
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.
 
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.
3094
2871
    
3095
2872
    By default, any files that have been manually changed will be backed up
3096
2873
    first.  (Files changed only by merge are not backed up.)  Backup files have
3100
2877
    from the target revision.  So you can use revert to "undelete" a file by
3101
2878
    name.  If you name a directory, all the contents of that directory will be
3102
2879
    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.
3115
2880
    """
3116
2881
 
3117
2882
    _see_also = ['cat', 'export']
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
 
        ]
 
2883
    takes_options = ['revision', 'no-backup']
3124
2884
    takes_args = ['file*']
3125
2885
 
3126
 
    def run(self, revision=None, no_backup=False, file_list=None,
3127
 
            forget_merges=None):
 
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")
 
2890
        else:
 
2891
            file_list = []
 
2892
        
3128
2893
        tree, file_list = tree_files(file_list)
3129
 
        if forget_merges:
3130
 
            tree.set_parent_ids(tree.get_parent_ids()[:1])
3131
 
        else:
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):
3136
2894
        if revision is None:
 
2895
            # FIXME should be tree.last_revision
3137
2896
            rev_id = tree.last_revision()
3138
2897
        elif len(revision) != 1:
3139
2898
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
3141
2900
            rev_id = revision[0].in_history(tree.branch).rev_id
3142
2901
        pb = ui.ui_factory.nested_progress_bar()
3143
2902
        try:
3144
 
            tree.revert(file_list,
 
2903
            tree.revert(file_list, 
3145
2904
                        tree.branch.repository.revision_tree(rev_id),
3146
2905
                        not no_backup, pb, report_changes=True)
3147
2906
        finally:
3163
2922
    """
3164
2923
 
3165
2924
    _see_also = ['topics']
3166
 
    takes_options = [
3167
 
            Option('long', 'Show help on all commands.'),
3168
 
            ]
 
2925
    takes_options = [Option('long', 'show help on all commands')]
3169
2926
    takes_args = ['topic?']
3170
2927
    aliases = ['?', '--help', '-?', '-h']
3171
2928
    
3214
2971
 
3215
2972
    _see_also = ['merge', 'pull']
3216
2973
    takes_args = ['other_branch?']
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
 
            ]
 
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
                     ]
3229
2985
    encoding_type = 'replace'
3230
2986
 
3231
2987
    @display_command
3233
2989
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
3234
2990
            show_ids=False, verbose=False, this=False, other=False):
3235
2991
        from bzrlib.missing import find_unmerged, iter_log_revisions
 
2992
        from bzrlib.log import log_formatter
3236
2993
 
3237
2994
        if this:
3238
2995
          mine_only = this
3244
3001
        if other_branch is None:
3245
3002
            other_branch = parent
3246
3003
            if other_branch is None:
3247
 
                raise errors.BzrCommandError("No peer location known"
3248
 
                                             " or specified.")
 
3004
                raise errors.BzrCommandError("No peer location known or specified.")
3249
3005
            display_url = urlutils.unescape_for_display(parent,
3250
3006
                                                        self.outf.encoding)
3251
 
            self.outf.write("Using last location: " + display_url + "\n")
 
3007
            print "Using last location: " + display_url
3252
3008
 
3253
3009
        remote_branch = Branch.open(other_branch)
3254
3010
        if remote_branch.base == local_branch.base:
3257
3013
        try:
3258
3014
            remote_branch.lock_read()
3259
3015
            try:
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)
 
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)
3265
3020
                lf = log_format(to_file=self.outf,
3266
3021
                                show_ids=show_ids,
3267
3022
                                show_timezone='original')
3269
3024
                    local_extra.reverse()
3270
3025
                    remote_extra.reverse()
3271
3026
                if local_extra and not theirs_only:
3272
 
                    self.outf.write("You have %d extra revision(s):\n" %
3273
 
                                    len(local_extra))
3274
 
                    for revision in iter_log_revisions(local_extra,
 
3027
                    print "You have %d extra revision(s):" % len(local_extra)
 
3028
                    for revision in iter_log_revisions(local_extra, 
3275
3029
                                        local_branch.repository,
3276
3030
                                        verbose):
3277
3031
                        lf.log_revision(revision)
3280
3034
                    printed_local = False
3281
3035
                if remote_extra and not mine_only:
3282
3036
                    if printed_local is True:
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,
 
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, 
3288
3041
                                        verbose):
3289
3042
                        lf.log_revision(revision)
3290
3043
                if not remote_extra and not local_extra:
3291
3044
                    status_code = 0
3292
 
                    self.outf.write("Branches are up to date.\n")
 
3045
                    print "Branches are up to date."
3293
3046
                else:
3294
3047
                    status_code = 1
3295
3048
            finally:
3307
3060
        return status_code
3308
3061
 
3309
3062
 
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
 
 
3326
3063
class cmd_plugins(Command):
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
 
 
 
3064
    """List plugins"""
 
3065
    hidden = True
3344
3066
    @display_command
3345
3067
    def run(self):
3346
3068
        import bzrlib.plugin
3347
3069
        from inspect import getdoc
3348
 
        for name, plugin in bzrlib.plugin.plugins().items():
3349
 
            print plugin.path(), "[%s]" % plugin.__version__
3350
 
            d = getdoc(plugin.module)
 
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)
3351
3079
            if d:
3352
3080
                print '\t', d.split('\n')[0]
3353
3081
 
3354
3082
 
3355
3083
class cmd_testament(Command):
3356
3084
    """Show testament (signing-form) of a revision."""
3357
 
    takes_options = [
3358
 
            'revision',
3359
 
            Option('long', help='Produce long-format testament.'),
3360
 
            Option('strict',
3361
 
                   help='Produce a strict-format testament.')]
 
3085
    takes_options = ['revision',
 
3086
                     Option('long', help='Produce long-format testament'), 
 
3087
                     Option('strict', help='Produce a strict-format'
 
3088
                            ' testament')]
3362
3089
    takes_args = ['branch?']
3363
3090
    @display_command
3364
3091
    def run(self, branch=u'.', revision=None, long=False, strict=False):
3397
3124
    #       with new uncommitted lines marked
3398
3125
    aliases = ['ann', 'blame', 'praise']
3399
3126
    takes_args = ['filename']
3400
 
    takes_options = [Option('all', help='Show annotations on all lines.'),
3401
 
                     Option('long', help='Show commit date in annotations.'),
 
3127
    takes_options = [Option('all', help='show annotations on all lines'),
 
3128
                     Option('long', help='show date in annotations'),
3402
3129
                     'revision',
3403
3130
                     'show-ids',
3404
3131
                     ]
3405
 
    encoding_type = 'exact'
3406
3132
 
3407
3133
    @display_command
3408
3134
    def run(self, filename, all=False, long=False, revision=None,
3419
3145
            else:
3420
3146
                revision_id = revision[0].in_history(branch).rev_id
3421
3147
            file_id = tree.path2id(relpath)
3422
 
            if file_id is None:
3423
 
                raise errors.NotVersionedError(filename)
3424
3148
            tree = branch.repository.revision_tree(revision_id)
3425
3149
            file_version = tree.inventory[file_id].revision
3426
 
            annotate_file(branch, file_version, file_id, long, all, self.outf,
 
3150
            annotate_file(branch, file_version, file_id, long, all, sys.stdout,
3427
3151
                          show_ids=show_ids)
3428
3152
        finally:
3429
3153
            branch.unlock()
3438
3162
    takes_options = ['revision']
3439
3163
    
3440
3164
    def run(self, revision_id_list=None, revision=None):
 
3165
        import bzrlib.gpg as gpg
3441
3166
        if revision_id_list is not None and revision is not None:
3442
3167
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3443
3168
        if revision_id_list is None and revision is None:
3444
3169
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3445
3170
        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
3454
3171
        gpg_strategy = gpg.GPGStrategy(b.get_config())
3455
3172
        if revision_id_list is not None:
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()
 
3173
            for revision_id in revision_id_list:
 
3174
                b.repository.sign_revision(revision_id, gpg_strategy)
3465
3175
        elif revision is not None:
3466
3176
            if len(revision) == 1:
3467
3177
                revno, rev_id = revision[0].in_history(b)
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()
 
3178
                b.repository.sign_revision(rev_id, gpg_strategy)
3476
3179
            elif len(revision) == 2:
3477
3180
                # are they both on rh- if so we can walk between them
3478
3181
                # might be nice to have a range helper for arbitrary
3483
3186
                    to_revno = b.revno()
3484
3187
                if from_revno is None or to_revno is None:
3485
3188
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
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()
 
3189
                for revno in range(from_revno, to_revno + 1):
 
3190
                    b.repository.sign_revision(b.get_rev_id(revno), 
 
3191
                                               gpg_strategy)
3496
3192
            else:
3497
3193
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
3498
3194
 
3551
3247
    --verbose will print out what is being removed.
3552
3248
    --dry-run will go through all the motions, but not actually
3553
3249
    remove anything.
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
 
 
 
3250
    
3559
3251
    In the future, uncommit will create a revision bundle, which can then
3560
3252
    be re-applied.
3561
3253
    """
3566
3258
    # information in shared branches as well.
3567
3259
    _see_also = ['commit']
3568
3260
    takes_options = ['verbose', 'revision',
3569
 
                    Option('dry-run', help='Don\'t actually make changes.'),
 
3261
                    Option('dry-run', help='Don\'t actually make changes'),
3570
3262
                    Option('force', help='Say yes to all questions.')]
3571
3263
    takes_args = ['location?']
3572
3264
    aliases = []
3573
 
    encoding_type = 'replace'
3574
3265
 
3575
3266
    def run(self, location=None,
3576
3267
            dry_run=False, verbose=False,
3577
3268
            revision=None, force=False):
 
3269
        from bzrlib.log import log_formatter, show_log
 
3270
        import sys
 
3271
        from bzrlib.uncommit import uncommit
 
3272
 
3578
3273
        if location is None:
3579
3274
            location = u'.'
3580
3275
        control, relpath = bzrdir.BzrDir.open_containing(location)
3585
3280
            tree = None
3586
3281
            b = control.open_branch()
3587
3282
 
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
 
 
3606
3283
        rev_id = None
3607
3284
        if revision is None:
3608
 
            revno = last_revno
3609
 
            rev_id = last_rev_id
 
3285
            revno = b.revno()
3610
3286
        else:
3611
3287
            # 'bzr uncommit -r 10' actually means uncommit
3612
3288
            # so that the final tree is at revno 10.
3613
3289
            # but bzrlib.uncommit.uncommit() actually uncommits
3614
3290
            # the revisions that are supplied.
3615
3291
            # So we need to offset it by one
3616
 
            revno = revision[0].in_history(b).revno + 1
3617
 
            if revno <= last_revno:
3618
 
                rev_id = b.get_rev_id(revno)
 
3292
            revno = revision[0].in_history(b).revno+1
3619
3293
 
3620
 
        if rev_id is None or _mod_revision.is_null(rev_id):
 
3294
        if revno <= b.revno():
 
3295
            rev_id = b.get_rev_id(revno)
 
3296
        if rev_id is None:
3621
3297
            self.outf.write('No revisions to uncommit.\n')
3622
3298
            return 1
3623
3299
 
3630
3306
                 verbose=False,
3631
3307
                 direction='forward',
3632
3308
                 start_revision=revno,
3633
 
                 end_revision=last_revno)
 
3309
                 end_revision=b.revno())
3634
3310
 
3635
3311
        if dry_run:
3636
3312
            print 'Dry-run, pretending to remove the above revisions.'
3645
3321
                    return 0
3646
3322
 
3647
3323
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3648
 
                 revno=revno)
 
3324
                revno=revno)
3649
3325
 
3650
3326
 
3651
3327
class cmd_break_lock(Command):
3656
3332
 
3657
3333
    You can get information on what locks are open via the 'bzr info' command.
3658
3334
    
3659
 
    :Examples:
 
3335
    example:
3660
3336
        bzr break-lock
3661
3337
    """
3662
3338
    takes_args = ['location?']
3692
3368
 
3693
3369
    takes_options = [
3694
3370
        Option('inet',
3695
 
               help='Serve on stdin/out for use from inetd or sshd.'),
 
3371
               help='serve on stdin/out for use from inetd or sshd'),
3696
3372
        Option('port',
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 '
 
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 '
3700
3376
                    '4155.',
3701
3377
               type=str),
3702
3378
        Option('directory',
3703
 
               help='Serve contents of this directory.',
 
3379
               help='serve contents of directory',
3704
3380
               type=unicode),
3705
3381
        Option('allow-writes',
3706
 
               help='By default the server is a readonly server.  Supplying '
 
3382
               help='By default the server is a readonly server. Supplying '
3707
3383
                    '--allow-writes enables write access to the contents of '
3708
 
                    'the served directory and below.'
 
3384
                    'the served directory and below. '
3709
3385
                ),
3710
3386
        ]
3711
3387
 
3712
3388
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
3713
 
        from bzrlib import lockdir
3714
3389
        from bzrlib.smart import medium, server
3715
3390
        from bzrlib.transport import get_transport
3716
3391
        from bzrlib.transport.chroot import ChrootServer
 
3392
        from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3717
3393
        if directory is None:
3718
3394
            directory = os.getcwd()
3719
3395
        url = urlutils.local_path_to_url(directory)
3726
3402
            smart_server = medium.SmartServerPipeStreamMedium(
3727
3403
                sys.stdin, sys.stdout, t)
3728
3404
        else:
3729
 
            host = medium.BZR_DEFAULT_INTERFACE
 
3405
            host = BZR_DEFAULT_INTERFACE
3730
3406
            if port is None:
3731
 
                port = medium.BZR_DEFAULT_PORT
 
3407
                port = BZR_DEFAULT_PORT
3732
3408
            else:
3733
3409
                if ':' in port:
3734
3410
                    host, port = port.split(':')
3741
3417
        # be changed with care though, as we dont want to use bandwidth sending
3742
3418
        # progress over stderr to smart server clients!
3743
3419
        old_factory = ui.ui_factory
3744
 
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3745
3420
        try:
3746
3421
            ui.ui_factory = ui.SilentUIFactory()
3747
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3748
3422
            smart_server.serve()
3749
3423
        finally:
3750
3424
            ui.ui_factory = old_factory
3751
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
3752
3425
 
3753
3426
 
3754
3427
class cmd_join(Command):
3774
3447
 
3775
3448
    _see_also = ['split']
3776
3449
    takes_args = ['tree']
3777
 
    takes_options = [
3778
 
            Option('reference', help='Join by reference.'),
3779
 
            ]
 
3450
    takes_options = [Option('reference', 'join by reference')]
3780
3451
    hidden = True
3781
3452
 
3782
3453
    def run(self, tree, reference=False):
3806
3477
 
3807
3478
 
3808
3479
class cmd_split(Command):
3809
 
    """Split a subdirectory of a tree into a separate tree.
 
3480
    """Split a tree into two trees.
3810
3481
 
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'.
 
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.
3814
3485
 
3815
3486
    The TREE argument should be a subdirectory of a working tree.  That
3816
3487
    subdirectory will be converted into an independent tree, with its own
3817
3488
    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".
3818
3490
    """
3819
3491
 
3820
 
    # join is not un-hidden yet
3821
 
    #_see_also = ['join']
 
3492
    _see_also = ['join']
3822
3493
    takes_args = ['tree']
3823
3494
 
 
3495
    hidden = True
 
3496
 
3824
3497
    def run(self, tree):
3825
3498
        containing_tree, subdir = WorkingTree.open_containing(tree)
3826
3499
        sub_id = containing_tree.path2id(subdir)
3832
3505
            raise errors.UpgradeRequired(containing_tree.branch.base)
3833
3506
 
3834
3507
 
 
3508
 
3835
3509
class cmd_merge_directive(Command):
3836
3510
    """Generate a merge directive for auto-merge tools.
3837
3511
 
3851
3525
 
3852
3526
    takes_args = ['submit_branch?', 'public_branch?']
3853
3527
 
3854
 
    hidden = True
3855
 
 
3856
 
    _see_also = ['send']
3857
 
 
3858
3528
    takes_options = [
3859
3529
        RegistryOption.from_kwargs('patch-type',
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',
 
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',
3868
3536
        Option('mail-to', type=str,
3869
 
            help='Instead of printing the directive, email to this address.'),
 
3537
            help='Instead of printing the directive, email to this address'),
3870
3538
        Option('message', type=str, short_name='m',
3871
 
            help='Message to use when committing this merge.')
 
3539
            help='Message to use when committing this merge')
3872
3540
        ]
3873
3541
 
3874
 
    encoding_type = 'exact'
3875
 
 
3876
3542
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3877
3543
            sign=False, revision=None, mail_to=None, message=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]
 
3544
        if patch_type == 'plain':
 
3545
            patch_type = None
3884
3546
        branch = Branch.open('.')
3885
3547
        stored_submit_branch = branch.get_submit_branch()
3886
3548
        if submit_branch is None:
3898
3560
            public_branch = stored_public_branch
3899
3561
        elif stored_public_branch is None:
3900
3562
            branch.set_public_branch(public_branch)
3901
 
        if not include_bundle and public_branch is None:
 
3563
        if patch_type != "bundle" and public_branch is None:
3902
3564
            raise errors.BzrCommandError('No public branch specified or'
3903
3565
                                         ' known')
3904
 
        base_revision_id = None
3905
3566
        if revision is not None:
3906
 
            if len(revision) > 2:
 
3567
            if len(revision) != 1:
3907
3568
                raise errors.BzrCommandError('bzr merge-directive takes '
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)
 
3569
                    'exactly one revision identifier')
 
3570
            else:
 
3571
                revision_id = revision[0].in_history(branch).rev_id
3913
3572
        else:
3914
3573
            revision_id = branch.last_revision()
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(
 
3574
        directive = merge_directive.MergeDirective.from_objects(
3919
3575
            branch.repository, revision_id, time.time(),
3920
3576
            osutils.local_time_offset(), submit_branch,
3921
 
            public_branch=public_branch, include_patch=include_patch,
3922
 
            include_bundle=include_bundle, message=message,
3923
 
            base_revision_id=base_revision_id)
 
3577
            public_branch=public_branch, patch_type=patch_type,
 
3578
            message=message)
3924
3579
        if mail_to is None:
3925
3580
            if sign:
3926
3581
                self.outf.write(directive.to_signed(branch))
3928
3583
                self.outf.writelines(directive.to_lines())
3929
3584
        else:
3930
3585
            message = directive.to_email(mail_to, branch, sign)
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)
 
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())
4187
3592
 
4188
3593
 
4189
3594
class cmd_tag(Command):
4190
 
    """Create, remove or modify a tag naming a revision.
 
3595
    """Create a tag naming a revision.
4191
3596
    
4192
3597
    Tags give human-meaningful names to revisions.  Commands that take a -r
4193
3598
    (--revision) option can be given -rtag:X, where X is any previously
4212
3617
            type=unicode,
4213
3618
            ),
4214
3619
        Option('force',
4215
 
            help='Replace existing tags.',
 
3620
            help='Replace existing tags',
4216
3621
            ),
4217
3622
        'revision',
4218
3623
        ]
4249
3654
class cmd_tags(Command):
4250
3655
    """List tags.
4251
3656
 
4252
 
    This command shows a table of tag names and the revisions they reference.
 
3657
    This tag shows a table of tag names and the revisions they reference.
4253
3658
    """
4254
3659
 
4255
3660
    _see_also = ['tag']
4256
3661
    takes_options = [
4257
3662
        Option('directory',
4258
 
            help='Branch whose tags should be displayed.',
 
3663
            help='Branch whose tags should be displayed',
4259
3664
            short_name='d',
4260
3665
            type=unicode,
4261
3666
            ),
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',
4268
3667
    ]
4269
3668
 
4270
3669
    @display_command
4271
3670
    def run(self,
4272
3671
            directory='.',
4273
 
            sort='alpha',
4274
 
            show_ids=False,
4275
3672
            ):
4276
3673
        branch, relpath = Branch.open_containing(directory)
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
 
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.')
4287
3759
                else:
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'))
 
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
4375
3773
 
4376
3774
 
4377
3775
def _create_prefix(cur_transport):
4380
3778
    while True:
4381
3779
        new_transport = cur_transport.clone('..')
4382
3780
        if new_transport.base == cur_transport.base:
4383
 
            raise errors.BzrCommandError(
4384
 
                "Failed to create path prefix for %s."
4385
 
                % cur_transport.base)
 
3781
            raise errors.BzrCommandError("Failed to create path"
 
3782
                                         " prefix for %s."
 
3783
                                         % location)
4386
3784
        try:
4387
3785
            new_transport.mkdir('.')
4388
3786
        except errors.NoSuchFile:
4390
3788
            cur_transport = new_transport
4391
3789
        else:
4392
3790
            break
 
3791
 
4393
3792
    # Now we only need to create child directories
4394
3793
    while needed:
4395
3794
        cur_transport = needed.pop()
4396
3795
        cur_transport.ensure_base()
4397
3796
 
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
 
3797
# Compatibility
 
3798
merge = _merge_helper
4425
3799
 
4426
3800
 
4427
3801
# these get imported and then picked up by the scan for cmd_*
4431
3805
# details were needed.
4432
3806
from bzrlib.cmd_version_info import cmd_version_info
4433
3807
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
4434
 
from bzrlib.bundle.commands import (
4435
 
    cmd_bundle_info,
4436
 
    )
 
3808
from bzrlib.bundle.commands import cmd_bundle_revisions
4437
3809
from bzrlib.sign_my_commits import cmd_sign_my_commits
4438
3810
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
4439
3811
        cmd_weave_plan_merge, cmd_weave_merge_text