~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Clean up the lock.py code to use less indenting, and conform to better coding practise.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
lazy_import(globals(), """
24
24
import codecs
25
25
import errno
 
26
import smtplib
26
27
import sys
27
28
import tempfile
28
29
import time
30
31
import bzrlib
31
32
from bzrlib import (
32
33
    branch,
33
 
    bugtracker,
34
34
    bundle,
35
35
    bzrdir,
36
36
    delta,
44
44
    osutils,
45
45
    registry,
46
46
    repository,
47
 
    revision as _mod_revision,
48
 
    revisionspec,
49
47
    symbol_versioning,
50
48
    transport,
51
49
    tree as _mod_tree,
53
51
    urlutils,
54
52
    )
55
53
from bzrlib.branch import Branch
 
54
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
56
55
from bzrlib.conflicts import ConflictList
 
56
from bzrlib.revision import common_ancestor
57
57
from bzrlib.revisionspec import RevisionSpec
58
 
from bzrlib.smtp_connection import SMTPConnection
59
58
from bzrlib.workingtree import WorkingTree
60
59
""")
61
60
 
62
61
from bzrlib.commands import Command, display_command
63
 
from bzrlib.option import ListOption, Option, RegistryOption
 
62
from bzrlib.option import Option, RegistryOption
64
63
from bzrlib.progress import DummyProgress, ProgressPhase
65
64
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
66
65
 
149
148
    unknown
150
149
        Not versioned and not matching an ignore pattern.
151
150
 
152
 
    To see ignored files use 'bzr ignored'.  For details on the
 
151
    To see ignored files use 'bzr ignored'.  For details in the
153
152
    changes to file texts, use 'bzr diff'.
154
153
    
155
154
    --short gives a status flags for each item, similar to the SVN's status
156
155
    command.
157
156
 
 
157
    Column 1: versioning / renames
 
158
      + File versioned
 
159
      - File unversioned
 
160
      R File renamed
 
161
      ? File unknown
 
162
      C File has conflicts
 
163
      P Entry for a pending merge (not a file)
 
164
 
 
165
    Column 2: Contents
 
166
      N File created
 
167
      D File deleted
 
168
      K File kind changed
 
169
      M File modified
 
170
 
 
171
    Column 3: Execute
 
172
      * The execute bit was changed
 
173
 
158
174
    If no arguments are specified, the status of the entire working
159
175
    directory is shown.  Otherwise, only the status of the specified
160
176
    files or directories is reported.  If a directory is given, status
167
183
    # TODO: --no-recurse, --recurse options
168
184
    
169
185
    takes_args = ['file*']
170
 
    takes_options = ['show-ids', 'revision',
171
 
                     Option('short', help='Give short SVN-style status lines.'),
172
 
                     Option('versioned', help='Only show versioned files.')]
 
186
    takes_options = ['show-ids', 'revision', 'short',
 
187
                     Option('versioned', help='Only show versioned files')]
173
188
    aliases = ['st', 'stat']
174
189
 
175
190
    encoding_type = 'replace'
176
 
    _see_also = ['diff', 'revert', 'status-flags']
177
191
    
178
192
    @display_command
179
193
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
203
217
    @display_command
204
218
    def run(self, revision_id=None, revision=None):
205
219
 
206
 
        revision_id = osutils.safe_revision_id(revision_id, warn=False)
207
220
        if revision_id is not None and revision is not None:
208
221
            raise errors.BzrCommandError('You can only supply one of'
209
222
                                         ' revision_id or --revision')
229
242
 
230
243
    Since a lightweight checkout is little more than a working tree
231
244
    this will refuse to run against one.
232
 
 
233
 
    To re-create the working tree, use "bzr checkout".
234
245
    """
235
 
    _see_also = ['checkout', 'working-trees']
236
246
 
237
247
    takes_args = ['location?']
238
248
 
262
272
    This is equal to the number of revisions on this branch.
263
273
    """
264
274
 
265
 
    _see_also = ['info']
266
275
    takes_args = ['location?']
267
276
 
268
277
    @display_command
287
296
        if revision_info_list is not None:
288
297
            for rev in revision_info_list:
289
298
                revs.append(RevisionSpec.from_string(rev))
290
 
 
291
 
        b = Branch.open_containing(u'.')[0]
292
 
 
293
299
        if len(revs) == 0:
294
 
            revs.append(RevisionSpec.from_string('-1'))
 
300
            raise errors.BzrCommandError('You must supply a revision identifier')
 
301
 
 
302
        b = WorkingTree.open_containing(u'.')[0].branch
295
303
 
296
304
        for rev in revs:
297
305
            revinfo = rev.in_history(b)
298
306
            if revinfo.revno is None:
299
 
                dotted_map = b.get_revision_id_to_revno_map()
300
 
                revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
301
 
                print '%s %s' % (revno, revinfo.rev_id)
 
307
                print '     %s' % revinfo.rev_id
302
308
            else:
303
309
                print '%4d %s' % (revinfo.revno, revinfo.rev_id)
304
310
 
331
337
 
332
338
    --file-ids-from will try to use the file ids from the supplied path.
333
339
    It looks up ids trying to find a matching parent directory with the
334
 
    same filename, and then by pure path. This option is rarely needed
335
 
    but can be useful when adding the same logical file into two
336
 
    branches that will be merged later (without showing the two different
337
 
    adds as a conflict). It is also useful when merging another project
338
 
    into a subdirectory of this one.
 
340
    same filename, and then by pure path.
339
341
    """
340
342
    takes_args = ['file*']
341
 
    takes_options = [
342
 
        Option('no-recurse',
343
 
               help="Don't recursively add the contents of directories."),
344
 
        Option('dry-run',
345
 
               help="Show what would be done, but don't actually do anything."),
346
 
        'verbose',
347
 
        Option('file-ids-from',
348
 
               type=unicode,
349
 
               help='Lookup file ids from this tree.'),
350
 
        ]
 
343
    takes_options = ['no-recurse', 'dry-run', 'verbose',
 
344
                     Option('file-ids-from', type=unicode,
 
345
                            help='Lookup file ids from here')]
351
346
    encoding_type = 'replace'
352
 
    _see_also = ['remove']
353
347
 
354
348
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
355
349
            file_ids_from=None):
374
368
        if base_tree:
375
369
            base_tree.lock_read()
376
370
        try:
377
 
            file_list = self._maybe_expand_globs(file_list)
378
 
            if file_list:
379
 
                tree = WorkingTree.open_containing(file_list[0])[0]
380
 
            else:
381
 
                tree = WorkingTree.open_containing(u'.')[0]
382
 
            added, ignored = tree.smart_add(file_list, not
383
 
                no_recurse, action=action, save=not dry_run)
 
371
            added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
 
372
                action=action, save=not dry_run)
384
373
        finally:
385
374
            if base_tree is not None:
386
375
                base_tree.unlock()
439
428
 
440
429
    It is also possible to restrict the list of files to a specific
441
430
    set. For example: bzr inventory --show-ids this/file
 
431
 
 
432
    See also: bzr ls
442
433
    """
443
434
 
444
435
    hidden = True
445
 
    _see_also = ['ls']
446
 
    takes_options = [
447
 
        'revision',
448
 
        'show-ids',
449
 
        Option('kind',
450
 
               help='List entries of a particular kind: file, directory, symlink.',
451
 
               type=unicode),
452
 
        ]
 
436
 
 
437
    takes_options = ['revision', 'show-ids', 'kind']
 
438
 
453
439
    takes_args = ['file*']
454
440
 
455
441
    @display_command
456
442
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
457
443
        if kind and kind not in ['file', 'directory', 'symlink']:
458
 
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
 
444
            raise errors.BzrCommandError('invalid kind specified')
459
445
 
460
446
        work_tree, file_list = tree_files(file_list)
461
447
        work_tree.lock_read()
519
505
    """
520
506
 
521
507
    takes_args = ['names*']
522
 
    takes_options = [Option("after", help="Move only the bzr identifier"
523
 
        " of the file, because the file has already been moved."),
524
 
        ]
 
508
    takes_options = [Option("after", help="move only the bzr identifier"
 
509
        " of the file (file has already been moved). Use this flag if"
 
510
        " bzr is not able to detect this itself.")]
525
511
    aliases = ['move', 'rename']
526
512
    encoding_type = 'replace'
527
513
 
566
552
    location can be accessed.
567
553
    """
568
554
 
569
 
    _see_also = ['push', 'update', 'status-flags']
570
555
    takes_options = ['remember', 'overwrite', 'revision', 'verbose',
571
556
        Option('directory',
572
 
            help='Branch to pull into, '
573
 
                 'rather than the one containing the working directory.',
 
557
            help='branch to pull into, '
 
558
                 'rather than the one containing the working directory',
574
559
            short_name='d',
575
560
            type=unicode,
576
561
            ),
581
566
    def run(self, location=None, remember=False, overwrite=False,
582
567
            revision=None, verbose=False,
583
568
            directory=None):
 
569
        from bzrlib.tag import _merge_tags_if_possible
584
570
        # FIXME: too much stuff is in the command class
585
 
        revision_id = None
586
 
        mergeable = None
587
571
        if directory is None:
588
572
            directory = u'.'
589
573
        try:
593
577
            tree_to = None
594
578
            branch_to = Branch.open_containing(directory)[0]
595
579
 
 
580
        reader = None
596
581
        if location is not None:
597
 
            mergeable, location_transport = _get_mergeable_helper(location)
 
582
            try:
 
583
                reader = bundle.read_bundle_from_url(location)
 
584
            except errors.NotABundle:
 
585
                pass # Continue on considering this url a Branch
598
586
 
599
587
        stored_loc = branch_to.get_parent()
600
588
        if location is None:
606
594
                        self.outf.encoding)
607
595
                self.outf.write("Using saved location: %s\n" % display_url)
608
596
                location = stored_loc
609
 
                location_transport = transport.get_transport(location)
610
597
 
611
 
        if mergeable is not None:
612
 
            if revision is not None:
613
 
                raise errors.BzrCommandError(
614
 
                    'Cannot use -r with merge directives or bundles')
615
 
            mergeable.install_revisions(branch_to.repository)
616
 
            base_revision_id, revision_id, verified = \
617
 
                mergeable.get_merge_request(branch_to.repository)
 
598
        if reader is not None:
 
599
            install_bundle(branch_to.repository, reader)
618
600
            branch_from = branch_to
619
601
        else:
620
 
            branch_from = Branch.open_from_transport(location_transport)
 
602
            branch_from = Branch.open(location)
621
603
 
622
604
            if branch_to.get_parent() is None or remember:
623
605
                branch_to.set_parent(branch_from.base)
624
606
 
625
 
        if revision is not None:
626
 
            if len(revision) == 1:
627
 
                revision_id = revision[0].in_history(branch_from).rev_id
628
 
            else:
629
 
                raise errors.BzrCommandError(
630
 
                    'bzr pull --revision takes one value.')
 
607
        rev_id = None
 
608
        if revision is None:
 
609
            if reader is not None:
 
610
                rev_id = reader.target
 
611
        elif len(revision) == 1:
 
612
            rev_id = revision[0].in_history(branch_from).rev_id
 
613
        else:
 
614
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
631
615
 
632
 
        if verbose:
633
 
            old_rh = branch_to.revision_history()
 
616
        old_rh = branch_to.revision_history()
634
617
        if tree_to is not None:
635
 
            result = tree_to.pull(branch_from, overwrite, revision_id,
 
618
            result = tree_to.pull(branch_from, overwrite, rev_id,
636
619
                delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
637
620
        else:
638
 
            result = branch_to.pull(branch_from, overwrite, revision_id)
 
621
            result = branch_to.pull(branch_from, overwrite, rev_id)
639
622
 
640
623
        result.report(self.outf)
641
624
        if verbose:
642
625
            from bzrlib.log import show_changed_revisions
643
626
            new_rh = branch_to.revision_history()
644
 
            show_changed_revisions(branch_to, old_rh, new_rh,
645
 
                                   to_file=self.outf)
 
627
            show_changed_revisions(branch_to, old_rh, new_rh, to_file=self.outf)
646
628
 
647
629
 
648
630
class cmd_push(Command):
671
653
    location can be accessed.
672
654
    """
673
655
 
674
 
    _see_also = ['pull', 'update', 'working-trees']
675
656
    takes_options = ['remember', 'overwrite', 'verbose',
676
657
        Option('create-prefix',
677
658
               help='Create the path leading up to the branch '
678
 
                    'if it does not already exist.'),
 
659
                    'if it does not already exist'),
679
660
        Option('directory',
680
 
            help='Branch to push from, '
681
 
                 'rather than the one containing the working directory.',
 
661
            help='branch to push from, '
 
662
                 'rather than the one containing the working directory',
682
663
            short_name='d',
683
664
            type=unicode,
684
665
            ),
685
666
        Option('use-existing-dir',
686
667
               help='By default push will fail if the target'
687
668
                    ' directory exists, but does not already'
688
 
                    ' have a control directory.  This flag will'
 
669
                    ' have a control directory. This flag will'
689
670
                    ' allow push to proceed.'),
690
671
        ]
691
672
    takes_args = ['location?']
711
692
                location = stored_loc
712
693
 
713
694
        to_transport = transport.get_transport(location)
 
695
        location_url = to_transport.base
714
696
 
715
697
        br_to = repository_to = dir_to = None
716
698
        try:
732
714
                # Found a branch, so we must have found a repository
733
715
                repository_to = br_to.repository
734
716
        push_result = None
735
 
        if verbose:
736
 
            old_rh = []
 
717
        old_rh = []
737
718
        if dir_to is None:
738
719
            # The destination doesn't exist; create it.
739
720
            # XXX: Refactor the create_prefix/no_create_prefix code into a
753
734
                        "\nYou may supply --create-prefix to create all"
754
735
                        " leading parent directories."
755
736
                        % location)
756
 
                _create_prefix(to_transport)
757
 
 
 
737
 
 
738
                cur_transport = to_transport
 
739
                needed = [cur_transport]
 
740
                # Recurse upwards until we can create a directory successfully
 
741
                while True:
 
742
                    new_transport = cur_transport.clone('..')
 
743
                    if new_transport.base == cur_transport.base:
 
744
                        raise errors.BzrCommandError("Failed to create path"
 
745
                                                     " prefix for %s."
 
746
                                                     % location)
 
747
                    try:
 
748
                        new_transport.mkdir('.')
 
749
                    except errors.NoSuchFile:
 
750
                        needed.append(new_transport)
 
751
                        cur_transport = new_transport
 
752
                    else:
 
753
                        break
 
754
 
 
755
                # Now we only need to create child directories
 
756
                while needed:
 
757
                    cur_transport = needed.pop()
 
758
                    cur_transport.mkdir('.')
 
759
            
758
760
            # Now the target directory exists, but doesn't have a .bzr
759
761
            # directory. So we need to create it, along with any work to create
760
762
            # all of the dependent branches, etc.
761
 
            dir_to = br_from.bzrdir.clone_on_transport(to_transport,
 
763
            dir_to = br_from.bzrdir.clone(location_url,
762
764
                revision_id=br_from.last_revision())
763
765
            br_to = dir_to.open_branch()
764
766
            # TODO: Some more useful message about what was copied
789
791
            # we don't need to successfully push because of possible divergence.
790
792
            if br_from.get_push_location() is None or remember:
791
793
                br_from.set_push_location(br_to.base)
792
 
            if verbose:
793
 
                old_rh = br_to.revision_history()
 
794
            old_rh = br_to.revision_history()
794
795
            try:
795
796
                try:
796
797
                    tree_to = dir_to.open_workingtree()
797
798
                except errors.NotLocalUrl:
798
 
                    warning("This transport does not update the working " 
799
 
                            "tree of: %s. See 'bzr help working-trees' for "
800
 
                            "more information." % br_to.base)
 
799
                    warning('This transport does not update the working '
 
800
                            'tree of: %s' % (br_to.base,))
801
801
                    push_result = br_from.push(br_to, overwrite)
802
802
                except errors.NoWorkingTree:
803
803
                    push_result = br_from.push(br_to, overwrite)
831
831
 
832
832
    If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
833
833
    be used.  In other words, "branch ../foo/bar" will attempt to create ./bar.
834
 
    If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
835
 
    is derived from the FROM_LOCATION by stripping a leading scheme or drive
836
 
    identifier, if any. For example, "branch lp:foo-bar" will attempt to
837
 
    create ./foo-bar.
838
834
 
839
835
    To retrieve the branch as of a particular revision, supply the --revision
840
836
    parameter, as in "branch foo/bar -r 5".
 
837
 
 
838
    --basis is to speed up branching from remote branches.  When specified, it
 
839
    copies all the file-contents, inventory and revision data from the basis
 
840
    branch before copying anything from the remote branch.
841
841
    """
842
 
 
843
 
    _see_also = ['checkout']
844
842
    takes_args = ['from_location', 'to_location?']
845
 
    takes_options = ['revision']
 
843
    takes_options = ['revision', 'basis']
846
844
    aliases = ['get', 'clone']
847
845
 
848
 
    def run(self, from_location, to_location=None, revision=None):
 
846
    def run(self, from_location, to_location=None, revision=None, basis=None):
849
847
        from bzrlib.tag import _merge_tags_if_possible
850
848
        if revision is None:
851
849
            revision = [None]
856
854
        br_from = Branch.open(from_location)
857
855
        br_from.lock_read()
858
856
        try:
 
857
            if basis is not None:
 
858
                basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
 
859
            else:
 
860
                basis_dir = None
859
861
            if len(revision) == 1 and revision[0] is not None:
860
862
                revision_id = revision[0].in_history(br_from)[1]
861
863
            else:
864
866
                # RBC 20060209
865
867
                revision_id = br_from.last_revision()
866
868
            if to_location is None:
867
 
                to_location = urlutils.derive_to_location(from_location)
 
869
                to_location = os.path.basename(from_location.rstrip("/\\"))
868
870
                name = None
869
871
            else:
870
872
                name = os.path.basename(to_location) + '\n'
880
882
                                             % to_location)
881
883
            try:
882
884
                # preserve whatever source format we have.
883
 
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
884
 
                                            possible_transports=[to_transport])
 
885
                dir = br_from.bzrdir.sprout(to_transport.base,
 
886
                        revision_id, basis_dir)
885
887
                branch = dir.open_branch()
886
888
            except errors.NoSuchRevision:
887
889
                to_transport.delete_tree('.')
888
890
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
889
891
                raise errors.BzrCommandError(msg)
 
892
            except errors.UnlistableBranch:
 
893
                osutils.rmtree(to_location)
 
894
                msg = "The branch %s cannot be used as a --basis" % (basis,)
 
895
                raise errors.BzrCommandError(msg)
890
896
            if name:
891
897
                branch.control_files.put_utf8('branch-name', name)
892
898
            _merge_tags_if_possible(br_from, branch)
905
911
    
906
912
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
907
913
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
908
 
    If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
909
 
    is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
910
 
    identifier, if any. For example, "checkout lp:foo-bar" will attempt to
911
 
    create ./foo-bar.
912
914
 
913
915
    To retrieve the branch as of a particular revision, supply the --revision
914
916
    parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
915
917
    out of date [so you cannot commit] but it may be useful (i.e. to examine old
916
918
    code.)
 
919
 
 
920
    --basis is to speed up checking out from remote branches.  When specified, it
 
921
    uses the inventory and file contents from the basis branch in preference to the
 
922
    branch being checked out.
 
923
 
 
924
    See "help checkouts" for more information on checkouts.
917
925
    """
918
 
 
919
 
    _see_also = ['checkouts', 'branch']
920
926
    takes_args = ['branch_location?', 'to_location?']
921
 
    takes_options = ['revision',
 
927
    takes_options = ['revision', # , 'basis']
922
928
                     Option('lightweight',
923
 
                            help="Perform a lightweight checkout.  Lightweight "
 
929
                            help="perform a lightweight checkout. Lightweight "
924
930
                                 "checkouts depend on access to the branch for "
925
 
                                 "every operation.  Normal checkouts can perform "
 
931
                                 "every operation. Normal checkouts can perform "
926
932
                                 "common operations like diff and status without "
927
933
                                 "such access, and also support local commits."
928
934
                            ),
929
935
                     ]
930
936
    aliases = ['co']
931
937
 
932
 
    def run(self, branch_location=None, to_location=None, revision=None,
 
938
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
933
939
            lightweight=False):
934
940
        if revision is None:
935
941
            revision = [None]
941
947
            to_location = branch_location
942
948
        source = Branch.open(branch_location)
943
949
        if len(revision) == 1 and revision[0] is not None:
944
 
            revision_id = _mod_revision.ensure_null(
945
 
                revision[0].in_history(source)[1])
 
950
            revision_id = revision[0].in_history(source)[1]
946
951
        else:
947
952
            revision_id = None
948
953
        if to_location is None:
949
 
            to_location = urlutils.derive_to_location(branch_location)
 
954
            to_location = os.path.basename(branch_location.rstrip("/\\"))
950
955
        # if the source and to_location are the same, 
951
956
        # and there is no working tree,
952
957
        # then reconstitute a branch
955
960
            try:
956
961
                source.bzrdir.open_workingtree()
957
962
            except errors.NoWorkingTree:
958
 
                source.bzrdir.create_workingtree(revision_id)
 
963
                source.bzrdir.create_workingtree()
959
964
                return
960
965
        try:
961
966
            os.mkdir(to_location)
977
982
    # TODO: Option to show renames between two historical versions.
978
983
 
979
984
    # TODO: Only show renames under dir, rather than in the whole branch.
980
 
    _see_also = ['status']
981
985
    takes_args = ['dir?']
982
986
 
983
987
    @display_command
1010
1014
    If you want to discard your local changes, you can just do a 
1011
1015
    'bzr revert' instead of 'bzr commit' after the update.
1012
1016
    """
1013
 
 
1014
 
    _see_also = ['pull', 'working-trees', 'status-flags']
1015
1017
    takes_args = ['dir?']
1016
1018
    aliases = ['up']
1017
1019
 
1024
1026
            tree.lock_tree_write()
1025
1027
        try:
1026
1028
            existing_pending_merges = tree.get_parent_ids()[1:]
1027
 
            last_rev = _mod_revision.ensure_null(tree.last_revision())
1028
 
            if last_rev == _mod_revision.ensure_null(
1029
 
                tree.branch.last_revision()):
 
1029
            last_rev = tree.last_revision()
 
1030
            if last_rev == tree.branch.last_revision():
1030
1031
                # may be up to date, check master too.
1031
1032
                master = tree.branch.get_master_branch()
1032
 
                if master is None or last_rev == _mod_revision.ensure_null(
1033
 
                    master.last_revision()):
 
1033
                if master is None or last_rev == master.last_revision():
1034
1034
                    revno = tree.branch.revision_id_to_revno(last_rev)
1035
1035
                    note("Tree is up to date at revision %d." % (revno,))
1036
1036
                    return 0
1037
 
            conflicts = tree.update(delta._ChangeReporter(
1038
 
                                        unversioned_filter=tree.is_ignored))
1039
 
            revno = tree.branch.revision_id_to_revno(
1040
 
                _mod_revision.ensure_null(tree.last_revision()))
 
1037
            conflicts = tree.update()
 
1038
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
1041
1039
            note('Updated to revision %d.' % (revno,))
1042
1040
            if tree.get_parent_ids()[1:] != existing_pending_merges:
1043
1041
                note('Your local commits will now show as pending merges with '
1059
1057
 
1060
1058
    Branches and working trees will also report any missing revisions.
1061
1059
    """
1062
 
    _see_also = ['revno', 'working-trees', 'repositories']
1063
1060
    takes_args = ['location?']
1064
1061
    takes_options = ['verbose']
1065
1062
 
1066
1063
    @display_command
1067
 
    def run(self, location=None, verbose=0):
 
1064
    def run(self, location=None, verbose=False):
1068
1065
        from bzrlib.info import show_bzrdir_info
1069
1066
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1070
1067
                         verbose=verbose)
1071
1068
 
1072
1069
 
1073
1070
class cmd_remove(Command):
1074
 
    """Remove files or directories.
 
1071
    """Make a file unversioned.
1075
1072
 
1076
 
    This makes bzr stop tracking changes to the specified files and
1077
 
    delete them if they can easily be recovered using revert.
 
1073
    This makes bzr stop tracking changes to a versioned file.  It does
 
1074
    not delete the working copy.
1078
1075
 
1079
1076
    You can specify one or more files, and/or --new.  If you specify --new,
1080
1077
    only 'added' files will be removed.  If you specify both, then new files
1082
1079
    also new, they will also be removed.
1083
1080
    """
1084
1081
    takes_args = ['file*']
1085
 
    takes_options = ['verbose',
1086
 
        Option('new', help='Remove newly-added files.'),
1087
 
        RegistryOption.from_kwargs('file-deletion-strategy',
1088
 
            'The file deletion mode to be used',
1089
 
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1090
 
            safe='Only delete files if they can be'
1091
 
                 ' safely recovered (default).',
1092
 
            keep="Don't delete any files.",
1093
 
            force='Delete all the specified files, even if they can not be '
1094
 
                'recovered and even if they are non-empty directories.')]
 
1082
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
1095
1083
    aliases = ['rm']
1096
1084
    encoding_type = 'replace'
1097
 
 
1098
 
    def run(self, file_list, verbose=False, new=False,
1099
 
        file_deletion_strategy='safe'):
 
1085
    
 
1086
    def run(self, file_list, verbose=False, new=False):
1100
1087
        tree, file_list = tree_files(file_list)
1101
 
 
1102
 
        if file_list is not None:
1103
 
            file_list = [f for f in file_list if f != '']
1104
 
        elif not new:
1105
 
            raise errors.BzrCommandError('Specify one or more files to'
1106
 
            ' remove, or use --new.')
1107
 
 
1108
 
        if new:
 
1088
        if new is False:
 
1089
            if file_list is None:
 
1090
                raise errors.BzrCommandError('Specify one or more files to'
 
1091
                                             ' remove, or use --new.')
 
1092
        else:
1109
1093
            added = tree.changes_from(tree.basis_tree(),
1110
1094
                specific_files=file_list).added
1111
1095
            file_list = sorted([f[0] for f in added], reverse=True)
1112
1096
            if len(file_list) == 0:
1113
1097
                raise errors.BzrCommandError('No matching files.')
1114
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1115
 
            keep_files=file_deletion_strategy=='keep',
1116
 
            force=file_deletion_strategy=='force')
 
1098
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
1117
1099
 
1118
1100
 
1119
1101
class cmd_file_id(Command):
1125
1107
    """
1126
1108
 
1127
1109
    hidden = True
1128
 
    _see_also = ['inventory', 'ls']
1129
1110
    takes_args = ['filename']
1130
1111
 
1131
1112
    @display_command
1178
1159
 
1179
1160
    The branch *MUST* be on a listable system such as local disk or sftp.
1180
1161
    """
1181
 
 
1182
 
    _see_also = ['check']
1183
1162
    takes_args = ['branch?']
1184
1163
 
1185
1164
    def run(self, branch="."):
1190
1169
 
1191
1170
class cmd_revision_history(Command):
1192
1171
    """Display the list of revision ids on a branch."""
1193
 
 
1194
 
    _see_also = ['log']
1195
1172
    takes_args = ['location?']
1196
1173
 
1197
1174
    hidden = True
1206
1183
 
1207
1184
class cmd_ancestry(Command):
1208
1185
    """List all revisions merged into this branch."""
1209
 
 
1210
 
    _see_also = ['log', 'revision-history']
1211
1186
    takes_args = ['location?']
1212
1187
 
1213
1188
    hidden = True
1238
1213
 
1239
1214
    If there is a repository in a parent directory of the location, then 
1240
1215
    the history of the branch will be stored in the repository.  Otherwise
1241
 
    init creates a standalone branch which carries its own history
1242
 
    in the .bzr directory.
 
1216
    init creates a standalone branch which carries its own history in 
 
1217
    .bzr.
1243
1218
 
1244
1219
    If there is already a branch at the location but it has no working tree,
1245
1220
    the tree can be populated with 'bzr checkout'.
1251
1226
        bzr status
1252
1227
        bzr commit -m 'imported project'
1253
1228
    """
1254
 
 
1255
 
    _see_also = ['init-repo', 'branch', 'checkout']
1256
1229
    takes_args = ['location?']
1257
1230
    takes_options = [
1258
 
        Option('create-prefix',
1259
 
               help='Create the path leading up to the branch '
1260
 
                    'if it does not already exist.'),
1261
1231
         RegistryOption('format',
1262
1232
                help='Specify a format for this branch. '
1263
1233
                'See "help formats".',
1270
1240
                help='Never change revnos or the existing log.'
1271
1241
                '  Append revisions to it only.')
1272
1242
         ]
1273
 
    def run(self, location=None, format=None, append_revisions_only=False,
1274
 
            create_prefix=False):
 
1243
    def run(self, location=None, format=None, append_revisions_only=False):
1275
1244
        if format is None:
1276
1245
            format = bzrdir.format_registry.make_bzrdir('default')
1277
1246
        if location is None:
1284
1253
        # Just using os.mkdir, since I don't
1285
1254
        # believe that we want to create a bunch of
1286
1255
        # locations if the user supplies an extended path
1287
 
        try:
1288
 
            to_transport.ensure_base()
1289
 
        except errors.NoSuchFile:
1290
 
            if not create_prefix:
1291
 
                raise errors.BzrCommandError("Parent directory of %s"
1292
 
                    " does not exist."
1293
 
                    "\nYou may supply --create-prefix to create all"
1294
 
                    " leading parent directories."
1295
 
                    % location)
1296
 
            _create_prefix(to_transport)
1297
 
 
1298
 
        try:
1299
 
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
1256
        # TODO: create-prefix
 
1257
        try:
 
1258
            to_transport.mkdir('.')
 
1259
        except errors.FileExists:
 
1260
            pass
 
1261
                    
 
1262
        try:
 
1263
            existing_bzrdir = bzrdir.BzrDir.open(location)
1300
1264
        except errors.NotBranchError:
1301
1265
            # really a NotBzrDir error...
1302
 
            create_branch = bzrdir.BzrDir.create_branch_convenience
1303
 
            branch = create_branch(to_transport.base, format=format,
1304
 
                                   possible_transports=[to_transport])
 
1266
            branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
 
1267
                                                             format=format)
1305
1268
        else:
1306
1269
            from bzrlib.transport.local import LocalTransport
1307
1270
            if existing_bzrdir.has_branch():
1323
1286
class cmd_init_repository(Command):
1324
1287
    """Create a shared repository to hold branches.
1325
1288
 
1326
 
    New branches created under the repository directory will store their
1327
 
    revisions in the repository, not in the branch directory.
1328
 
 
1329
 
    If the --no-trees option is used then the branches in the repository
1330
 
    will not have working trees by default.
 
1289
    New branches created under the repository directory will store their revisions
 
1290
    in the repository, not in the branch directory, if the branch format supports
 
1291
    shared storage.
1331
1292
 
1332
1293
    example:
1333
 
        bzr init-repo --no-trees repo
 
1294
        bzr init-repo repo
1334
1295
        bzr init repo/trunk
1335
1296
        bzr checkout --lightweight repo/trunk trunk-checkout
1336
1297
        cd trunk-checkout
1337
1298
        (add files here)
1338
 
 
1339
 
    See 'bzr help repositories' for more information.
1340
1299
    """
1341
 
 
1342
 
    _see_also = ['init', 'branch', 'checkout']
1343
1300
    takes_args = ["location"]
1344
1301
    takes_options = [RegistryOption('format',
1345
1302
                            help='Specify a format for this repository. See'
1346
 
                                 ' "bzr help formats" for details.',
 
1303
                                 ' "bzr help formats" for details',
1347
1304
                            registry=bzrdir.format_registry,
1348
1305
                            converter=bzrdir.format_registry.make_bzrdir,
1349
1306
                            value_switches=True, title='Repository format'),
1350
 
                     Option('no-trees',
1351
 
                             help='Branches in the repository will default to'
1352
 
                                  ' not having a working tree.'),
1353
 
                    ]
 
1307
                     Option('trees',
 
1308
                             help='Allows branches in repository to have'
 
1309
                             ' a working tree')]
1354
1310
    aliases = ["init-repo"]
1355
 
 
1356
 
    def run(self, location, format=None, no_trees=False):
 
1311
    def run(self, location, format=None, trees=False):
1357
1312
        if format is None:
1358
1313
            format = bzrdir.format_registry.make_bzrdir('default')
1359
1314
 
1361
1316
            location = '.'
1362
1317
 
1363
1318
        to_transport = transport.get_transport(location)
1364
 
        to_transport.ensure_base()
 
1319
        try:
 
1320
            to_transport.mkdir('.')
 
1321
        except errors.FileExists:
 
1322
            pass
1365
1323
 
1366
1324
        newdir = format.initialize_on_transport(to_transport)
1367
1325
        repo = newdir.create_repository(shared=True)
1368
 
        repo.set_make_working_trees(not no_trees)
 
1326
        repo.set_make_working_trees(trees)
1369
1327
 
1370
1328
 
1371
1329
class cmd_diff(Command):
1402
1360
 
1403
1361
    # TODO: This probably handles non-Unix newlines poorly.
1404
1362
 
1405
 
    _see_also = ['status']
1406
1363
    takes_args = ['file*']
1407
 
    takes_options = [
1408
 
        Option('diff-options', type=str,
1409
 
               help='Pass these options to the external diff program.'),
 
1364
    takes_options = ['revision', 'diff-options',
1410
1365
        Option('prefix', type=str,
1411
1366
               short_name='p',
1412
1367
               help='Set prefixes to added to old and new filenames, as '
1413
 
                    'two values separated by a colon. (eg "old/:new/").'),
1414
 
        'revision',
 
1368
                    'two values separated by a colon. (eg "old/:new/")'),
1415
1369
        ]
1416
1370
    aliases = ['di', 'dif']
1417
1371
    encoding_type = 'exact'
1491
1445
    # directories with readdir, rather than stating each one.  Same
1492
1446
    # level of effort but possibly much less IO.  (Or possibly not,
1493
1447
    # if the directories are very large...)
1494
 
    _see_also = ['status', 'ls']
1495
1448
    takes_options = ['show-ids']
1496
1449
 
1497
1450
    @display_command
1517
1470
 
1518
1471
class cmd_modified(Command):
1519
1472
    """List files modified in working tree.
 
1473
 
 
1474
    See also: "bzr status".
1520
1475
    """
1521
1476
 
1522
1477
    hidden = True
1523
 
    _see_also = ['status', 'ls']
1524
1478
 
1525
1479
    @display_command
1526
1480
    def run(self):
1532
1486
 
1533
1487
class cmd_added(Command):
1534
1488
    """List files added in working tree.
 
1489
 
 
1490
    See also: "bzr status".
1535
1491
    """
1536
1492
 
1537
1493
    hidden = True
1538
 
    _see_also = ['status', 'ls']
1539
1494
 
1540
1495
    @display_command
1541
1496
    def run(self):
1567
1522
 
1568
1523
    The root is the nearest enclosing directory with a .bzr control
1569
1524
    directory."""
1570
 
 
1571
1525
    takes_args = ['filename?']
1572
1526
    @display_command
1573
1527
    def run(self, filename=None):
1576
1530
        self.outf.write(tree.basedir + '\n')
1577
1531
 
1578
1532
 
1579
 
def _parse_limit(limitstring):
1580
 
    try:
1581
 
        return int(limitstring)
1582
 
    except ValueError:
1583
 
        msg = "The limit argument must be an integer."
1584
 
        raise errors.BzrCommandError(msg)
1585
 
 
1586
 
 
1587
1533
class cmd_log(Command):
1588
1534
    """Show log of a branch, file, or directory.
1589
1535
 
1602
1548
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1603
1549
 
1604
1550
    takes_args = ['location?']
1605
 
    takes_options = [
1606
 
            Option('forward',
1607
 
                   help='Show from oldest to newest.'),
1608
 
            Option('timezone',
1609
 
                   type=str,
1610
 
                   help='Display timezone as local, original, or utc.'),
1611
 
            Option('verbose',
1612
 
                   short_name='v',
1613
 
                   help='Show files changed in each revision.'),
1614
 
            'show-ids',
1615
 
            'revision',
1616
 
            'log-format',
1617
 
            Option('message',
1618
 
                   short_name='m',
1619
 
                   help='Show revisions whose message matches this '
1620
 
                        'regular expression.',
1621
 
                   type=str),
1622
 
            Option('limit',
1623
 
                   help='Limit the output to the first N revisions.',
1624
 
                   argname='N',
1625
 
                   type=_parse_limit),
1626
 
            ]
 
1551
    takes_options = [Option('forward', 
 
1552
                            help='show from oldest to newest'),
 
1553
                     'timezone', 
 
1554
                     Option('verbose', 
 
1555
                             short_name='v',
 
1556
                             help='show files changed in each revision'),
 
1557
                     'show-ids', 'revision',
 
1558
                     'log-format',
 
1559
                     Option('message',
 
1560
                            short_name='m',
 
1561
                            help='show revisions whose message matches this regexp',
 
1562
                            type=str),
 
1563
                     ]
1627
1564
    encoding_type = 'replace'
1628
1565
 
1629
1566
    @display_command
1633
1570
            forward=False,
1634
1571
            revision=None,
1635
1572
            log_format=None,
1636
 
            message=None,
1637
 
            limit=None):
 
1573
            message=None):
1638
1574
        from bzrlib.log import show_log
1639
1575
        assert message is None or isinstance(message, basestring), \
1640
1576
            "invalid message argument %r" % message
1672
1608
                rev1 = None
1673
1609
                rev2 = None
1674
1610
            elif len(revision) == 1:
1675
 
                rev1 = rev2 = revision[0].in_history(b)
 
1611
                rev1 = rev2 = revision[0].in_history(b).revno
1676
1612
            elif len(revision) == 2:
1677
1613
                if revision[1].get_branch() != revision[0].get_branch():
1678
1614
                    # b is taken from revision[0].get_branch(), and
1681
1617
                    raise errors.BzrCommandError(
1682
1618
                        "Log doesn't accept two revisions in different"
1683
1619
                        " branches.")
1684
 
                rev1 = revision[0].in_history(b)
1685
 
                rev2 = revision[1].in_history(b)
 
1620
                if revision[0].spec is None:
 
1621
                    # missing begin-range means first revision
 
1622
                    rev1 = 1
 
1623
                else:
 
1624
                    rev1 = revision[0].in_history(b).revno
 
1625
 
 
1626
                if revision[1].spec is None:
 
1627
                    # missing end-range means last known revision
 
1628
                    rev2 = b.revno()
 
1629
                else:
 
1630
                    rev2 = revision[1].in_history(b).revno
1686
1631
            else:
1687
1632
                raise errors.BzrCommandError(
1688
1633
                    'bzr log --revision takes one or two values.')
1689
1634
 
 
1635
            # By this point, the revision numbers are converted to the +ve
 
1636
            # form if they were supplied in the -ve form, so we can do
 
1637
            # this comparison in relative safety
 
1638
            if rev1 > rev2:
 
1639
                (rev2, rev1) = (rev1, rev2)
 
1640
 
1690
1641
            if log_format is None:
1691
1642
                log_format = log.log_formatter_registry.get_default(b)
1692
1643
 
1700
1651
                     direction=direction,
1701
1652
                     start_revision=rev1,
1702
1653
                     end_revision=rev2,
1703
 
                     search=message,
1704
 
                     limit=limit)
 
1654
                     search=message)
1705
1655
        finally:
1706
1656
            b.unlock()
1707
1657
 
1739
1689
    """List files in a tree.
1740
1690
    """
1741
1691
 
1742
 
    _see_also = ['status', 'cat']
1743
1692
    takes_args = ['path?']
1744
1693
    # TODO: Take a revision or remote path and list that tree instead.
1745
 
    takes_options = [
1746
 
            'verbose',
1747
 
            'revision',
1748
 
            Option('non-recursive',
1749
 
                   help='Don\'t recurse into subdirectories.'),
1750
 
            Option('from-root',
1751
 
                   help='Print paths relative to the root of the branch.'),
1752
 
            Option('unknown', help='Print unknown files.'),
1753
 
            Option('versioned', help='Print versioned files.'),
1754
 
            Option('ignored', help='Print ignored files.'),
1755
 
            Option('null',
1756
 
                   help='Write an ascii NUL (\\0) separator '
1757
 
                   'between files rather than a newline.'),
1758
 
            Option('kind',
1759
 
                   help='List entries of a particular kind: file, directory, symlink.',
1760
 
                   type=unicode),
1761
 
            'show-ids',
1762
 
            ]
 
1694
    takes_options = ['verbose', 'revision',
 
1695
                     Option('non-recursive',
 
1696
                            help='don\'t recurse into sub-directories'),
 
1697
                     Option('from-root',
 
1698
                            help='Print all paths from the root of the branch.'),
 
1699
                     Option('unknown', help='Print unknown files'),
 
1700
                     Option('versioned', help='Print versioned files'),
 
1701
                     Option('ignored', help='Print ignored files'),
 
1702
 
 
1703
                     Option('null', help='Null separate the files'),
 
1704
                     'kind', 'show-ids'
 
1705
                    ]
1763
1706
    @display_command
1764
 
    def run(self, revision=None, verbose=False,
 
1707
    def run(self, revision=None, verbose=False, 
1765
1708
            non_recursive=False, from_root=False,
1766
1709
            unknown=False, versioned=False, ignored=False,
1767
1710
            null=False, kind=None, show_ids=False, path=None):
1835
1778
 
1836
1779
class cmd_unknowns(Command):
1837
1780
    """List unknown files.
 
1781
 
 
1782
    See also: "bzr ls --unknown".
1838
1783
    """
1839
1784
 
1840
1785
    hidden = True
1841
 
    _see_also = ['ls']
1842
1786
 
1843
1787
    @display_command
1844
1788
    def run(self):
1879
1823
        bzr ignore 'lib/**/*.o'
1880
1824
        bzr ignore 'RE:lib/.*\.o'
1881
1825
    """
1882
 
 
1883
 
    _see_also = ['status', 'ignored']
1884
1826
    takes_args = ['name_pattern*']
1885
1827
    takes_options = [
1886
 
        Option('old-default-rules',
1887
 
               help='Write out the ignore rules bzr < 0.9 always used.')
1888
 
        ]
 
1828
                     Option('old-default-rules',
 
1829
                            help='Out the ignore rules bzr < 0.9 always used.')
 
1830
                     ]
1889
1831
    
1890
1832
    def run(self, name_pattern_list=None, old_default_rules=None):
1891
1833
        from bzrlib.atomicfile import AtomicFile
1936
1878
 
1937
1879
class cmd_ignored(Command):
1938
1880
    """List ignored files and the patterns that matched them.
1939
 
    """
1940
1881
 
1941
 
    _see_also = ['ignore']
 
1882
    See also: bzr ignore"""
1942
1883
    @display_command
1943
1884
    def run(self):
1944
1885
        tree = WorkingTree.open_containing(u'.')[0]
1974
1915
 
1975
1916
 
1976
1917
class cmd_export(Command):
1977
 
    """Export current or past revision to a destination directory or archive.
 
1918
    """Export past revision to destination directory.
1978
1919
 
1979
1920
    If no revision is specified this exports the last committed revision.
1980
1921
 
1982
1923
    given, try to find the format with the extension. If no extension
1983
1924
    is found exports to a directory (equivalent to --format=dir).
1984
1925
 
1985
 
    If root is supplied, it will be used as the root directory inside
1986
 
    container formats (tar, zip, etc). If it is not supplied it will default
1987
 
    to the exported filename. The root option has no effect for 'dir' format.
1988
 
 
1989
 
    If branch is omitted then the branch containing the current working
1990
 
    directory will be used.
1991
 
 
1992
 
    Note: Export of tree with non-ASCII filenames to zip is not supported.
 
1926
    Root may be the top directory for tar, tgz and tbz2 formats. If none
 
1927
    is given, the top directory will be the root name of the file.
 
1928
 
 
1929
    If branch is omitted then the branch containing the CWD will be used.
 
1930
 
 
1931
    Note: export of tree with non-ascii filenames to zip is not supported.
1993
1932
 
1994
1933
     Supported formats       Autodetected by extension
1995
1934
     -----------------       -------------------------
2000
1939
         zip                          .zip
2001
1940
    """
2002
1941
    takes_args = ['dest', 'branch?']
2003
 
    takes_options = [
2004
 
        Option('format',
2005
 
               help="Type of file to export to.",
2006
 
               type=unicode),
2007
 
        'revision',
2008
 
        Option('root',
2009
 
               type=str,
2010
 
               help="Name of the root directory inside the exported file."),
2011
 
        ]
 
1942
    takes_options = ['revision', 'format', 'root']
2012
1943
    def run(self, dest, branch=None, revision=None, format=None, root=None):
2013
1944
        from bzrlib.export import export
2014
1945
 
2033
1964
 
2034
1965
 
2035
1966
class cmd_cat(Command):
2036
 
    """Write the contents of a file as of a given revision to standard output.
2037
 
 
2038
 
    If no revision is nominated, the last revision is used.
2039
 
 
2040
 
    Note: Take care to redirect standard output when using this command on a
2041
 
    binary file. 
2042
 
    """
2043
 
 
2044
 
    _see_also = ['ls']
2045
 
    takes_options = [
2046
 
        Option('name-from-revision', help='The path name in the old tree.'),
2047
 
        'revision',
2048
 
        ]
 
1967
    """Write a file's text from a previous revision."""
 
1968
 
 
1969
    takes_options = ['revision', 'name-from-revision']
2049
1970
    takes_args = ['filename']
2050
1971
    encoding_type = 'exact'
2051
1972
 
2109
2030
    within it is committed.
2110
2031
 
2111
2032
    A selected-file commit may fail in some cases where the committed
2112
 
    tree would be invalid. Consider::
2113
 
 
2114
 
      bzr init foo
2115
 
      mkdir foo/bar
2116
 
      bzr add foo/bar
2117
 
      bzr commit foo -m "committing foo"
2118
 
      bzr mv foo/bar foo/baz
2119
 
      mkdir foo/bar
2120
 
      bzr add foo/bar
2121
 
      bzr commit foo/bar -m "committing bar but not baz"
2122
 
 
2123
 
    In the example above, the last commit will fail by design. This gives
2124
 
    the user the opportunity to decide whether they want to commit the
2125
 
    rename at the same time, separately first, or not at all. (As a general
2126
 
    rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2127
 
 
2128
 
    Note: A selected-file commit after a merge is not yet supported.
 
2033
    tree would be invalid, such as trying to commit a file in a
 
2034
    newly-added directory that is not itself committed.
2129
2035
    """
2130
2036
    # TODO: Run hooks on tree to-be-committed, and after commit.
2131
2037
 
2136
2042
 
2137
2043
    # XXX: verbose currently does nothing
2138
2044
 
2139
 
    _see_also = ['bugs', 'uncommit']
2140
2045
    takes_args = ['selected*']
2141
 
    takes_options = [
2142
 
            Option('message', type=unicode,
2143
 
                   short_name='m',
2144
 
                   help="Description of the new revision."),
2145
 
            'verbose',
2146
 
             Option('unchanged',
2147
 
                    help='Commit even if nothing has changed.'),
2148
 
             Option('file', type=str,
2149
 
                    short_name='F',
2150
 
                    argname='msgfile',
2151
 
                    help='Take commit message from this file.'),
2152
 
             Option('strict',
2153
 
                    help="Refuse to commit if there are unknown "
2154
 
                    "files in the working tree."),
2155
 
             ListOption('fixes', type=str,
2156
 
                    help="Mark a bug as being fixed by this revision."),
2157
 
             Option('local',
2158
 
                    help="Perform a local commit in a bound "
2159
 
                         "branch.  Local commits are not pushed to "
2160
 
                         "the master branch until a normal commit "
2161
 
                         "is performed."
2162
 
                    ),
2163
 
             ]
 
2046
    takes_options = ['message', 'verbose', 
 
2047
                     Option('unchanged',
 
2048
                            help='commit even if nothing has changed'),
 
2049
                     Option('file', type=str, 
 
2050
                            short_name='F',
 
2051
                            argname='msgfile',
 
2052
                            help='file containing commit message'),
 
2053
                     Option('strict',
 
2054
                            help="refuse to commit if there are unknown "
 
2055
                            "files in the working tree."),
 
2056
                     Option('local',
 
2057
                            help="perform a local only commit in a bound "
 
2058
                                 "branch. Such commits are not pushed to "
 
2059
                                 "the master branch until a normal commit "
 
2060
                                 "is performed."
 
2061
                            ),
 
2062
                     ]
2164
2063
    aliases = ['ci', 'checkin']
2165
2064
 
2166
 
    def _get_bug_fix_properties(self, fixes, branch):
2167
 
        properties = []
2168
 
        # Configure the properties for bug fixing attributes.
2169
 
        for fixed_bug in fixes:
2170
 
            tokens = fixed_bug.split(':')
2171
 
            if len(tokens) != 2:
2172
 
                raise errors.BzrCommandError(
2173
 
                    "Invalid bug %s. Must be in the form of 'tag:id'. "
2174
 
                    "Commit refused." % fixed_bug)
2175
 
            tag, bug_id = tokens
2176
 
            try:
2177
 
                bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2178
 
            except errors.UnknownBugTrackerAbbreviation:
2179
 
                raise errors.BzrCommandError(
2180
 
                    'Unrecognized bug %s. Commit refused.' % fixed_bug)
2181
 
            except errors.MalformedBugIdentifier:
2182
 
                raise errors.BzrCommandError(
2183
 
                    "Invalid bug identifier for %s. Commit refused."
2184
 
                    % fixed_bug)
2185
 
            properties.append('%s fixed' % bug_url)
2186
 
        return '\n'.join(properties)
2187
 
 
2188
2065
    def run(self, message=None, file=None, verbose=True, selected_list=None,
2189
 
            unchanged=False, strict=False, local=False, fixes=None):
 
2066
            unchanged=False, strict=False, local=False):
2190
2067
        from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2191
2068
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2192
2069
                StrictCommitFailed)
2198
2075
 
2199
2076
        # TODO: do more checks that the commit will succeed before 
2200
2077
        # spending the user's valuable time typing a commit message.
2201
 
 
2202
 
        properties = {}
2203
 
 
2204
2078
        tree, selected_list = tree_files(selected_list)
2205
2079
        if selected_list == ['']:
2206
2080
            # workaround - commit of root of tree should be exactly the same
2208
2082
            # selected-file merge commit is not done yet
2209
2083
            selected_list = []
2210
2084
 
2211
 
        bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2212
 
        if bug_property:
2213
 
            properties['bugs'] = bug_property
2214
 
 
2215
2085
        if local and not tree.branch.get_bound_location():
2216
2086
            raise errors.LocalRequiresBoundBranch()
2217
2087
 
2233
2103
            if my_message == "":
2234
2104
                raise errors.BzrCommandError("empty commit message specified")
2235
2105
            return my_message
2236
 
 
 
2106
        
2237
2107
        if verbose:
2238
2108
            reporter = ReportCommitToLog()
2239
2109
        else:
2243
2113
            tree.commit(message_callback=get_message,
2244
2114
                        specific_files=selected_list,
2245
2115
                        allow_pointless=unchanged, strict=strict, local=local,
2246
 
                        reporter=reporter, revprops=properties)
 
2116
                        reporter=reporter)
2247
2117
        except PointlessCommit:
2248
2118
            # FIXME: This should really happen before the file is read in;
2249
2119
            # perhaps prepare the commit; get the message; then actually commit
2269
2139
    This command checks various invariants about the branch storage to
2270
2140
    detect data corruption or bzr bugs.
2271
2141
    """
2272
 
 
2273
 
    _see_also = ['reconcile']
2274
2142
    takes_args = ['branch?']
2275
2143
    takes_options = ['verbose']
2276
2144
 
2291
2159
    this command. When the default format has changed you may also be warned
2292
2160
    during other operations to upgrade.
2293
2161
    """
2294
 
 
2295
 
    _see_also = ['check']
2296
2162
    takes_args = ['url?']
2297
2163
    takes_options = [
2298
2164
                    RegistryOption('format',
2299
2165
                        help='Upgrade to a specific format.  See "bzr help'
2300
 
                             ' formats" for details.',
 
2166
                             ' formats" for details',
2301
2167
                        registry=bzrdir.format_registry,
2302
2168
                        converter=bzrdir.format_registry.make_bzrdir,
2303
2169
                        value_switches=True, title='Branch format'),
2318
2184
        bzr whoami 'Frank Chu <fchu@example.com>'
2319
2185
    """
2320
2186
    takes_options = [ Option('email',
2321
 
                             help='Display email address only.'),
 
2187
                             help='display email address only'),
2322
2188
                      Option('branch',
2323
 
                             help='Set identity for the current branch instead of '
2324
 
                                  'globally.'),
 
2189
                             help='set identity for the current branch instead of '
 
2190
                                  'globally'),
2325
2191
                    ]
2326
2192
    takes_args = ['name?']
2327
2193
    encoding_type = 'replace'
2361
2227
    If unset, the tree root directory name is used as the nickname
2362
2228
    To print the current nickname, execute with no argument.  
2363
2229
    """
2364
 
 
2365
 
    _see_also = ['info']
2366
2230
    takes_args = ['nickname?']
2367
2231
    def run(self, nickname=None):
2368
2232
        branch = Branch.open_containing(u'.')[0]
2373
2237
 
2374
2238
    @display_command
2375
2239
    def printme(self, branch):
2376
 
        print branch.nick
 
2240
        print branch.nick 
2377
2241
 
2378
2242
 
2379
2243
class cmd_selftest(Command):
2380
2244
    """Run internal test suite.
2381
2245
    
 
2246
    This creates temporary test directories in the working directory, but not
 
2247
    existing data is affected.  These directories are deleted if the tests
 
2248
    pass, or left behind to help in debugging if they fail and --keep-output
 
2249
    is specified.
 
2250
    
2382
2251
    If arguments are given, they are regular expressions that say which tests
2383
2252
    should run.  Tests matching any expression are run, and other tests are
2384
2253
    not run.
2387
2256
    all other tests are run.  This is useful if you have been working in a
2388
2257
    particular area, but want to make sure nothing else was broken.
2389
2258
 
2390
 
    If --exclude is given, tests that match that regular expression are
2391
 
    excluded, regardless of whether they match --first or not.
2392
 
 
2393
 
    To help catch accidential dependencies between tests, the --randomize
2394
 
    option is useful. In most cases, the argument used is the word 'now'.
2395
 
    Note that the seed used for the random number generator is displayed
2396
 
    when this option is used. The seed can be explicitly passed as the
2397
 
    argument to this option if required. This enables reproduction of the
2398
 
    actual ordering used if and when an order sensitive problem is encountered.
2399
 
 
2400
 
    If --list-only is given, the tests that would be run are listed. This is
2401
 
    useful when combined with --first, --exclude and/or --randomize to
2402
 
    understand their impact. The test harness reports "Listed nn tests in ..."
2403
 
    instead of "Ran nn tests in ..." when list mode is enabled.
2404
 
 
2405
2259
    If the global option '--no-plugins' is given, plugins are not loaded
2406
2260
    before running the selftests.  This has two effects: features provided or
2407
2261
    modified by plugins will not be tested, and tests provided by plugins will
2408
2262
    not be run.
2409
2263
 
2410
 
    Tests that need working space on disk use a common temporary directory, 
2411
 
    typically inside $TMPDIR or /tmp.
2412
 
 
2413
2264
    examples::
2414
2265
        bzr selftest ignore
2415
2266
            run only tests relating to 'ignore'
2416
2267
        bzr --no-plugins selftest -v
2417
2268
            disable plugins and list tests as they're run
 
2269
 
 
2270
    For each test, that needs actual disk access, bzr create their own
 
2271
    subdirectory in the temporary testing directory (testXXXX.tmp).
 
2272
    By default the name of such subdirectory is based on the name of the test.
 
2273
    If option '--numbered-dirs' is given, bzr will use sequent numbers
 
2274
    of running tests to create such subdirectories. This is default behavior
 
2275
    on Windows because of path length limitation.
2418
2276
    """
 
2277
    # TODO: --list should give a list of all available tests
 
2278
 
2419
2279
    # NB: this is used from the class without creating an instance, which is
2420
2280
    # why it does not have a self parameter.
2421
2281
    def get_transport_type(typestring):
2436
2296
    hidden = True
2437
2297
    takes_args = ['testspecs*']
2438
2298
    takes_options = ['verbose',
2439
 
                     Option('one',
2440
 
                             help='Stop when one test fails.',
2441
 
                             short_name='1',
2442
 
                             ),
 
2299
                     Option('one', help='stop when one test fails'),
 
2300
                     Option('keep-output',
 
2301
                            help='keep output directories when tests fail'),
2443
2302
                     Option('transport',
2444
2303
                            help='Use a different transport by default '
2445
2304
                                 'throughout the test suite.',
2446
2305
                            type=get_transport_type),
2447
 
                     Option('benchmark',
2448
 
                            help='Run the benchmarks rather than selftests.'),
 
2306
                     Option('benchmark', help='run the bzr benchmarks.'),
2449
2307
                     Option('lsprof-timed',
2450
 
                            help='Generate lsprof output for benchmarked'
 
2308
                            help='generate lsprof output for benchmarked'
2451
2309
                                 ' sections of code.'),
2452
2310
                     Option('cache-dir', type=str,
2453
 
                            help='Cache intermediate benchmark output in this '
2454
 
                                 'directory.'),
 
2311
                            help='a directory to cache intermediate'
 
2312
                                 ' benchmark steps'),
 
2313
                     Option('clean-output',
 
2314
                            help='clean temporary tests directories'
 
2315
                                 ' without running tests'),
2455
2316
                     Option('first',
2456
 
                            help='Run all tests, but run specified tests first.',
2457
 
                            short_name='f',
 
2317
                            help='run all tests, but run specified tests first'
2458
2318
                            ),
2459
 
                     Option('list-only',
2460
 
                            help='List the tests instead of running them.'),
2461
 
                     Option('randomize', type=str, argname="SEED",
2462
 
                            help='Randomize the order of tests using the given'
2463
 
                                 ' seed or "now" for the current time.'),
2464
 
                     Option('exclude', type=str, argname="PATTERN",
2465
 
                            short_name='x',
2466
 
                            help='Exclude tests that match this regular'
2467
 
                                 ' expression.'),
 
2319
                     Option('numbered-dirs',
 
2320
                            help='use numbered dirs for TestCaseInTempDir'),
2468
2321
                     ]
2469
2322
    encoding_type = 'replace'
2470
2323
 
2471
2324
    def run(self, testspecs_list=None, verbose=None, one=False,
2472
 
            transport=None, benchmark=None,
2473
 
            lsprof_timed=None, cache_dir=None,
2474
 
            first=False, list_only=False,
2475
 
            randomize=None, exclude=None):
 
2325
            keep_output=False, transport=None, benchmark=None,
 
2326
            lsprof_timed=None, cache_dir=None, clean_output=False,
 
2327
            first=False, numbered_dirs=None):
2476
2328
        import bzrlib.ui
2477
2329
        from bzrlib.tests import selftest
2478
2330
        import bzrlib.benchmarks as benchmarks
2479
2331
        from bzrlib.benchmarks import tree_creator
2480
 
        from bzrlib.version import show_version
 
2332
 
 
2333
        if clean_output:
 
2334
            from bzrlib.tests import clean_selftest_output
 
2335
            clean_selftest_output()
 
2336
            return 0
 
2337
 
 
2338
        if numbered_dirs is None and sys.platform == 'win32':
 
2339
            numbered_dirs = True
2481
2340
 
2482
2341
        if cache_dir is not None:
2483
2342
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2484
 
        if not list_only:
2485
 
            show_version(show_config=False, show_copyright=False)
 
2343
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
 
2344
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2486
2345
        print
2487
2346
        if testspecs_list is not None:
2488
2347
            pattern = '|'.join(testspecs_list)
2500
2359
                verbose = False
2501
2360
            benchfile = None
2502
2361
        try:
2503
 
            result = selftest(verbose=verbose,
 
2362
            result = selftest(verbose=verbose, 
2504
2363
                              pattern=pattern,
2505
 
                              stop_on_failure=one,
 
2364
                              stop_on_failure=one, 
 
2365
                              keep_output=keep_output,
2506
2366
                              transport=transport,
2507
2367
                              test_suite_factory=test_suite_factory,
2508
2368
                              lsprof_timed=lsprof_timed,
2509
2369
                              bench_history=benchfile,
2510
2370
                              matching_tests_first=first,
2511
 
                              list_only=list_only,
2512
 
                              random_seed=randomize,
2513
 
                              exclude_pattern=exclude
 
2371
                              numbered_dirs=numbered_dirs,
2514
2372
                              )
2515
2373
        finally:
2516
2374
            if benchfile is not None:
2550
2408
    
2551
2409
    @display_command
2552
2410
    def run(self, branch, other):
2553
 
        from bzrlib.revision import ensure_null, MultipleRevisionSources
 
2411
        from bzrlib.revision import MultipleRevisionSources
2554
2412
        
2555
2413
        branch1 = Branch.open_containing(branch)[0]
2556
2414
        branch2 = Branch.open_containing(other)[0]
2557
2415
 
2558
 
        last1 = ensure_null(branch1.last_revision())
2559
 
        last2 = ensure_null(branch2.last_revision())
 
2416
        last1 = branch1.last_revision()
 
2417
        last2 = branch2.last_revision()
2560
2418
 
2561
 
        graph = branch1.repository.get_graph(branch2.repository)
2562
 
        base_rev_id = graph.find_unique_lca(last1, last2)
 
2419
        source = MultipleRevisionSources(branch1.repository, 
 
2420
                                         branch2.repository)
 
2421
        
 
2422
        base_rev_id = common_ancestor(last1, last2, source)
2563
2423
 
2564
2424
        print 'merge base is revision %s' % base_rev_id
2565
2425
 
2595
2455
 
2596
2456
    Examples:
2597
2457
 
2598
 
    To merge the latest revision from bzr.dev:
2599
 
        bzr merge ../bzr.dev
 
2458
    To merge the latest revision from bzr.dev
 
2459
    bzr merge ../bzr.dev
2600
2460
 
2601
 
    To merge changes up to and including revision 82 from bzr.dev:
2602
 
        bzr merge -r 82 ../bzr.dev
 
2461
    To merge changes up to and including revision 82 from bzr.dev
 
2462
    bzr merge -r 82 ../bzr.dev
2603
2463
 
2604
2464
    To merge the changes introduced by 82, without previous changes:
2605
 
        bzr merge -r 81..82 ../bzr.dev
 
2465
    bzr merge -r 81..82 ../bzr.dev
2606
2466
    
2607
2467
    merge refuses to run if there are any uncommitted changes, unless
2608
2468
    --force is given.
 
2469
 
 
2470
    The following merge types are available:
2609
2471
    """
2610
 
 
2611
 
    _see_also = ['update', 'remerge', 'status-flags']
2612
2472
    takes_args = ['branch?']
2613
 
    takes_options = [
2614
 
        'revision',
2615
 
        Option('force',
2616
 
               help='Merge even if the destination tree has uncommitted changes.'),
2617
 
        'merge-type',
2618
 
        'reprocess',
2619
 
        'remember',
 
2473
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2620
2474
        Option('show-base', help="Show base revision text in "
2621
 
               "conflicts."),
 
2475
               "conflicts"),
2622
2476
        Option('uncommitted', help='Apply uncommitted changes'
2623
 
               ' from a working copy, instead of branch changes.'),
 
2477
               ' from a working copy, instead of branch changes'),
2624
2478
        Option('pull', help='If the destination is already'
2625
2479
                ' completely merged into the source, pull from the'
2626
 
                ' source rather than merging.  When this happens,'
 
2480
                ' source rather than merging. When this happens,'
2627
2481
                ' you do not need to commit the result.'),
2628
2482
        Option('directory',
2629
 
               help='Branch to merge into, '
2630
 
                    'rather than the one containing the working directory.',
2631
 
               short_name='d',
2632
 
               type=unicode,
2633
 
               ),
 
2483
            help='Branch to merge into, '
 
2484
                 'rather than the one containing the working directory',
 
2485
            short_name='d',
 
2486
            type=unicode,
 
2487
            ),
2634
2488
    ]
2635
2489
 
2636
2490
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2639
2493
            directory=None,
2640
2494
            ):
2641
2495
        from bzrlib.tag import _merge_tags_if_possible
2642
 
        # This is actually a branch (or merge-directive) *location*.
2643
 
        location = branch
2644
 
        del branch
2645
 
 
2646
2496
        if merge_type is None:
2647
2497
            merge_type = _mod_merge.Merge3Merger
2648
2498
 
2649
2499
        if directory is None: directory = u'.'
2650
 
        possible_transports = []
2651
 
        merger = None
2652
 
        allow_pending = True
2653
 
        verified = 'inapplicable'
 
2500
        # XXX: jam 20070225 WorkingTree should be locked before you extract its
 
2501
        #      inventory. Because merge is a mutating operation, it really
 
2502
        #      should be a lock_write() for the whole cmd_merge operation.
 
2503
        #      However, cmd_merge open's its own tree in _merge_helper, which
 
2504
        #      means if we lock here, the later lock_write() will always block.
 
2505
        #      Either the merge helper code should be updated to take a tree,
 
2506
        #      (What about tree.merge_from_branch?)
2654
2507
        tree = WorkingTree.open_containing(directory)[0]
2655
2508
        change_reporter = delta._ChangeReporter(
2656
2509
            unversioned_filter=tree.is_ignored)
2657
 
        cleanups = []
2658
 
        try:
2659
 
            pb = ui.ui_factory.nested_progress_bar()
2660
 
            cleanups.append(pb.finished)
2661
 
            tree.lock_write()
2662
 
            cleanups.append(tree.unlock)
2663
 
            if location is not None:
2664
 
                mergeable, other_transport = _get_mergeable_helper(location)
2665
 
                if mergeable:
2666
 
                    if uncommitted:
2667
 
                        raise errors.BzrCommandError('Cannot use --uncommitted'
2668
 
                            ' with bundles or merge directives.')
2669
 
 
2670
 
                    if revision is not None:
2671
 
                        raise errors.BzrCommandError(
2672
 
                            'Cannot use -r with merge directives or bundles')
2673
 
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
2674
 
                       mergeable, pb)
2675
 
                possible_transports.append(other_transport)
2676
 
 
2677
 
            if merger is None and uncommitted:
2678
 
                if revision is not None and len(revision) > 0:
2679
 
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
2680
 
                        ' --revision at the same time.')
2681
 
                location = self._select_branch_location(tree, location)[0]
2682
 
                other_tree, other_path = WorkingTree.open_containing(location)
2683
 
                merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2684
 
                    pb)
2685
 
                allow_pending = False
2686
 
 
2687
 
            if merger is None:
2688
 
                merger, allow_pending = self._get_merger_from_branch(tree,
2689
 
                    location, revision, remember, possible_transports, pb)
2690
 
 
2691
 
            merger.merge_type = merge_type
2692
 
            merger.reprocess = reprocess
2693
 
            merger.show_base = show_base
2694
 
            merger.change_reporter = change_reporter
2695
 
            self.sanity_check_merger(merger)
2696
 
            if (merger.base_rev_id == merger.other_rev_id and
2697
 
                merger.other_rev_id != None):
2698
 
                note('Nothing to do.')
2699
 
                return 0
2700
 
            if pull:
2701
 
                if merger.interesting_files is not None:
2702
 
                    raise BzrCommandError('Cannot pull individual files')
2703
 
                if (merger.base_rev_id == tree.last_revision()):
2704
 
                    result = tree.pull(merger.other_branch, False,
2705
 
                                       merger.other_rev_id)
2706
 
                    result.report(self.outf)
 
2510
 
 
2511
        if branch is not None:
 
2512
            try:
 
2513
                reader = bundle.read_bundle_from_url(branch)
 
2514
            except errors.NotABundle:
 
2515
                pass # Continue on considering this url a Branch
 
2516
            else:
 
2517
                conflicts = merge_bundle(reader, tree, not force, merge_type,
 
2518
                                         reprocess, show_base, change_reporter)
 
2519
                if conflicts == 0:
2707
2520
                    return 0
2708
 
            merger.check_basis(not force)
2709
 
            conflict_count = merger.do_merge()
2710
 
            if allow_pending:
2711
 
                merger.set_pending()
2712
 
            if verified == 'failed':
2713
 
                warning('Preview patch does not match changes')
2714
 
            if conflict_count != 0:
2715
 
                return 1
2716
 
            else:
2717
 
                return 0
2718
 
        finally:
2719
 
            for cleanup in reversed(cleanups):
2720
 
                cleanup()
2721
 
 
2722
 
    def sanity_check_merger(self, merger):
2723
 
        if (merger.show_base and
2724
 
            not merger.merge_type is _mod_merge.Merge3Merger):
2725
 
            raise errors.BzrCommandError("Show-base is not supported for this"
2726
 
                                         " merge type. %s" % merge_type)
2727
 
        if merger.reprocess and not merger.merge_type.supports_reprocess:
2728
 
            raise errors.BzrCommandError("Conflict reduction is not supported"
2729
 
                                         " for merge type %s." % merge_type)
2730
 
        if merger.reprocess and merger.show_base:
2731
 
            raise errors.BzrCommandError("Cannot do conflict reduction and"
2732
 
                                         " show base.")
2733
 
 
2734
 
    def _get_merger_from_branch(self, tree, location, revision, remember,
2735
 
                                possible_transports, pb):
2736
 
        """Produce a merger from a location, assuming it refers to a branch."""
2737
 
        from bzrlib.tag import _merge_tags_if_possible
2738
 
        assert revision is None or len(revision) < 3
2739
 
        # find the branch locations
2740
 
        other_loc, location = self._select_branch_location(tree, location,
2741
 
            revision, -1)
2742
 
        if revision is not None and len(revision) == 2:
2743
 
            base_loc, location = self._select_branch_location(tree, location,
2744
 
                                                              revision, 0)
2745
 
        else:
2746
 
            base_loc = other_loc
2747
 
        # Open the branches
2748
 
        other_branch, other_path = Branch.open_containing(other_loc,
2749
 
            possible_transports)
2750
 
        if base_loc == other_loc:
2751
 
            base_branch = other_branch
2752
 
        else:
2753
 
            base_branch, base_path = Branch.open_containing(base_loc,
2754
 
                possible_transports)
2755
 
        # Find the revision ids
2756
 
        if revision is None or len(revision) < 1 or revision[-1] is None:
2757
 
            other_revision_id = _mod_revision.ensure_null(
2758
 
                other_branch.last_revision())
2759
 
        else:
2760
 
            other_revision_id = \
2761
 
                _mod_revision.ensure_null(
2762
 
                    revision[-1].in_history(other_branch).rev_id)
2763
 
        if (revision is not None and len(revision) == 2
2764
 
            and revision[0] is not None):
2765
 
            base_revision_id = \
2766
 
                _mod_revision.ensure_null(
2767
 
                    revision[0].in_history(base_branch).rev_id)
2768
 
        else:
2769
 
            base_revision_id = None
2770
 
        # Remember where we merge from
2771
 
        if ((tree.branch.get_parent() is None or remember) and
2772
 
            other_branch is not None):
 
2521
                else:
 
2522
                    return 1
 
2523
 
 
2524
        if revision is None \
 
2525
                or len(revision) < 1 or revision[0].needs_branch():
 
2526
            branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
2527
 
 
2528
        if revision is None or len(revision) < 1:
 
2529
            if uncommitted:
 
2530
                base = [branch, -1]
 
2531
                other = [branch, None]
 
2532
            else:
 
2533
                base = [None, None]
 
2534
                other = [branch, -1]
 
2535
            other_branch, path = Branch.open_containing(branch)
 
2536
        else:
 
2537
            if uncommitted:
 
2538
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2539
                                             ' --revision at the same time.')
 
2540
            branch = revision[0].get_branch() or branch
 
2541
            if len(revision) == 1:
 
2542
                base = [None, None]
 
2543
                other_branch, path = Branch.open_containing(branch)
 
2544
                revno = revision[0].in_history(other_branch).revno
 
2545
                other = [branch, revno]
 
2546
            else:
 
2547
                assert len(revision) == 2
 
2548
                if None in revision:
 
2549
                    raise errors.BzrCommandError(
 
2550
                        "Merge doesn't permit empty revision specifier.")
 
2551
                base_branch, path = Branch.open_containing(branch)
 
2552
                branch1 = revision[1].get_branch() or branch
 
2553
                other_branch, path1 = Branch.open_containing(branch1)
 
2554
                if revision[0].get_branch() is not None:
 
2555
                    # then path was obtained from it, and is None.
 
2556
                    path = path1
 
2557
 
 
2558
                base = [branch, revision[0].in_history(base_branch).revno]
 
2559
                other = [branch1, revision[1].in_history(other_branch).revno]
 
2560
 
 
2561
        if tree.branch.get_parent() is None or remember:
2773
2562
            tree.branch.set_parent(other_branch.base)
 
2563
 
 
2564
        # pull tags now... it's a bit inconsistent to do it ahead of copying
 
2565
        # the history but that's done inside the merge code
2774
2566
        _merge_tags_if_possible(other_branch, tree.branch)
2775
 
        merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2776
 
            other_revision_id, base_revision_id, other_branch, base_branch)
2777
 
        if other_path != '':
2778
 
            allow_pending = False
2779
 
            merger.interesting_files = [other_path]
 
2567
 
 
2568
        if path != "":
 
2569
            interesting_files = [path]
2780
2570
        else:
2781
 
            allow_pending = True
2782
 
        return merger, allow_pending
2783
 
 
2784
 
    def _select_branch_location(self, tree, location, revision=None,
2785
 
                                index=None):
2786
 
        """Select a branch location, according to possible inputs.
2787
 
 
2788
 
        If provided, branches from ``revision`` are preferred.  (Both
2789
 
        ``revision`` and ``index`` must be supplied.)
2790
 
 
2791
 
        Otherwise, the ``location`` parameter is used.  If it is None, then the
2792
 
        ``parent`` location is used, and a note is printed.
2793
 
 
2794
 
        :param tree: The working tree to select a branch for merging into
2795
 
        :param location: The location entered by the user
2796
 
        :param revision: The revision parameter to the command
2797
 
        :param index: The index to use for the revision parameter.  Negative
2798
 
            indices are permitted.
2799
 
        :return: (selected_location, default_location).  The default location
2800
 
            will be the user-entered location, if any, or else the remembered
2801
 
            location.
2802
 
        """
2803
 
        if (revision is not None and index is not None
2804
 
            and revision[index] is not None):
2805
 
            branch = revision[index].get_branch()
2806
 
            if branch is not None:
2807
 
                return branch, location
2808
 
        location = self._get_remembered_parent(tree, location, 'Merging from')
2809
 
        return location, location
 
2571
            interesting_files = None
 
2572
        pb = ui.ui_factory.nested_progress_bar()
 
2573
        try:
 
2574
            try:
 
2575
                conflict_count = _merge_helper(
 
2576
                    other, base, check_clean=(not force),
 
2577
                    merge_type=merge_type,
 
2578
                    reprocess=reprocess,
 
2579
                    show_base=show_base,
 
2580
                    pull=pull,
 
2581
                    this_dir=directory,
 
2582
                    pb=pb, file_list=interesting_files,
 
2583
                    change_reporter=change_reporter)
 
2584
            finally:
 
2585
                pb.finished()
 
2586
            if conflict_count != 0:
 
2587
                return 1
 
2588
            else:
 
2589
                return 0
 
2590
        except errors.AmbiguousBase, e:
 
2591
            m = ("sorry, bzr can't determine the right merge base yet\n"
 
2592
                 "candidates are:\n  "
 
2593
                 + "\n  ".join(e.bases)
 
2594
                 + "\n"
 
2595
                 "please specify an explicit base with -r,\n"
 
2596
                 "and (if you want) report this to the bzr developers\n")
 
2597
            log_error(m)
2810
2598
 
2811
2599
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2812
2600
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2820
2608
        mutter("%s", stored_location)
2821
2609
        if stored_location is None:
2822
2610
            raise errors.BzrCommandError("No location specified or remembered")
2823
 
        display_url = urlutils.unescape_for_display(stored_location,
2824
 
            self.outf.encoding)
2825
 
        self.outf.write("%s remembered location %s\n" % (verb_string,
2826
 
            display_url))
 
2611
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
 
2612
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2827
2613
        return stored_location
2828
2614
 
2829
2615
 
2839
2625
    pending merge, and it lets you specify particular files.
2840
2626
 
2841
2627
    Examples:
2842
 
 
2843
2628
    $ bzr remerge --show-base
2844
2629
        Re-do the merge of all conflicted files, and show the base text in
2845
2630
        conflict regions, in addition to the usual THIS and OTHER texts.
2847
2632
    $ bzr remerge --merge-type weave --reprocess foobar
2848
2633
        Re-do the merge of "foobar", using the weave merge algorithm, with
2849
2634
        additional processing to reduce the size of conflict regions.
2850
 
    """
 
2635
    
 
2636
    The following merge types are available:"""
2851
2637
    takes_args = ['file*']
2852
 
    takes_options = [
2853
 
            'merge-type',
2854
 
            'reprocess',
2855
 
            Option('show-base',
2856
 
                   help="Show base revision text in conflicts."),
2857
 
            ]
 
2638
    takes_options = ['merge-type', 'reprocess',
 
2639
                     Option('show-base', help="Show base revision text in "
 
2640
                            "conflicts")]
2858
2641
 
2859
2642
    def run(self, file_list=None, merge_type=None, show_base=False,
2860
2643
            reprocess=False):
2869
2652
                                             " merges.  Not cherrypicking or"
2870
2653
                                             " multi-merges.")
2871
2654
            repository = tree.branch.repository
2872
 
            graph = repository.get_graph()
2873
 
            base_revision = graph.find_unique_lca(parents[0], parents[1])
 
2655
            base_revision = common_ancestor(parents[0],
 
2656
                                            parents[1], repository)
2874
2657
            base_tree = repository.revision_tree(base_revision)
2875
2658
            other_tree = repository.revision_tree(parents[1])
2876
2659
            interesting_ids = None
2903
2686
                    restore(tree.abspath(filename))
2904
2687
                except errors.NotConflicted:
2905
2688
                    pass
2906
 
            # Disable pending merges, because the file texts we are remerging
2907
 
            # have not had those merges performed.  If we use the wrong parents
2908
 
            # list, we imply that the working tree text has seen and rejected
2909
 
            # all the changes from the other tree, when in fact those changes
2910
 
            # have not yet been seen.
2911
 
            tree.set_parent_ids(parents[:1])
2912
 
            try:
2913
 
                conflicts = _mod_merge.merge_inner(
2914
 
                                          tree.branch, other_tree, base_tree,
2915
 
                                          this_tree=tree,
2916
 
                                          interesting_ids=interesting_ids,
2917
 
                                          other_rev_id=parents[1],
2918
 
                                          merge_type=merge_type,
2919
 
                                          show_base=show_base,
2920
 
                                          reprocess=reprocess)
2921
 
            finally:
2922
 
                tree.set_parent_ids(parents)
 
2689
            conflicts = _mod_merge.merge_inner(
 
2690
                                      tree.branch, other_tree, base_tree,
 
2691
                                      this_tree=tree,
 
2692
                                      interesting_ids=interesting_ids,
 
2693
                                      other_rev_id=parents[1],
 
2694
                                      merge_type=merge_type,
 
2695
                                      show_base=show_base,
 
2696
                                      reprocess=reprocess)
2923
2697
        finally:
2924
2698
            tree.unlock()
2925
2699
        if conflicts > 0:
2949
2723
    name.  If you name a directory, all the contents of that directory will be
2950
2724
    reverted.
2951
2725
    """
2952
 
 
2953
 
    _see_also = ['cat', 'export']
2954
 
    takes_options = [
2955
 
            'revision',
2956
 
            Option('no-backup', "Do not save backups of reverted files."),
2957
 
            ]
 
2726
    takes_options = ['revision', 'no-backup']
2958
2727
    takes_args = ['file*']
 
2728
    aliases = ['merge-revert']
2959
2729
 
2960
2730
    def run(self, revision=None, no_backup=False, file_list=None):
2961
2731
        if file_list is not None:
2993
2763
 
2994
2764
class cmd_help(Command):
2995
2765
    """Show help on a command or other topic.
 
2766
 
 
2767
    For a list of all available commands, say 'bzr help commands'.
2996
2768
    """
2997
 
 
2998
 
    _see_also = ['topics']
2999
 
    takes_options = [
3000
 
            Option('long', 'Show help on all commands.'),
3001
 
            ]
 
2769
    takes_options = [Option('long', 'show help on all commands')]
3002
2770
    takes_args = ['topic?']
3003
2771
    aliases = ['?', '--help', '-?', '-h']
3004
2772
    
3041
2809
 
3042
2810
class cmd_missing(Command):
3043
2811
    """Show unmerged/unpulled revisions between two branches.
3044
 
    
 
2812
 
3045
2813
    OTHER_BRANCH may be local or remote.
3046
2814
    """
3047
 
 
3048
 
    _see_also = ['merge', 'pull']
3049
2815
    takes_args = ['other_branch?']
3050
 
    takes_options = [
3051
 
            Option('reverse', 'Reverse the order of revisions.'),
3052
 
            Option('mine-only',
3053
 
                   'Display changes in the local branch only.'),
3054
 
            Option('this' , 'Same as --mine-only.'),
3055
 
            Option('theirs-only',
3056
 
                   'Display changes in the remote branch only.'),
3057
 
            Option('other', 'Same as --theirs-only.'),
3058
 
            'log-format',
3059
 
            'show-ids',
3060
 
            'verbose'
3061
 
            ]
 
2816
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
 
2817
                     Option('mine-only', 
 
2818
                            'Display changes in the local branch only'),
 
2819
                     Option('theirs-only', 
 
2820
                            'Display changes in the remote branch only'), 
 
2821
                     'log-format',
 
2822
                     'show-ids',
 
2823
                     'verbose'
 
2824
                     ]
3062
2825
    encoding_type = 'replace'
3063
2826
 
3064
2827
    @display_command
3065
2828
    def run(self, other_branch=None, reverse=False, mine_only=False,
3066
2829
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
3067
 
            show_ids=False, verbose=False, this=False, other=False):
3068
 
        from bzrlib.missing import find_unmerged, iter_log_revisions
 
2830
            show_ids=False, verbose=False):
 
2831
        from bzrlib.missing import find_unmerged, iter_log_data
3069
2832
        from bzrlib.log import log_formatter
3070
 
 
3071
 
        if this:
3072
 
          mine_only = this
3073
 
        if other:
3074
 
          theirs_only = other
3075
 
 
3076
2833
        local_branch = Branch.open_containing(u".")[0]
3077
2834
        parent = local_branch.get_parent()
3078
2835
        if other_branch is None:
3079
2836
            other_branch = parent
3080
2837
            if other_branch is None:
3081
 
                raise errors.BzrCommandError("No peer location known"
3082
 
                                             " or specified.")
 
2838
                raise errors.BzrCommandError("No peer location known or specified.")
3083
2839
            display_url = urlutils.unescape_for_display(parent,
3084
2840
                                                        self.outf.encoding)
3085
 
            self.outf.write("Using last location: " + display_url + "\n")
 
2841
            print "Using last location: " + display_url
3086
2842
 
3087
2843
        remote_branch = Branch.open(other_branch)
3088
2844
        if remote_branch.base == local_branch.base:
3091
2847
        try:
3092
2848
            remote_branch.lock_read()
3093
2849
            try:
3094
 
                local_extra, remote_extra = find_unmerged(local_branch,
3095
 
                                                          remote_branch)
3096
 
                if log_format is None:
3097
 
                    registry = log.log_formatter_registry
3098
 
                    log_format = registry.get_default(local_branch)
 
2850
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
 
2851
                if (log_format is None):
 
2852
                    log_format = log.log_formatter_registry.get_default(
 
2853
                        local_branch)
3099
2854
                lf = log_format(to_file=self.outf,
3100
2855
                                show_ids=show_ids,
3101
2856
                                show_timezone='original')
3103
2858
                    local_extra.reverse()
3104
2859
                    remote_extra.reverse()
3105
2860
                if local_extra and not theirs_only:
3106
 
                    self.outf.write("You have %d extra revision(s):\n" %
3107
 
                                    len(local_extra))
3108
 
                    for revision in iter_log_revisions(local_extra,
3109
 
                                        local_branch.repository,
3110
 
                                        verbose):
3111
 
                        lf.log_revision(revision)
 
2861
                    print "You have %d extra revision(s):" % len(local_extra)
 
2862
                    for data in iter_log_data(local_extra, local_branch.repository,
 
2863
                                              verbose):
 
2864
                        lf.show(*data)
3112
2865
                    printed_local = True
3113
2866
                else:
3114
2867
                    printed_local = False
3115
2868
                if remote_extra and not mine_only:
3116
2869
                    if printed_local is True:
3117
 
                        self.outf.write("\n\n\n")
3118
 
                    self.outf.write("You are missing %d revision(s):\n" %
3119
 
                                    len(remote_extra))
3120
 
                    for revision in iter_log_revisions(remote_extra,
3121
 
                                        remote_branch.repository,
3122
 
                                        verbose):
3123
 
                        lf.log_revision(revision)
 
2870
                        print "\n\n"
 
2871
                    print "You are missing %d revision(s):" % len(remote_extra)
 
2872
                    for data in iter_log_data(remote_extra, remote_branch.repository, 
 
2873
                                              verbose):
 
2874
                        lf.show(*data)
3124
2875
                if not remote_extra and not local_extra:
3125
2876
                    status_code = 0
3126
 
                    self.outf.write("Branches are up to date.\n")
 
2877
                    print "Branches are up to date."
3127
2878
                else:
3128
2879
                    status_code = 1
3129
2880
            finally:
3141
2892
        return status_code
3142
2893
 
3143
2894
 
3144
 
class cmd_pack(Command):
3145
 
    """Compress the data within a repository."""
3146
 
 
3147
 
    _see_also = ['repositories']
3148
 
    takes_args = ['branch_or_repo?']
3149
 
 
3150
 
    def run(self, branch_or_repo='.'):
3151
 
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3152
 
        try:
3153
 
            branch = dir.open_branch()
3154
 
            repository = branch.repository
3155
 
        except errors.NotBranchError:
3156
 
            repository = dir.open_repository()
3157
 
        repository.pack()
3158
 
 
3159
 
 
3160
2895
class cmd_plugins(Command):
3161
 
    """List the installed plugins.
3162
 
    
3163
 
    This command displays the list of installed plugins including the
3164
 
    path where each one is located and a short description of each.
3165
 
 
3166
 
    A plugin is an external component for Bazaar that extends the
3167
 
    revision control system, by adding or replacing code in Bazaar.
3168
 
    Plugins can do a variety of things, including overriding commands,
3169
 
    adding new commands, providing additional network transports and
3170
 
    customizing log output.
3171
 
 
3172
 
    See the Bazaar web site, http://bazaar-vcs.org, for further
3173
 
    information on plugins including where to find them and how to
3174
 
    install them. Instructions are also provided there on how to
3175
 
    write new plugins using the Python programming language.
3176
 
    """
3177
 
 
 
2896
    """List plugins"""
 
2897
    hidden = True
3178
2898
    @display_command
3179
2899
    def run(self):
3180
2900
        import bzrlib.plugin
3194
2914
 
3195
2915
class cmd_testament(Command):
3196
2916
    """Show testament (signing-form) of a revision."""
3197
 
    takes_options = [
3198
 
            'revision',
3199
 
            Option('long', help='Produce long-format testament.'),
3200
 
            Option('strict',
3201
 
                   help='Produce a strict-format testament.')]
 
2917
    takes_options = ['revision', 
 
2918
                     Option('long', help='Produce long-format testament'), 
 
2919
                     Option('strict', help='Produce a strict-format'
 
2920
                            ' testament')]
3202
2921
    takes_args = ['branch?']
3203
2922
    @display_command
3204
2923
    def run(self, branch=u'.', revision=None, long=False, strict=False):
3237
2956
    #       with new uncommitted lines marked
3238
2957
    aliases = ['ann', 'blame', 'praise']
3239
2958
    takes_args = ['filename']
3240
 
    takes_options = [Option('all', help='Show annotations on all lines.'),
3241
 
                     Option('long', help='Show commit date in annotations.'),
 
2959
    takes_options = [Option('all', help='show annotations on all lines'),
 
2960
                     Option('long', help='show date in annotations'),
3242
2961
                     'revision',
3243
2962
                     'show-ids',
3244
2963
                     ]
3245
 
    encoding_type = 'exact'
3246
2964
 
3247
2965
    @display_command
3248
2966
    def run(self, filename, all=False, long=False, revision=None,
3259
2977
            else:
3260
2978
                revision_id = revision[0].in_history(branch).rev_id
3261
2979
            file_id = tree.path2id(relpath)
3262
 
            if file_id is None:
3263
 
                raise errors.NotVersionedError(filename)
3264
2980
            tree = branch.repository.revision_tree(revision_id)
3265
2981
            file_version = tree.inventory[file_id].revision
3266
 
            annotate_file(branch, file_version, file_id, long, all, self.outf,
 
2982
            annotate_file(branch, file_version, file_id, long, all, sys.stdout,
3267
2983
                          show_ids=show_ids)
3268
2984
        finally:
3269
2985
            branch.unlock()
3314
3030
 
3315
3031
    Once converted into a checkout, commits must succeed on the master branch
3316
3032
    before they will be applied to the local branch.
 
3033
 
 
3034
    See "help checkouts" for more information on checkouts.
3317
3035
    """
3318
3036
 
3319
 
    _see_also = ['checkouts', 'unbind']
3320
3037
    takes_args = ['location?']
3321
3038
    takes_options = []
3322
3039
 
3345
3062
 
3346
3063
    After unbinding, the local branch is considered independent and subsequent
3347
3064
    commits will be local only.
 
3065
 
 
3066
    See "help checkouts" for more information on checkouts.
3348
3067
    """
3349
3068
 
3350
 
    _see_also = ['checkouts', 'bind']
3351
3069
    takes_args = []
3352
3070
    takes_options = []
3353
3071
 
3372
3090
    # unreferenced information in 'branch-as-repository' branches.
3373
3091
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3374
3092
    # information in shared branches as well.
3375
 
    _see_also = ['commit']
3376
3093
    takes_options = ['verbose', 'revision',
3377
 
                    Option('dry-run', help='Don\'t actually make changes.'),
 
3094
                    Option('dry-run', help='Don\'t actually make changes'),
3378
3095
                    Option('force', help='Say yes to all questions.')]
3379
3096
    takes_args = ['location?']
3380
3097
    aliases = []
3484
3201
 
3485
3202
    takes_options = [
3486
3203
        Option('inet',
3487
 
               help='Serve on stdin/out for use from inetd or sshd.'),
 
3204
               help='serve on stdin/out for use from inetd or sshd'),
3488
3205
        Option('port',
3489
 
               help='Listen for connections on nominated port of the form '
3490
 
                    '[hostname:]portnumber.  Passing 0 as the port number will '
3491
 
                    'result in a dynamically allocated port.  The default port is '
 
3206
               help='listen for connections on nominated port of the form '
 
3207
                    '[hostname:]portnumber. Passing 0 as the port number will '
 
3208
                    'result in a dynamically allocated port. Default port is '
3492
3209
                    '4155.',
3493
3210
               type=str),
3494
3211
        Option('directory',
3495
 
               help='Serve contents of this directory.',
 
3212
               help='serve contents of directory',
3496
3213
               type=unicode),
3497
3214
        Option('allow-writes',
3498
 
               help='By default the server is a readonly server.  Supplying '
 
3215
               help='By default the server is a readonly server. Supplying '
3499
3216
                    '--allow-writes enables write access to the contents of '
3500
 
                    'the served directory and below.'
 
3217
                    'the served directory and below. '
3501
3218
                ),
3502
3219
        ]
3503
3220
 
3504
3221
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
3505
 
        from bzrlib.smart import medium, server
 
3222
        from bzrlib.transport import smart
3506
3223
        from bzrlib.transport import get_transport
3507
 
        from bzrlib.transport.chroot import ChrootServer
3508
 
        from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3509
3224
        if directory is None:
3510
3225
            directory = os.getcwd()
3511
3226
        url = urlutils.local_path_to_url(directory)
3512
3227
        if not allow_writes:
3513
3228
            url = 'readonly+' + url
3514
 
        chroot_server = ChrootServer(get_transport(url))
3515
 
        chroot_server.setUp()
3516
 
        t = get_transport(chroot_server.get_url())
 
3229
        t = get_transport(url)
3517
3230
        if inet:
3518
 
            smart_server = medium.SmartServerPipeStreamMedium(
3519
 
                sys.stdin, sys.stdout, t)
 
3231
            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
3520
3232
        else:
3521
 
            host = BZR_DEFAULT_INTERFACE
3522
3233
            if port is None:
3523
 
                port = BZR_DEFAULT_PORT
 
3234
                port = smart.BZR_DEFAULT_PORT
 
3235
                host = '127.0.0.1'
3524
3236
            else:
3525
3237
                if ':' in port:
3526
3238
                    host, port = port.split(':')
 
3239
                else:
 
3240
                    host = '127.0.0.1'
3527
3241
                port = int(port)
3528
 
            smart_server = server.SmartTCPServer(t, host=host, port=port)
3529
 
            print 'listening on port: ', smart_server.port
 
3242
            server = smart.SmartTCPServer(t, host=host, port=port)
 
3243
            print 'listening on port: ', server.port
3530
3244
            sys.stdout.flush()
3531
 
        # for the duration of this server, no UI output is permitted.
3532
 
        # note that this may cause problems with blackbox tests. This should
3533
 
        # be changed with care though, as we dont want to use bandwidth sending
3534
 
        # progress over stderr to smart server clients!
3535
 
        old_factory = ui.ui_factory
3536
 
        try:
3537
 
            ui.ui_factory = ui.SilentUIFactory()
3538
 
            smart_server.serve()
3539
 
        finally:
3540
 
            ui.ui_factory = old_factory
3541
 
 
 
3245
        server.serve()
3542
3246
 
3543
3247
class cmd_join(Command):
3544
3248
    """Combine a subtree into its containing tree.
3561
3265
    and merge, will recurse into the subtree.
3562
3266
    """
3563
3267
 
3564
 
    _see_also = ['split']
3565
3268
    takes_args = ['tree']
3566
 
    takes_options = [
3567
 
            Option('reference', help='Join by reference.'),
3568
 
            ]
 
3269
    takes_options = [Option('reference', 'join by reference')]
3569
3270
    hidden = True
3570
3271
 
3571
3272
    def run(self, tree, reference=False):
3605
3306
    subdirectory will be converted into an independent tree, with its own
3606
3307
    branch.  Commits in the top-level tree will not apply to the new subtree.
3607
3308
    If you want that behavior, do "bzr join --reference TREE".
 
3309
 
 
3310
    To undo this operation, do "bzr join TREE".
3608
3311
    """
3609
3312
 
3610
 
    _see_also = ['join']
3611
3313
    takes_args = ['tree']
3612
3314
 
3613
3315
    hidden = True
3643
3345
 
3644
3346
    takes_args = ['submit_branch?', 'public_branch?']
3645
3347
 
3646
 
    hidden = True
3647
 
 
3648
 
    _see_also = ['submit']
3649
 
 
3650
3348
    takes_options = [
3651
3349
        RegistryOption.from_kwargs('patch-type',
3652
3350
            'The type of patch to include in the directive',
3653
 
            title='Patch type',
3654
 
            value_switches=True,
3655
 
            enum_switch=False,
3656
 
            bundle='Bazaar revision bundle (default).',
3657
 
            diff='Normal unified diff.',
3658
 
            plain='No patch, just directive.'),
3659
 
        Option('sign', help='GPG-sign the directive.'), 'revision',
 
3351
            title='Patch type', value_switches=True, enum_switch=False,
 
3352
            bundle='Bazaar revision bundle (default)',
 
3353
            diff='Normal unified diff',
 
3354
            plain='No patch, just directive'),
 
3355
        Option('sign', help='GPG-sign the directive'), 'revision',
3660
3356
        Option('mail-to', type=str,
3661
 
            help='Instead of printing the directive, email to this address.'),
 
3357
            help='Instead of printing the directive, email to this address'),
3662
3358
        Option('message', type=str, short_name='m',
3663
 
            help='Message to use when committing this merge.')
 
3359
            help='Message to use when committing this merge')
3664
3360
        ]
3665
3361
 
3666
 
    encoding_type = 'exact'
3667
 
 
3668
3362
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3669
3363
            sign=False, revision=None, mail_to=None, message=None):
3670
 
        from bzrlib.revision import ensure_null, NULL_REVISION
3671
 
        include_patch, include_bundle = {
3672
 
            'plain': (False, False),
3673
 
            'diff': (True, False),
3674
 
            'bundle': (True, True),
3675
 
            }[patch_type]
 
3364
        if patch_type == 'plain':
 
3365
            patch_type = None
3676
3366
        branch = Branch.open('.')
3677
3367
        stored_submit_branch = branch.get_submit_branch()
3678
3368
        if submit_branch is None:
3690
3380
            public_branch = stored_public_branch
3691
3381
        elif stored_public_branch is None:
3692
3382
            branch.set_public_branch(public_branch)
3693
 
        if not include_bundle and public_branch is None:
 
3383
        if patch_type != "bundle" and public_branch is None:
3694
3384
            raise errors.BzrCommandError('No public branch specified or'
3695
3385
                                         ' known')
3696
 
        base_revision_id = None
3697
3386
        if revision is not None:
3698
 
            if len(revision) > 2:
 
3387
            if len(revision) != 1:
3699
3388
                raise errors.BzrCommandError('bzr merge-directive takes '
3700
 
                    'at most two one revision identifiers')
3701
 
            revision_id = revision[-1].in_history(branch).rev_id
3702
 
            if len(revision) == 2:
3703
 
                base_revision_id = revision[0].in_history(branch).rev_id
3704
 
                base_revision_id = ensure_null(base_revision_id)
 
3389
                    'exactly one revision identifier')
 
3390
            else:
 
3391
                revision_id = revision[0].in_history(branch).rev_id
3705
3392
        else:
3706
3393
            revision_id = branch.last_revision()
3707
 
        revision_id = ensure_null(revision_id)
3708
 
        if revision_id == NULL_REVISION:
3709
 
            raise errors.BzrCommandError('No revisions to bundle.')
3710
 
        directive = merge_directive.MergeDirective2.from_objects(
 
3394
        directive = merge_directive.MergeDirective.from_objects(
3711
3395
            branch.repository, revision_id, time.time(),
3712
3396
            osutils.local_time_offset(), submit_branch,
3713
 
            public_branch=public_branch, include_patch=include_patch,
3714
 
            include_bundle=include_bundle, message=message,
3715
 
            base_revision_id=base_revision_id)
 
3397
            public_branch=public_branch, patch_type=patch_type,
 
3398
            message=message)
3716
3399
        if mail_to is None:
3717
3400
            if sign:
3718
3401
                self.outf.write(directive.to_signed(branch))
3720
3403
                self.outf.writelines(directive.to_lines())
3721
3404
        else:
3722
3405
            message = directive.to_email(mail_to, branch, sign)
3723
 
            s = SMTPConnection(branch.get_config())
3724
 
            s.send_email(message)
3725
 
 
3726
 
 
3727
 
class cmd_submit(Command):
3728
 
    """Create a merge-directive for submiting changes.
3729
 
 
3730
 
    A merge directive provides many things needed for requesting merges:
3731
 
    - A machine-readable description of the merge to perform
3732
 
    - An optional patch that is a preview of the changes requested
3733
 
    - An optional bundle of revision data, so that the changes can be applied
3734
 
      directly from the merge directive, without retrieving data from a
3735
 
      branch.
3736
 
 
3737
 
    If --no-bundle is specified, then public_branch is needed (and must be
3738
 
    up-to-date), so that the receiver can perform the merge using the
3739
 
    public_branch.  The public_branch is always included if known, so that
3740
 
    people can check it later.
3741
 
 
3742
 
    The submit branch defaults to the parent, but can be overridden.  Both
3743
 
    submit branch and public branch will be remembered if supplied.
3744
 
 
3745
 
    If a public_branch is known for the submit_branch, that public submit
3746
 
    branch is used in the merge instructions.  This means that a local mirror
3747
 
    can be used as your actual submit branch, once you have set public_branch
3748
 
    for that mirror.
3749
 
    """
3750
 
 
3751
 
    encoding_type = 'exact'
3752
 
 
3753
 
    aliases = ['bundle', 'bundle-revisions']
3754
 
 
3755
 
    _see_also = ['merge']
3756
 
 
3757
 
    takes_args = ['submit_branch?', 'public_branch?']
3758
 
    takes_options = [
3759
 
        Option('no-bundle',
3760
 
               help='Do not include a bundle in the merge directive.'),
3761
 
        Option('no-patch', help='Do not include a preview patch in the merge'
3762
 
               ' directive.'),
3763
 
        Option('remember',
3764
 
               help='Remember submit and public branch.'),
3765
 
        Option('from',
3766
 
               help='Branch to generate the submission from, '
3767
 
               'rather than the one containing the working directory.',
3768
 
               short_name='f',
3769
 
               type=unicode),
3770
 
        Option('output', short_name='o', help='Write directive to this file.',
3771
 
               type=unicode),
3772
 
        'revision',
3773
 
        ]
3774
 
 
3775
 
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3776
 
            no_patch=False, revision=None, remember=False, output=None,
3777
 
            **kwargs):
3778
 
        from bzrlib.revision import ensure_null, NULL_REVISION
3779
 
        if output is None:
3780
 
            outfile = self.outf
3781
 
        else:
3782
 
            outfile = open(output, 'wb')
3783
 
        try:
3784
 
            from_ = kwargs.get('from', '.')
3785
 
            branch = Branch.open_containing(from_)[0]
3786
 
            if remember and submit_branch is None:
3787
 
                raise errors.BzrCommandError(
3788
 
                    '--remember requires a branch to be specified.')
3789
 
            stored_submit_branch = branch.get_submit_branch()
3790
 
            remembered_submit_branch = False
3791
 
            if submit_branch is None:
3792
 
                submit_branch = stored_submit_branch
3793
 
                remembered_submit_branch = True
3794
 
            else:
3795
 
                if stored_submit_branch is None or remember:
3796
 
                    branch.set_submit_branch(submit_branch)
3797
 
            if submit_branch is None:
3798
 
                submit_branch = branch.get_parent()
3799
 
                remembered_submit_branch = True
3800
 
            if submit_branch is None:
3801
 
                raise errors.BzrCommandError('No submit branch known or'
3802
 
                                             ' specified')
3803
 
            if remembered_submit_branch:
3804
 
                note('Using saved location: %s', submit_branch)
3805
 
 
3806
 
            stored_public_branch = branch.get_public_branch()
3807
 
            if public_branch is None:
3808
 
                public_branch = stored_public_branch
3809
 
            elif stored_public_branch is None or remember:
3810
 
                branch.set_public_branch(public_branch)
3811
 
            if no_bundle and public_branch is None:
3812
 
                raise errors.BzrCommandError('No public branch specified or'
3813
 
                                             ' known')
3814
 
            base_revision_id = None
3815
 
            if revision is not None:
3816
 
                if len(revision) > 2:
3817
 
                    raise errors.BzrCommandError('bzr submit takes '
3818
 
                        'at most two one revision identifiers')
3819
 
                revision_id = revision[-1].in_history(branch).rev_id
3820
 
                if len(revision) == 2:
3821
 
                    base_revision_id = revision[0].in_history(branch).rev_id
3822
 
                    base_revision_id = ensure_null(base_revision_id)
3823
 
            else:
3824
 
                revision_id = branch.last_revision()
3825
 
            revision_id = ensure_null(revision_id)
3826
 
            if revision_id == NULL_REVISION:
3827
 
                raise errors.BzrCommandError('No revisions to submit.')
3828
 
            directive = merge_directive.MergeDirective2.from_objects(
3829
 
                branch.repository, revision_id, time.time(),
3830
 
                osutils.local_time_offset(), submit_branch,
3831
 
                public_branch=public_branch, include_patch=not no_patch,
3832
 
                include_bundle=not no_bundle, message=None,
3833
 
                base_revision_id=base_revision_id)
3834
 
            outfile.writelines(directive.to_lines())
3835
 
        finally:
3836
 
            if output is not None:
3837
 
                outfile.close()
 
3406
            s = smtplib.SMTP()
 
3407
            server = branch.get_config().get_user_option('smtp_server')
 
3408
            if not server:
 
3409
                server = 'localhost'
 
3410
            s.connect()
 
3411
            s.sendmail(message['From'], message['To'], message.as_string())
 
3412
 
3838
3413
 
3839
3414
class cmd_tag(Command):
3840
3415
    """Create a tag naming a revision.
3850
3425
    --force, in which case the tag is moved to point to the new revision.
3851
3426
    """
3852
3427
 
3853
 
    _see_also = ['commit', 'tags']
3854
3428
    takes_args = ['tag_name']
3855
3429
    takes_options = [
3856
3430
        Option('delete',
3862
3436
            type=unicode,
3863
3437
            ),
3864
3438
        Option('force',
3865
 
            help='Replace existing tags.',
 
3439
            help='Replace existing tags',
3866
3440
            ),
3867
3441
        'revision',
3868
3442
        ]
3902
3476
    This tag shows a table of tag names and the revisions they reference.
3903
3477
    """
3904
3478
 
3905
 
    _see_also = ['tag']
3906
3479
    takes_options = [
3907
3480
        Option('directory',
3908
 
            help='Branch whose tags should be displayed.',
 
3481
            help='Branch whose tags should be displayed',
3909
3482
            short_name='d',
3910
3483
            type=unicode,
3911
3484
            ),
3920
3493
            self.outf.write('%-20s %s\n' % (tag_name, target))
3921
3494
 
3922
3495
 
3923
 
def _create_prefix(cur_transport):
3924
 
    needed = [cur_transport]
3925
 
    # Recurse upwards until we can create a directory successfully
3926
 
    while True:
3927
 
        new_transport = cur_transport.clone('..')
3928
 
        if new_transport.base == cur_transport.base:
3929
 
            raise errors.BzrCommandError(
3930
 
                "Failed to create path prefix for %s."
3931
 
                % cur_transport.base)
3932
 
        try:
3933
 
            new_transport.mkdir('.')
3934
 
        except errors.NoSuchFile:
3935
 
            needed.append(new_transport)
3936
 
            cur_transport = new_transport
3937
 
        else:
3938
 
            break
3939
 
    # Now we only need to create child directories
3940
 
    while needed:
3941
 
        cur_transport = needed.pop()
3942
 
        cur_transport.ensure_base()
3943
 
 
3944
 
 
3945
 
def _get_mergeable_helper(location):
3946
 
    """Get a merge directive or bundle if 'location' points to one.
3947
 
 
3948
 
    Try try to identify a bundle and returns its mergeable form. If it's not,
3949
 
    we return the tried transport anyway so that it can reused to access the
3950
 
    branch
3951
 
 
3952
 
    :param location: can point to a bundle or a branch.
3953
 
 
3954
 
    :return: mergeable, transport
 
3496
# command-line interpretation helper for merge-related commands
 
3497
def _merge_helper(other_revision, base_revision,
 
3498
                  check_clean=True, ignore_zero=False,
 
3499
                  this_dir=None, backup_files=False,
 
3500
                  merge_type=None,
 
3501
                  file_list=None, show_base=False, reprocess=False,
 
3502
                  pull=False,
 
3503
                  pb=DummyProgress(),
 
3504
                  change_reporter=None):
 
3505
    """Merge changes into a tree.
 
3506
 
 
3507
    base_revision
 
3508
        list(path, revno) Base for three-way merge.  
 
3509
        If [None, None] then a base will be automatically determined.
 
3510
    other_revision
 
3511
        list(path, revno) Other revision for three-way merge.
 
3512
    this_dir
 
3513
        Directory to merge changes into; '.' by default.
 
3514
    check_clean
 
3515
        If true, this_dir must have no uncommitted changes before the
 
3516
        merge begins.
 
3517
    ignore_zero - If true, suppress the "zero conflicts" message when 
 
3518
        there are no conflicts; should be set when doing something we expect
 
3519
        to complete perfectly.
 
3520
    file_list - If supplied, merge only changes to selected files.
 
3521
 
 
3522
    All available ancestors of other_revision and base_revision are
 
3523
    automatically pulled into the branch.
 
3524
 
 
3525
    The revno may be -1 to indicate the last revision on the branch, which is
 
3526
    the typical case.
 
3527
 
 
3528
    This function is intended for use from the command line; programmatic
 
3529
    clients might prefer to call merge.merge_inner(), which has less magic 
 
3530
    behavior.
3955
3531
    """
3956
 
    mergeable = None
3957
 
    url = urlutils.normalize_url(location)
3958
 
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
3959
 
    location_transport = transport.get_transport(url)
3960
 
    if filename:
3961
 
        try:
3962
 
            # There may be redirections but we ignore the intermediate
3963
 
            # and final transports used
3964
 
            read = bundle.read_mergeable_from_transport
3965
 
            mergeable, t = read(location_transport, filename)
3966
 
        except errors.NotABundle:
3967
 
            # Continue on considering this url a Branch but adjust the
3968
 
            # location_transport
3969
 
            location_transport = location_transport.clone(filename)
3970
 
    return mergeable, location_transport
 
3532
    # Loading it late, so that we don't always have to import bzrlib.merge
 
3533
    if merge_type is None:
 
3534
        merge_type = _mod_merge.Merge3Merger
 
3535
    if this_dir is None:
 
3536
        this_dir = u'.'
 
3537
    this_tree = WorkingTree.open_containing(this_dir)[0]
 
3538
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
3539
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
3540
                                     " type. %s" % merge_type)
 
3541
    if reprocess and not merge_type.supports_reprocess:
 
3542
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
3543
                                     " type %s." % merge_type)
 
3544
    if reprocess and show_base:
 
3545
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
 
3546
    # TODO: jam 20070226 We should really lock these trees earlier. However, we
 
3547
    #       only want to take out a lock_tree_write() if we don't have to pull
 
3548
    #       any ancestry. But merge might fetch ancestry in the middle, in
 
3549
    #       which case we would need a lock_write().
 
3550
    #       Because we cannot upgrade locks, for now we live with the fact that
 
3551
    #       the tree will be locked multiple times during a merge. (Maybe
 
3552
    #       read-only some of the time, but it means things will get read
 
3553
    #       multiple times.)
 
3554
    try:
 
3555
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
3556
                                   pb=pb, change_reporter=change_reporter)
 
3557
        merger.pp = ProgressPhase("Merge phase", 5, pb)
 
3558
        merger.pp.next_phase()
 
3559
        merger.check_basis(check_clean)
 
3560
        merger.set_other(other_revision)
 
3561
        merger.pp.next_phase()
 
3562
        merger.set_base(base_revision)
 
3563
        if merger.base_rev_id == merger.other_rev_id:
 
3564
            note('Nothing to do.')
 
3565
            return 0
 
3566
        if file_list is None:
 
3567
            if pull and merger.base_rev_id == merger.this_rev_id:
 
3568
                # FIXME: deduplicate with pull
 
3569
                result = merger.this_tree.pull(merger.this_branch,
 
3570
                        False, merger.other_rev_id)
 
3571
                if result.old_revid == result.new_revid:
 
3572
                    note('No revisions to pull.')
 
3573
                else:
 
3574
                    note('Now on revision %d.' % result.new_revno)
 
3575
                return 0
 
3576
        merger.backup_files = backup_files
 
3577
        merger.merge_type = merge_type 
 
3578
        merger.set_interesting_files(file_list)
 
3579
        merger.show_base = show_base 
 
3580
        merger.reprocess = reprocess
 
3581
        conflicts = merger.do_merge()
 
3582
        if file_list is None:
 
3583
            merger.set_pending()
 
3584
    finally:
 
3585
        pb.clear()
 
3586
    return conflicts
 
3587
 
 
3588
 
 
3589
# Compatibility
 
3590
merge = _merge_helper
3971
3591
 
3972
3592
 
3973
3593
# these get imported and then picked up by the scan for cmd_*
3977
3597
# details were needed.
3978
3598
from bzrlib.cmd_version_info import cmd_version_info
3979
3599
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3980
 
from bzrlib.bundle.commands import (
3981
 
    cmd_bundle_info,
3982
 
    )
 
3600
from bzrlib.bundle.commands import cmd_bundle_revisions
3983
3601
from bzrlib.sign_my_commits import cmd_sign_my_commits
3984
 
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
 
3602
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
3985
3603
        cmd_weave_plan_merge, cmd_weave_merge_text