~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Martin Pool
  • Date: 2010-02-25 06:17:27 UTC
  • mfrom: (5055 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5057.
  • Revision ID: mbp@sourcefrog.net-20100225061727-4sd9lt0qmdc6087t
merge news

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
20
20
 
21
21
from bzrlib.lazy_import import lazy_import
22
22
lazy_import(globals(), """
 
23
import codecs
23
24
import cStringIO
24
25
import sys
25
26
import time
32
33
    bzrdir,
33
34
    directory_service,
34
35
    delta,
35
 
    config as _mod_config,
 
36
    config,
36
37
    errors,
37
38
    globbing,
38
39
    hooks,
59
60
from bzrlib.workingtree import WorkingTree
60
61
""")
61
62
 
62
 
from bzrlib.commands import (
63
 
    Command,
64
 
    builtin_command_registry,
65
 
    display_command,
66
 
    )
 
63
from bzrlib.commands import Command, display_command
67
64
from bzrlib.option import (
68
65
    ListOption,
69
66
    Option,
74
71
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
75
72
 
76
73
 
77
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
74
def tree_files(file_list, default_branch=u'.', canonicalize=True,
79
75
    apply_view=True):
80
 
    return internal_tree_files(file_list, default_branch, canonicalize,
81
 
        apply_view)
 
76
    try:
 
77
        return internal_tree_files(file_list, default_branch, canonicalize,
 
78
            apply_view)
 
79
    except errors.FileInWrongBranch, e:
 
80
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
81
                                     (e.path, file_list[0]))
82
82
 
83
83
 
84
84
def tree_files_for_add(file_list):
148
148
 
149
149
# XXX: Bad function name; should possibly also be a class method of
150
150
# WorkingTree rather than a function.
151
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
152
151
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
153
152
    apply_view=True):
154
153
    """Convert command-line paths to a WorkingTree and relative paths.
155
154
 
156
 
    Deprecated: use WorkingTree.open_containing_paths instead.
157
 
 
158
155
    This is typically used for command-line processors that take one or
159
156
    more filenames, and infer the workingtree that contains them.
160
157
 
170
167
 
171
168
    :return: workingtree, [relative_paths]
172
169
    """
173
 
    return WorkingTree.open_containing_paths(
174
 
        file_list, default_directory='.',
175
 
        canonicalize=True,
176
 
        apply_view=True)
 
170
    if file_list is None or len(file_list) == 0:
 
171
        tree = WorkingTree.open_containing(default_branch)[0]
 
172
        if tree.supports_views() and apply_view:
 
173
            view_files = tree.views.lookup_view()
 
174
            if view_files:
 
175
                file_list = view_files
 
176
                view_str = views.view_display_str(view_files)
 
177
                note("Ignoring files outside view. View is %s" % view_str)
 
178
        return tree, file_list
 
179
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
 
180
    return tree, safe_relpath_files(tree, file_list, canonicalize,
 
181
        apply_view=apply_view)
 
182
 
 
183
 
 
184
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
 
185
    """Convert file_list into a list of relpaths in tree.
 
186
 
 
187
    :param tree: A tree to operate on.
 
188
    :param file_list: A list of user provided paths or None.
 
189
    :param apply_view: if True and a view is set, apply it or check that
 
190
        specified files are within it
 
191
    :return: A list of relative paths.
 
192
    :raises errors.PathNotChild: When a provided path is in a different tree
 
193
        than tree.
 
194
    """
 
195
    if file_list is None:
 
196
        return None
 
197
    if tree.supports_views() and apply_view:
 
198
        view_files = tree.views.lookup_view()
 
199
    else:
 
200
        view_files = []
 
201
    new_list = []
 
202
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
 
203
    # doesn't - fix that up here before we enter the loop.
 
204
    if canonicalize:
 
205
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
 
206
    else:
 
207
        fixer = tree.relpath
 
208
    for filename in file_list:
 
209
        try:
 
210
            relpath = fixer(osutils.dereference_path(filename))
 
211
            if  view_files and not osutils.is_inside_any(view_files, relpath):
 
212
                raise errors.FileOutsideView(filename, view_files)
 
213
            new_list.append(relpath)
 
214
        except errors.PathNotChild:
 
215
            raise errors.FileInWrongBranch(tree.branch, filename)
 
216
    return new_list
177
217
 
178
218
 
179
219
def _get_view_info_for_change_reporter(tree):
188
228
    return view_info
189
229
 
190
230
 
191
 
def _open_directory_or_containing_tree_or_branch(filename, directory):
192
 
    """Open the tree or branch containing the specified file, unless
193
 
    the --directory option is used to specify a different branch."""
194
 
    if directory is not None:
195
 
        return (None, Branch.open(directory), filename)
196
 
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
197
 
 
198
 
 
199
231
# TODO: Make sure no commands unconditionally use the working directory as a
200
232
# branch.  If a filename argument is used, the first of them should be used to
201
233
# specify the branch.  (Perhaps this can be factored out into some kind of
203
235
# opens the branch?)
204
236
 
205
237
class cmd_status(Command):
206
 
    __doc__ = """Display status summary.
 
238
    """Display status summary.
207
239
 
208
240
    This reports on versioned and unknown files, reporting them
209
241
    grouped by state.  Possible states are:
250
282
    To skip the display of pending merge information altogether, use
251
283
    the no-pending option or specify a file/directory.
252
284
 
253
 
    To compare the working directory to a specific revision, pass a
254
 
    single revision to the revision argument.
255
 
 
256
 
    To see which files have changed in a specific revision, or between
257
 
    two revisions, pass a revision range to the revision argument.
258
 
    This will produce the same results as calling 'bzr diff --summarize'.
 
285
    If a revision argument is given, the status is calculated against
 
286
    that revision, or between two revisions if two are provided.
259
287
    """
260
288
 
261
289
    # TODO: --no-recurse, --recurse options
283
311
            raise errors.BzrCommandError('bzr status --revision takes exactly'
284
312
                                         ' one or two revision specifiers')
285
313
 
286
 
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
 
314
        tree, relfile_list = tree_files(file_list)
287
315
        # Avoid asking for specific files when that is not needed.
288
316
        if relfile_list == ['']:
289
317
            relfile_list = None
300
328
 
301
329
 
302
330
class cmd_cat_revision(Command):
303
 
    __doc__ = """Write out metadata for a revision.
 
331
    """Write out metadata for a revision.
304
332
 
305
333
    The revision to print can either be specified by a specific
306
334
    revision identifier, or you can use --revision.
308
336
 
309
337
    hidden = True
310
338
    takes_args = ['revision_id?']
311
 
    takes_options = ['directory', 'revision']
 
339
    takes_options = ['revision']
312
340
    # cat-revision is more for frontends so should be exact
313
341
    encoding = 'strict'
314
342
 
321
349
        self.outf.write(revtext.decode('utf-8'))
322
350
 
323
351
    @display_command
324
 
    def run(self, revision_id=None, revision=None, directory=u'.'):
 
352
    def run(self, revision_id=None, revision=None):
325
353
        if revision_id is not None and revision is not None:
326
354
            raise errors.BzrCommandError('You can only supply one of'
327
355
                                         ' revision_id or --revision')
328
356
        if revision_id is None and revision is None:
329
357
            raise errors.BzrCommandError('You must supply either'
330
358
                                         ' --revision or a revision_id')
331
 
 
332
 
        b = bzrdir.BzrDir.open_containing_tree_or_branch(directory)[1]
 
359
        b = WorkingTree.open_containing(u'.')[0].branch
333
360
 
334
361
        revisions = b.repository.revisions
335
362
        if revisions is None:
359
386
        
360
387
 
361
388
class cmd_dump_btree(Command):
362
 
    __doc__ = """Dump the contents of a btree index file to stdout.
 
389
    """Dump the contents of a btree index file to stdout.
363
390
 
364
391
    PATH is a btree index file, it can be any URL. This includes things like
365
392
    .bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
413
440
                self.outf.write(page_bytes[:header_end])
414
441
                page_bytes = data
415
442
            self.outf.write('\nPage %d\n' % (page_idx,))
416
 
            if len(page_bytes) == 0:
417
 
                self.outf.write('(empty)\n');
418
 
            else:
419
 
                decomp_bytes = zlib.decompress(page_bytes)
420
 
                self.outf.write(decomp_bytes)
421
 
                self.outf.write('\n')
 
443
            decomp_bytes = zlib.decompress(page_bytes)
 
444
            self.outf.write(decomp_bytes)
 
445
            self.outf.write('\n')
422
446
 
423
447
    def _dump_entries(self, trans, basename):
424
448
        try:
432
456
        for node in bt.iter_all_entries():
433
457
            # Node is made up of:
434
458
            # (index, key, value, [references])
435
 
            try:
436
 
                refs = node[3]
437
 
            except IndexError:
438
 
                refs_as_tuples = None
439
 
            else:
440
 
                refs_as_tuples = static_tuple.as_tuples(refs)
 
459
            refs_as_tuples = static_tuple.as_tuples(node[3])
441
460
            as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
442
461
            self.outf.write('%s\n' % (as_tuple,))
443
462
 
444
463
 
445
464
class cmd_remove_tree(Command):
446
 
    __doc__ = """Remove the working tree from a given branch/checkout.
 
465
    """Remove the working tree from a given branch/checkout.
447
466
 
448
467
    Since a lightweight checkout is little more than a working tree
449
468
    this will refuse to run against one.
455
474
    takes_options = [
456
475
        Option('force',
457
476
               help='Remove the working tree even if it has '
458
 
                    'uncommitted or shelved changes.'),
 
477
                    'uncommitted changes.'),
459
478
        ]
460
479
 
461
480
    def run(self, location_list, force=False):
475
494
            if not force:
476
495
                if (working.has_changes()):
477
496
                    raise errors.UncommittedChanges(working)
478
 
                if working.get_shelf_manager().last_shelf() is not None:
479
 
                    raise errors.ShelvedChanges(working)
480
497
 
481
 
            if working.user_url != working.branch.user_url:
 
498
            working_path = working.bzrdir.root_transport.base
 
499
            branch_path = working.branch.bzrdir.root_transport.base
 
500
            if working_path != branch_path:
482
501
                raise errors.BzrCommandError("You cannot remove the working tree"
483
502
                                             " from a lightweight checkout")
484
503
 
485
504
            d.destroy_workingtree()
486
505
 
487
506
 
488
 
class cmd_repair_workingtree(Command):
489
 
    __doc__ = """Reset the working tree state file.
490
 
 
491
 
    This is not meant to be used normally, but more as a way to recover from
492
 
    filesystem corruption, etc. This rebuilds the working inventory back to a
493
 
    'known good' state. Any new modifications (adding a file, renaming, etc)
494
 
    will be lost, though modified files will still be detected as such.
495
 
 
496
 
    Most users will want something more like "bzr revert" or "bzr update"
497
 
    unless the state file has become corrupted.
498
 
 
499
 
    By default this attempts to recover the current state by looking at the
500
 
    headers of the state file. If the state file is too corrupted to even do
501
 
    that, you can supply --revision to force the state of the tree.
502
 
    """
503
 
 
504
 
    takes_options = ['revision', 'directory',
505
 
        Option('force',
506
 
               help='Reset the tree even if it doesn\'t appear to be'
507
 
                    ' corrupted.'),
508
 
    ]
509
 
    hidden = True
510
 
 
511
 
    def run(self, revision=None, directory='.', force=False):
512
 
        tree, _ = WorkingTree.open_containing(directory)
513
 
        self.add_cleanup(tree.lock_tree_write().unlock)
514
 
        if not force:
515
 
            try:
516
 
                tree.check_state()
517
 
            except errors.BzrError:
518
 
                pass # There seems to be a real error here, so we'll reset
519
 
            else:
520
 
                # Refuse
521
 
                raise errors.BzrCommandError(
522
 
                    'The tree does not appear to be corrupt. You probably'
523
 
                    ' want "bzr revert" instead. Use "--force" if you are'
524
 
                    ' sure you want to reset the working tree.')
525
 
        if revision is None:
526
 
            revision_ids = None
527
 
        else:
528
 
            revision_ids = [r.as_revision_id(tree.branch) for r in revision]
529
 
        try:
530
 
            tree.reset_state(revision_ids)
531
 
        except errors.BzrError, e:
532
 
            if revision_ids is None:
533
 
                extra = (', the header appears corrupt, try passing -r -1'
534
 
                         ' to set the state to the last commit')
535
 
            else:
536
 
                extra = ''
537
 
            raise errors.BzrCommandError('failed to reset the tree state'
538
 
                                         + extra)
539
 
 
540
 
 
541
507
class cmd_revno(Command):
542
 
    __doc__ = """Show current revision number.
 
508
    """Show current revision number.
543
509
 
544
510
    This is equal to the number of revisions on this branch.
545
511
    """
555
521
        if tree:
556
522
            try:
557
523
                wt = WorkingTree.open_containing(location)[0]
558
 
                self.add_cleanup(wt.lock_read().unlock)
 
524
                wt.lock_read()
559
525
            except (errors.NoWorkingTree, errors.NotLocalUrl):
560
526
                raise errors.NoWorkingTree(location)
 
527
            self.add_cleanup(wt.unlock)
561
528
            revid = wt.last_revision()
562
529
            try:
563
530
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
566
533
            revno = ".".join(str(n) for n in revno_t)
567
534
        else:
568
535
            b = Branch.open_containing(location)[0]
569
 
            self.add_cleanup(b.lock_read().unlock)
 
536
            b.lock_read()
 
537
            self.add_cleanup(b.unlock)
570
538
            revno = b.revno()
571
539
        self.cleanup_now()
572
540
        self.outf.write(str(revno) + '\n')
573
541
 
574
542
 
575
543
class cmd_revision_info(Command):
576
 
    __doc__ = """Show revision number and revision id for a given revision identifier.
 
544
    """Show revision number and revision id for a given revision identifier.
577
545
    """
578
546
    hidden = True
579
547
    takes_args = ['revision_info*']
580
548
    takes_options = [
581
549
        'revision',
582
 
        custom_help('directory',
 
550
        Option('directory',
583
551
            help='Branch to examine, '
584
 
                 'rather than the one containing the working directory.'),
 
552
                 'rather than the one containing the working directory.',
 
553
            short_name='d',
 
554
            type=unicode,
 
555
            ),
585
556
        Option('tree', help='Show revno of working tree'),
586
557
        ]
587
558
 
592
563
        try:
593
564
            wt = WorkingTree.open_containing(directory)[0]
594
565
            b = wt.branch
595
 
            self.add_cleanup(wt.lock_read().unlock)
 
566
            wt.lock_read()
 
567
            self.add_cleanup(wt.unlock)
596
568
        except (errors.NoWorkingTree, errors.NotLocalUrl):
597
569
            wt = None
598
570
            b = Branch.open_containing(directory)[0]
599
 
            self.add_cleanup(b.lock_read().unlock)
 
571
            b.lock_read()
 
572
            self.add_cleanup(b.unlock)
600
573
        revision_ids = []
601
574
        if revision is not None:
602
575
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
630
603
 
631
604
 
632
605
class cmd_add(Command):
633
 
    __doc__ = """Add specified files or directories.
 
606
    """Add specified files or directories.
634
607
 
635
608
    In non-recursive mode, all the named items are added, regardless
636
609
    of whether they were previously ignored.  A warning is given if
701
674
                should_print=(not is_quiet()))
702
675
 
703
676
        if base_tree:
704
 
            self.add_cleanup(base_tree.lock_read().unlock)
 
677
            base_tree.lock_read()
 
678
            self.add_cleanup(base_tree.unlock)
705
679
        tree, file_list = tree_files_for_add(file_list)
706
680
        added, ignored = tree.smart_add(file_list, not
707
681
            no_recurse, action=action, save=not dry_run)
715
689
 
716
690
 
717
691
class cmd_mkdir(Command):
718
 
    __doc__ = """Create a new versioned directory.
 
692
    """Create a new versioned directory.
719
693
 
720
694
    This is equivalent to creating the directory and then adding it.
721
695
    """
725
699
 
726
700
    def run(self, dir_list):
727
701
        for d in dir_list:
 
702
            os.mkdir(d)
728
703
            wt, dd = WorkingTree.open_containing(d)
729
 
            base = os.path.dirname(dd)
730
 
            id = wt.path2id(base)
731
 
            if id != None:
732
 
                os.mkdir(d)
733
 
                wt.add([dd])
734
 
                self.outf.write('added %s\n' % d)
735
 
            else:
736
 
                raise errors.NotVersionedError(path=base)
 
704
            wt.add([dd])
 
705
            self.outf.write('added %s\n' % d)
737
706
 
738
707
 
739
708
class cmd_relpath(Command):
740
 
    __doc__ = """Show path of a file relative to root"""
 
709
    """Show path of a file relative to root"""
741
710
 
742
711
    takes_args = ['filename']
743
712
    hidden = True
752
721
 
753
722
 
754
723
class cmd_inventory(Command):
755
 
    __doc__ = """Show inventory of the current working copy or a revision.
 
724
    """Show inventory of the current working copy or a revision.
756
725
 
757
726
    It is possible to limit the output to a particular entry
758
727
    type using the --kind option.  For example: --kind file.
778
747
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
779
748
 
780
749
        revision = _get_one_revision('inventory', revision)
781
 
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
782
 
        self.add_cleanup(work_tree.lock_read().unlock)
 
750
        work_tree, file_list = tree_files(file_list)
 
751
        work_tree.lock_read()
 
752
        self.add_cleanup(work_tree.unlock)
783
753
        if revision is not None:
784
754
            tree = revision.as_tree(work_tree.branch)
785
755
 
786
756
            extra_trees = [work_tree]
787
 
            self.add_cleanup(tree.lock_read().unlock)
 
757
            tree.lock_read()
 
758
            self.add_cleanup(tree.unlock)
788
759
        else:
789
760
            tree = work_tree
790
761
            extra_trees = []
811
782
 
812
783
 
813
784
class cmd_mv(Command):
814
 
    __doc__ = """Move or rename a file.
 
785
    """Move or rename a file.
815
786
 
816
787
    :Usage:
817
788
        bzr mv OLDNAME NEWNAME
849
820
            names_list = []
850
821
        if len(names_list) < 2:
851
822
            raise errors.BzrCommandError("missing file argument")
852
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
853
 
        self.add_cleanup(tree.lock_tree_write().unlock)
 
823
        tree, rel_names = tree_files(names_list, canonicalize=False)
 
824
        tree.lock_tree_write()
 
825
        self.add_cleanup(tree.unlock)
854
826
        self._run(tree, names_list, rel_names, after)
855
827
 
856
828
    def run_auto(self, names_list, after, dry_run):
860
832
        if after:
861
833
            raise errors.BzrCommandError('--after cannot be specified with'
862
834
                                         ' --auto.')
863
 
        work_tree, file_list = WorkingTree.open_containing_paths(
864
 
            names_list, default_directory='.')
865
 
        self.add_cleanup(work_tree.lock_tree_write().unlock)
 
835
        work_tree, file_list = tree_files(names_list, default_branch='.')
 
836
        work_tree.lock_tree_write()
 
837
        self.add_cleanup(work_tree.unlock)
866
838
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
867
839
 
868
840
    def _run(self, tree, names_list, rel_names, after):
947
919
 
948
920
 
949
921
class cmd_pull(Command):
950
 
    __doc__ = """Turn this branch into a mirror of another branch.
 
922
    """Turn this branch into a mirror of another branch.
951
923
 
952
924
    By default, this command only works on branches that have not diverged.
953
925
    Branches are considered diverged if the destination branch's most recent 
976
948
    takes_options = ['remember', 'overwrite', 'revision',
977
949
        custom_help('verbose',
978
950
            help='Show logs of pulled revisions.'),
979
 
        custom_help('directory',
 
951
        Option('directory',
980
952
            help='Branch to pull into, '
981
 
                 'rather than the one containing the working directory.'),
 
953
                 'rather than the one containing the working directory.',
 
954
            short_name='d',
 
955
            type=unicode,
 
956
            ),
982
957
        Option('local',
983
958
            help="Perform a local pull in a bound "
984
959
                 "branch.  Local pulls are not applied to "
985
960
                 "the master branch."
986
961
            ),
987
 
        Option('show-base',
988
 
            help="Show base revision text in conflicts.")
989
962
        ]
990
963
    takes_args = ['location?']
991
964
    encoding_type = 'replace'
992
965
 
993
966
    def run(self, location=None, remember=False, overwrite=False,
994
967
            revision=None, verbose=False,
995
 
            directory=None, local=False,
996
 
            show_base=False):
 
968
            directory=None, local=False):
997
969
        # FIXME: too much stuff is in the command class
998
970
        revision_id = None
999
971
        mergeable = None
1002
974
        try:
1003
975
            tree_to = WorkingTree.open_containing(directory)[0]
1004
976
            branch_to = tree_to.branch
1005
 
            self.add_cleanup(tree_to.lock_write().unlock)
1006
977
        except errors.NoWorkingTree:
1007
978
            tree_to = None
1008
979
            branch_to = Branch.open_containing(directory)[0]
1009
 
            self.add_cleanup(branch_to.lock_write().unlock)
1010
 
 
1011
 
        if tree_to is None and show_base:
1012
 
            raise errors.BzrCommandError("Need working tree for --show-base.")
1013
 
 
 
980
        
1014
981
        if local and not branch_to.get_bound_location():
1015
982
            raise errors.LocalRequiresBoundBranch()
1016
983
 
1046
1013
        else:
1047
1014
            branch_from = Branch.open(location,
1048
1015
                possible_transports=possible_transports)
1049
 
            self.add_cleanup(branch_from.lock_read().unlock)
1050
1016
 
1051
1017
            if branch_to.get_parent() is None or remember:
1052
1018
                branch_to.set_parent(branch_from.base)
1053
1019
 
 
1020
        if branch_from is not branch_to:
 
1021
            branch_from.lock_read()
 
1022
            self.add_cleanup(branch_from.unlock)
1054
1023
        if revision is not None:
1055
1024
            revision_id = revision.as_revision_id(branch_from)
1056
1025
 
 
1026
        branch_to.lock_write()
 
1027
        self.add_cleanup(branch_to.unlock)
1057
1028
        if tree_to is not None:
1058
1029
            view_info = _get_view_info_for_change_reporter(tree_to)
1059
1030
            change_reporter = delta._ChangeReporter(
1061
1032
                view_info=view_info)
1062
1033
            result = tree_to.pull(
1063
1034
                branch_from, overwrite, revision_id, change_reporter,
1064
 
                possible_transports=possible_transports, local=local,
1065
 
                show_base=show_base)
 
1035
                possible_transports=possible_transports, local=local)
1066
1036
        else:
1067
1037
            result = branch_to.pull(
1068
1038
                branch_from, overwrite, revision_id, local=local)
1072
1042
            log.show_branch_change(
1073
1043
                branch_to, self.outf, result.old_revno,
1074
1044
                result.old_revid)
1075
 
        if getattr(result, 'tag_conflicts', None):
1076
 
            return 1
1077
 
        else:
1078
 
            return 0
1079
1045
 
1080
1046
 
1081
1047
class cmd_push(Command):
1082
 
    __doc__ = """Update a mirror of this branch.
 
1048
    """Update a mirror of this branch.
1083
1049
 
1084
1050
    The target branch will not have its working tree populated because this
1085
1051
    is both expensive, and is not supported on remote file systems.
1109
1075
        Option('create-prefix',
1110
1076
               help='Create the path leading up to the branch '
1111
1077
                    'if it does not already exist.'),
1112
 
        custom_help('directory',
 
1078
        Option('directory',
1113
1079
            help='Branch to push from, '
1114
 
                 'rather than the one containing the working directory.'),
 
1080
                 'rather than the one containing the working directory.',
 
1081
            short_name='d',
 
1082
            type=unicode,
 
1083
            ),
1115
1084
        Option('use-existing-dir',
1116
1085
               help='By default push will fail if the target'
1117
1086
                    ' directory exists, but does not already'
1128
1097
        Option('strict',
1129
1098
               help='Refuse to push if there are uncommitted changes in'
1130
1099
               ' the working tree, --no-strict disables the check.'),
1131
 
        Option('no-tree',
1132
 
               help="Don't populate the working tree, even for protocols"
1133
 
               " that support it."),
1134
1100
        ]
1135
1101
    takes_args = ['location?']
1136
1102
    encoding_type = 'replace'
1138
1104
    def run(self, location=None, remember=False, overwrite=False,
1139
1105
        create_prefix=False, verbose=False, revision=None,
1140
1106
        use_existing_dir=False, directory=None, stacked_on=None,
1141
 
        stacked=False, strict=None, no_tree=False):
 
1107
        stacked=False, strict=None):
1142
1108
        from bzrlib.push import _show_push_branch
1143
1109
 
1144
1110
        if directory is None:
1146
1112
        # Get the source branch
1147
1113
        (tree, br_from,
1148
1114
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
 
1115
        if strict is None:
 
1116
            strict = br_from.get_config().get_user_option_as_bool('push_strict')
 
1117
        if strict is None: strict = True # default value
1149
1118
        # Get the tip's revision_id
1150
1119
        revision = _get_one_revision('push', revision)
1151
1120
        if revision is not None:
1152
1121
            revision_id = revision.in_history(br_from).rev_id
1153
1122
        else:
1154
1123
            revision_id = None
1155
 
        if tree is not None and revision_id is None:
1156
 
            tree.check_changed_or_out_of_date(
1157
 
                strict, 'push_strict',
1158
 
                more_error='Use --no-strict to force the push.',
1159
 
                more_warning='Uncommitted changes will not be pushed.')
 
1124
        if strict and tree is not None and revision_id is None:
 
1125
            if (tree.has_changes()):
 
1126
                raise errors.UncommittedChanges(
 
1127
                    tree, more='Use --no-strict to force the push.')
 
1128
            if tree.last_revision() != tree.branch.last_revision():
 
1129
                # The tree has lost sync with its branch, there is little
 
1130
                # chance that the user is aware of it but he can still force
 
1131
                # the push with --no-strict
 
1132
                raise errors.OutOfDateTree(
 
1133
                    tree, more='Use --no-strict to force the push.')
 
1134
 
1160
1135
        # Get the stacked_on branch, if any
1161
1136
        if stacked_on is not None:
1162
1137
            stacked_on = urlutils.normalize_url(stacked_on)
1190
1165
        _show_push_branch(br_from, revision_id, location, self.outf,
1191
1166
            verbose=verbose, overwrite=overwrite, remember=remember,
1192
1167
            stacked_on=stacked_on, create_prefix=create_prefix,
1193
 
            use_existing_dir=use_existing_dir, no_tree=no_tree)
 
1168
            use_existing_dir=use_existing_dir)
1194
1169
 
1195
1170
 
1196
1171
class cmd_branch(Command):
1197
 
    __doc__ = """Create a new branch that is a copy of an existing branch.
 
1172
    """Create a new branch that is a copy of an existing branch.
1198
1173
 
1199
1174
    If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1200
1175
    be used.  In other words, "branch ../foo/bar" will attempt to create ./bar.
1205
1180
 
1206
1181
    To retrieve the branch as of a particular revision, supply the --revision
1207
1182
    parameter, as in "branch foo/bar -r 5".
1208
 
 
1209
 
    The synonyms 'clone' and 'get' for this command are deprecated.
1210
1183
    """
1211
1184
 
1212
1185
    _see_also = ['checkout']
1213
1186
    takes_args = ['from_location', 'to_location?']
1214
 
    takes_options = ['revision',
1215
 
        Option('hardlink', help='Hard-link working tree files where possible.'),
1216
 
        Option('files-from', type=str,
1217
 
               help="Get file contents from this tree."),
 
1187
    takes_options = ['revision', Option('hardlink',
 
1188
        help='Hard-link working tree files where possible.'),
1218
1189
        Option('no-tree',
1219
1190
            help="Create a branch without a working-tree."),
1220
1191
        Option('switch',
1238
1209
 
1239
1210
    def run(self, from_location, to_location=None, revision=None,
1240
1211
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1241
 
            use_existing_dir=False, switch=False, bind=False,
1242
 
            files_from=None):
 
1212
            use_existing_dir=False, switch=False, bind=False):
1243
1213
        from bzrlib import switch as _mod_switch
1244
1214
        from bzrlib.tag import _merge_tags_if_possible
1245
 
        if self.invoked_as in ['get', 'clone']:
1246
 
            ui.ui_factory.show_user_warning(
1247
 
                'deprecated_command',
1248
 
                deprecated_name=self.invoked_as,
1249
 
                recommended_name='branch',
1250
 
                deprecated_in_version='2.4')
1251
1215
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1252
1216
            from_location)
1253
 
        if not (hardlink or files_from):
1254
 
            # accelerator_tree is usually slower because you have to read N
1255
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1256
 
            # explicitly request it
1257
 
            accelerator_tree = None
1258
 
        if files_from is not None and files_from != from_location:
1259
 
            accelerator_tree = WorkingTree.open(files_from)
1260
1217
        revision = _get_one_revision('branch', revision)
1261
 
        self.add_cleanup(br_from.lock_read().unlock)
 
1218
        br_from.lock_read()
 
1219
        self.add_cleanup(br_from.unlock)
1262
1220
        if revision is not None:
1263
1221
            revision_id = revision.as_revision_id(br_from)
1264
1222
        else:
1324
1282
 
1325
1283
 
1326
1284
class cmd_checkout(Command):
1327
 
    __doc__ = """Create a new checkout of an existing branch.
 
1285
    """Create a new checkout of an existing branch.
1328
1286
 
1329
1287
    If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1330
1288
    the branch found in '.'. This is useful if you have removed the working tree
1369
1327
            to_location = branch_location
1370
1328
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1371
1329
            branch_location)
1372
 
        if not (hardlink or files_from):
1373
 
            # accelerator_tree is usually slower because you have to read N
1374
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1375
 
            # explicitly request it
1376
 
            accelerator_tree = None
1377
1330
        revision = _get_one_revision('checkout', revision)
1378
 
        if files_from is not None and files_from != branch_location:
 
1331
        if files_from is not None:
1379
1332
            accelerator_tree = WorkingTree.open(files_from)
1380
1333
        if revision is not None:
1381
1334
            revision_id = revision.as_revision_id(source)
1398
1351
 
1399
1352
 
1400
1353
class cmd_renames(Command):
1401
 
    __doc__ = """Show list of renamed files.
 
1354
    """Show list of renamed files.
1402
1355
    """
1403
1356
    # TODO: Option to show renames between two historical versions.
1404
1357
 
1409
1362
    @display_command
1410
1363
    def run(self, dir=u'.'):
1411
1364
        tree = WorkingTree.open_containing(dir)[0]
1412
 
        self.add_cleanup(tree.lock_read().unlock)
 
1365
        tree.lock_read()
 
1366
        self.add_cleanup(tree.unlock)
1413
1367
        new_inv = tree.inventory
1414
1368
        old_tree = tree.basis_tree()
1415
 
        self.add_cleanup(old_tree.lock_read().unlock)
 
1369
        old_tree.lock_read()
 
1370
        self.add_cleanup(old_tree.unlock)
1416
1371
        old_inv = old_tree.inventory
1417
1372
        renames = []
1418
1373
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1428
1383
 
1429
1384
 
1430
1385
class cmd_update(Command):
1431
 
    __doc__ = """Update a tree to have the latest code committed to its branch.
 
1386
    """Update a tree to have the latest code committed to its branch.
1432
1387
 
1433
1388
    This will perform a merge into the working tree, and may generate
1434
1389
    conflicts. If you have any local changes, you will still
1437
1392
    If you want to discard your local changes, you can just do a
1438
1393
    'bzr revert' instead of 'bzr commit' after the update.
1439
1394
 
1440
 
    If you want to restore a file that has been removed locally, use
1441
 
    'bzr revert' instead of 'bzr update'.
1442
 
 
1443
1395
    If the tree's branch is bound to a master branch, it will also update
1444
1396
    the branch from the master.
1445
1397
    """
1446
1398
 
1447
1399
    _see_also = ['pull', 'working-trees', 'status-flags']
1448
1400
    takes_args = ['dir?']
1449
 
    takes_options = ['revision',
1450
 
                     Option('show-base',
1451
 
                            help="Show base revision text in conflicts."),
1452
 
                     ]
 
1401
    takes_options = ['revision']
1453
1402
    aliases = ['up']
1454
1403
 
1455
 
    def run(self, dir='.', revision=None, show_base=None):
 
1404
    def run(self, dir='.', revision=None):
1456
1405
        if revision is not None and len(revision) != 1:
1457
1406
            raise errors.BzrCommandError(
1458
1407
                        "bzr update --revision takes exactly one revision")
1462
1411
        master = branch.get_master_branch(
1463
1412
            possible_transports=possible_transports)
1464
1413
        if master is not None:
 
1414
            tree.lock_write()
1465
1415
            branch_location = master.base
1466
 
            tree.lock_write()
1467
1416
        else:
 
1417
            tree.lock_tree_write()
1468
1418
            branch_location = tree.branch.base
1469
 
            tree.lock_tree_write()
1470
1419
        self.add_cleanup(tree.unlock)
1471
1420
        # get rid of the final '/' and be ready for display
1472
 
        branch_location = urlutils.unescape_for_display(
1473
 
            branch_location.rstrip('/'),
1474
 
            self.outf.encoding)
 
1421
        branch_location = urlutils.unescape_for_display(branch_location[:-1],
 
1422
                                                        self.outf.encoding)
1475
1423
        existing_pending_merges = tree.get_parent_ids()[1:]
1476
1424
        if master is None:
1477
1425
            old_tip = None
1485
1433
        else:
1486
1434
            revision_id = branch.last_revision()
1487
1435
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1488
 
            revno = branch.revision_id_to_dotted_revno(revision_id)
1489
 
            note("Tree is up to date at revision %s of branch %s" %
1490
 
                ('.'.join(map(str, revno)), branch_location))
 
1436
            revno = branch.revision_id_to_revno(revision_id)
 
1437
            note("Tree is up to date at revision %d of branch %s" %
 
1438
                (revno, branch_location))
1491
1439
            return 0
1492
1440
        view_info = _get_view_info_for_change_reporter(tree)
1493
1441
        change_reporter = delta._ChangeReporter(
1498
1446
                change_reporter,
1499
1447
                possible_transports=possible_transports,
1500
1448
                revision=revision_id,
1501
 
                old_tip=old_tip,
1502
 
                show_base=show_base)
 
1449
                old_tip=old_tip)
1503
1450
        except errors.NoSuchRevision, e:
1504
1451
            raise errors.BzrCommandError(
1505
1452
                                  "branch has no revision %s\n"
1506
1453
                                  "bzr update --revision only works"
1507
1454
                                  " for a revision in the branch history"
1508
1455
                                  % (e.revision))
1509
 
        revno = tree.branch.revision_id_to_dotted_revno(
 
1456
        revno = tree.branch.revision_id_to_revno(
1510
1457
            _mod_revision.ensure_null(tree.last_revision()))
1511
 
        note('Updated to revision %s of branch %s' %
1512
 
             ('.'.join(map(str, revno)), branch_location))
1513
 
        parent_ids = tree.get_parent_ids()
1514
 
        if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
 
1458
        note('Updated to revision %d of branch %s' %
 
1459
             (revno, branch_location))
 
1460
        if tree.get_parent_ids()[1:] != existing_pending_merges:
1515
1461
            note('Your local commits will now show as pending merges with '
1516
1462
                 "'bzr status', and can be committed with 'bzr commit'.")
1517
1463
        if conflicts != 0:
1521
1467
 
1522
1468
 
1523
1469
class cmd_info(Command):
1524
 
    __doc__ = """Show information about a working tree, branch or repository.
 
1470
    """Show information about a working tree, branch or repository.
1525
1471
 
1526
1472
    This command will show all known locations and formats associated to the
1527
1473
    tree, branch or repository.
1565
1511
 
1566
1512
 
1567
1513
class cmd_remove(Command):
1568
 
    __doc__ = """Remove files or directories.
 
1514
    """Remove files or directories.
1569
1515
 
1570
 
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1571
 
    delete them if they can easily be recovered using revert otherwise they
1572
 
    will be backed up (adding an extention of the form .~#~). If no options or
1573
 
    parameters are given Bazaar will scan for files that are being tracked by
1574
 
    Bazaar but missing in your tree and stop tracking them for you.
 
1516
    This makes bzr stop tracking changes to the specified files. bzr will delete
 
1517
    them if they can easily be recovered using revert. If no options or
 
1518
    parameters are given bzr will scan for files that are being tracked by bzr
 
1519
    but missing in your tree and stop tracking them for you.
1575
1520
    """
1576
1521
    takes_args = ['file*']
1577
1522
    takes_options = ['verbose',
1579
1524
        RegistryOption.from_kwargs('file-deletion-strategy',
1580
1525
            'The file deletion mode to be used.',
1581
1526
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1582
 
            safe='Backup changed files (default).',
 
1527
            safe='Only delete files if they can be'
 
1528
                 ' safely recovered (default).',
1583
1529
            keep='Delete from bzr but leave the working copy.',
1584
 
            no_backup='Don\'t backup changed files.',
1585
1530
            force='Delete all the specified files, even if they can not be '
1586
 
                'recovered and even if they are non-empty directories. '
1587
 
                '(deprecated, use no-backup)')]
 
1531
                'recovered and even if they are non-empty directories.')]
1588
1532
    aliases = ['rm', 'del']
1589
1533
    encoding_type = 'replace'
1590
1534
 
1591
1535
    def run(self, file_list, verbose=False, new=False,
1592
1536
        file_deletion_strategy='safe'):
1593
 
        if file_deletion_strategy == 'force':
1594
 
            note("(The --force option is deprecated, rather use --no-backup "
1595
 
                "in future.)")
1596
 
            file_deletion_strategy = 'no-backup'
1597
 
 
1598
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
1537
        tree, file_list = tree_files(file_list)
1599
1538
 
1600
1539
        if file_list is not None:
1601
1540
            file_list = [f for f in file_list]
1602
1541
 
1603
 
        self.add_cleanup(tree.lock_write().unlock)
 
1542
        tree.lock_write()
 
1543
        self.add_cleanup(tree.unlock)
1604
1544
        # Heuristics should probably all move into tree.remove_smart or
1605
1545
        # some such?
1606
1546
        if new:
1621
1561
            file_deletion_strategy = 'keep'
1622
1562
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1623
1563
            keep_files=file_deletion_strategy=='keep',
1624
 
            force=(file_deletion_strategy=='no-backup'))
 
1564
            force=file_deletion_strategy=='force')
1625
1565
 
1626
1566
 
1627
1567
class cmd_file_id(Command):
1628
 
    __doc__ = """Print file_id of a particular file or directory.
 
1568
    """Print file_id of a particular file or directory.
1629
1569
 
1630
1570
    The file_id is assigned when the file is first added and remains the
1631
1571
    same through all revisions where the file exists, even when it is
1647
1587
 
1648
1588
 
1649
1589
class cmd_file_path(Command):
1650
 
    __doc__ = """Print path of file_ids to a file or directory.
 
1590
    """Print path of file_ids to a file or directory.
1651
1591
 
1652
1592
    This prints one line for each directory down to the target,
1653
1593
    starting at the branch root.
1669
1609
 
1670
1610
 
1671
1611
class cmd_reconcile(Command):
1672
 
    __doc__ = """Reconcile bzr metadata in a branch.
 
1612
    """Reconcile bzr metadata in a branch.
1673
1613
 
1674
1614
    This can correct data mismatches that may have been caused by
1675
1615
    previous ghost operations or bzr upgrades. You should only
1689
1629
 
1690
1630
    _see_also = ['check']
1691
1631
    takes_args = ['branch?']
1692
 
    takes_options = [
1693
 
        Option('canonicalize-chks',
1694
 
               help='Make sure CHKs are in canonical form (repairs '
1695
 
                    'bug 522637).',
1696
 
               hidden=True),
1697
 
        ]
1698
1632
 
1699
 
    def run(self, branch=".", canonicalize_chks=False):
 
1633
    def run(self, branch="."):
1700
1634
        from bzrlib.reconcile import reconcile
1701
1635
        dir = bzrdir.BzrDir.open(branch)
1702
 
        reconcile(dir, canonicalize_chks=canonicalize_chks)
 
1636
        reconcile(dir)
1703
1637
 
1704
1638
 
1705
1639
class cmd_revision_history(Command):
1706
 
    __doc__ = """Display the list of revision ids on a branch."""
 
1640
    """Display the list of revision ids on a branch."""
1707
1641
 
1708
1642
    _see_also = ['log']
1709
1643
    takes_args = ['location?']
1719
1653
 
1720
1654
 
1721
1655
class cmd_ancestry(Command):
1722
 
    __doc__ = """List all revisions merged into this branch."""
 
1656
    """List all revisions merged into this branch."""
1723
1657
 
1724
1658
    _see_also = ['log', 'revision-history']
1725
1659
    takes_args = ['location?']
1744
1678
 
1745
1679
 
1746
1680
class cmd_init(Command):
1747
 
    __doc__ = """Make a directory into a versioned branch.
 
1681
    """Make a directory into a versioned branch.
1748
1682
 
1749
1683
    Use this to create an empty branch, or before importing an
1750
1684
    existing project.
1782
1716
                ),
1783
1717
         Option('append-revisions-only',
1784
1718
                help='Never change revnos or the existing log.'
1785
 
                '  Append revisions to it only.'),
1786
 
         Option('no-tree',
1787
 
                'Create a branch without a working tree.')
 
1719
                '  Append revisions to it only.')
1788
1720
         ]
1789
1721
    def run(self, location=None, format=None, append_revisions_only=False,
1790
 
            create_prefix=False, no_tree=False):
 
1722
            create_prefix=False):
1791
1723
        if format is None:
1792
1724
            format = bzrdir.format_registry.make_bzrdir('default')
1793
1725
        if location is None:
1816
1748
        except errors.NotBranchError:
1817
1749
            # really a NotBzrDir error...
1818
1750
            create_branch = bzrdir.BzrDir.create_branch_convenience
1819
 
            if no_tree:
1820
 
                force_new_tree = False
1821
 
            else:
1822
 
                force_new_tree = None
1823
1751
            branch = create_branch(to_transport.base, format=format,
1824
 
                                   possible_transports=[to_transport],
1825
 
                                   force_new_tree=force_new_tree)
 
1752
                                   possible_transports=[to_transport])
1826
1753
            a_bzrdir = branch.bzrdir
1827
1754
        else:
1828
1755
            from bzrlib.transport.local import LocalTransport
1832
1759
                        raise errors.BranchExistsWithoutWorkingTree(location)
1833
1760
                raise errors.AlreadyBranchError(location)
1834
1761
            branch = a_bzrdir.create_branch()
1835
 
            if not no_tree:
1836
 
                a_bzrdir.create_workingtree()
 
1762
            a_bzrdir.create_workingtree()
1837
1763
        if append_revisions_only:
1838
1764
            try:
1839
1765
                branch.set_append_revisions_only(True)
1861
1787
 
1862
1788
 
1863
1789
class cmd_init_repository(Command):
1864
 
    __doc__ = """Create a shared repository for branches to share storage space.
 
1790
    """Create a shared repository for branches to share storage space.
1865
1791
 
1866
1792
    New branches created under the repository directory will store their
1867
1793
    revisions in the repository, not in the branch directory.  For branches
1921
1847
 
1922
1848
 
1923
1849
class cmd_diff(Command):
1924
 
    __doc__ = """Show differences in the working tree, between revisions or branches.
 
1850
    """Show differences in the working tree, between revisions or branches.
1925
1851
 
1926
1852
    If no arguments are given, all changes for the current tree are listed.
1927
1853
    If files are given, only the changes in those files are listed.
1933
1859
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1934
1860
    produces patches suitable for "patch -p1".
1935
1861
 
1936
 
    Note that when using the -r argument with a range of revisions, the
1937
 
    differences are computed between the two specified revisions.  That
1938
 
    is, the command does not show the changes introduced by the first 
1939
 
    revision in the range.  This differs from the interpretation of 
1940
 
    revision ranges used by "bzr log" which includes the first revision
1941
 
    in the range.
1942
 
 
1943
1862
    :Exit values:
1944
1863
        1 - changed
1945
1864
        2 - unrepresentable changes
1963
1882
 
1964
1883
            bzr diff -r1..3 xxx
1965
1884
 
1966
 
        The changes introduced by revision 2 (equivalent to -r1..2)::
1967
 
 
1968
 
            bzr diff -c2
1969
 
 
1970
 
        To see the changes introduced by revision X::
 
1885
        To see the changes introduced in revision X::
1971
1886
        
1972
1887
            bzr diff -cX
1973
1888
 
1977
1892
 
1978
1893
            bzr diff -r<chosen_parent>..X
1979
1894
 
1980
 
        The changes between the current revision and the previous revision
1981
 
        (equivalent to -c-1 and -r-2..-1)
 
1895
        The changes introduced by revision 2 (equivalent to -r1..2)::
1982
1896
 
1983
 
            bzr diff -r-2..
 
1897
            bzr diff -c2
1984
1898
 
1985
1899
        Show just the differences for file NEWS::
1986
1900
 
2001
1915
        Same as 'bzr diff' but prefix paths with old/ and new/::
2002
1916
 
2003
1917
            bzr diff --prefix old/:new/
2004
 
            
2005
 
        Show the differences using a custom diff program with options::
2006
 
        
2007
 
            bzr diff --using /usr/bin/diff --diff-options -wu
2008
1918
    """
2009
1919
    _see_also = ['status']
2010
1920
    takes_args = ['file*']
2029
1939
            help='Use this command to compare files.',
2030
1940
            type=unicode,
2031
1941
            ),
2032
 
        RegistryOption('format',
2033
 
            short_name='F',
2034
 
            help='Diff format to use.',
2035
 
            lazy_registry=('bzrlib.diff', 'format_registry'),
2036
 
            title='Diff format'),
2037
1942
        ]
2038
1943
    aliases = ['di', 'dif']
2039
1944
    encoding_type = 'exact'
2040
1945
 
2041
1946
    @display_command
2042
1947
    def run(self, revision=None, file_list=None, diff_options=None,
2043
 
            prefix=None, old=None, new=None, using=None, format=None):
2044
 
        from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2045
 
            show_diff_trees)
 
1948
            prefix=None, old=None, new=None, using=None):
 
1949
        from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
2046
1950
 
2047
1951
        if (prefix is None) or (prefix == '0'):
2048
1952
            # diff -p0 format
2062
1966
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
2063
1967
                                         ' one or two revision specifiers')
2064
1968
 
2065
 
        if using is not None and format is not None:
2066
 
            raise errors.BzrCommandError('--using and --format are mutually '
2067
 
                'exclusive.')
2068
 
 
2069
1969
        (old_tree, new_tree,
2070
1970
         old_branch, new_branch,
2071
 
         specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
2072
 
            file_list, revision, old, new, self.add_cleanup, apply_view=True)
2073
 
        # GNU diff on Windows uses ANSI encoding for filenames
2074
 
        path_encoding = osutils.get_diff_header_encoding()
 
1971
         specific_files, extra_trees) = get_trees_and_branches_to_diff(
 
1972
            file_list, revision, old, new, apply_view=True)
2075
1973
        return show_diff_trees(old_tree, new_tree, sys.stdout,
2076
1974
                               specific_files=specific_files,
2077
1975
                               external_diff_options=diff_options,
2078
1976
                               old_label=old_label, new_label=new_label,
2079
 
                               extra_trees=extra_trees,
2080
 
                               path_encoding=path_encoding,
2081
 
                               using=using,
2082
 
                               format_cls=format)
 
1977
                               extra_trees=extra_trees, using=using)
2083
1978
 
2084
1979
 
2085
1980
class cmd_deleted(Command):
2086
 
    __doc__ = """List files deleted in the working tree.
 
1981
    """List files deleted in the working tree.
2087
1982
    """
2088
1983
    # TODO: Show files deleted since a previous revision, or
2089
1984
    # between two revisions.
2092
1987
    # level of effort but possibly much less IO.  (Or possibly not,
2093
1988
    # if the directories are very large...)
2094
1989
    _see_also = ['status', 'ls']
2095
 
    takes_options = ['directory', 'show-ids']
 
1990
    takes_options = ['show-ids']
2096
1991
 
2097
1992
    @display_command
2098
 
    def run(self, show_ids=False, directory=u'.'):
2099
 
        tree = WorkingTree.open_containing(directory)[0]
2100
 
        self.add_cleanup(tree.lock_read().unlock)
 
1993
    def run(self, show_ids=False):
 
1994
        tree = WorkingTree.open_containing(u'.')[0]
 
1995
        tree.lock_read()
 
1996
        self.add_cleanup(tree.unlock)
2101
1997
        old = tree.basis_tree()
2102
 
        self.add_cleanup(old.lock_read().unlock)
 
1998
        old.lock_read()
 
1999
        self.add_cleanup(old.unlock)
2103
2000
        for path, ie in old.inventory.iter_entries():
2104
2001
            if not tree.has_id(ie.file_id):
2105
2002
                self.outf.write(path)
2110
2007
 
2111
2008
 
2112
2009
class cmd_modified(Command):
2113
 
    __doc__ = """List files modified in working tree.
 
2010
    """List files modified in working tree.
2114
2011
    """
2115
2012
 
2116
2013
    hidden = True
2117
2014
    _see_also = ['status', 'ls']
2118
 
    takes_options = ['directory', 'null']
 
2015
    takes_options = [
 
2016
            Option('null',
 
2017
                   help='Write an ascii NUL (\\0) separator '
 
2018
                   'between files rather than a newline.')
 
2019
            ]
2119
2020
 
2120
2021
    @display_command
2121
 
    def run(self, null=False, directory=u'.'):
2122
 
        tree = WorkingTree.open_containing(directory)[0]
2123
 
        self.add_cleanup(tree.lock_read().unlock)
 
2022
    def run(self, null=False):
 
2023
        tree = WorkingTree.open_containing(u'.')[0]
2124
2024
        td = tree.changes_from(tree.basis_tree())
2125
 
        self.cleanup_now()
2126
2025
        for path, id, kind, text_modified, meta_modified in td.modified:
2127
2026
            if null:
2128
2027
                self.outf.write(path + '\0')
2131
2030
 
2132
2031
 
2133
2032
class cmd_added(Command):
2134
 
    __doc__ = """List files added in working tree.
 
2033
    """List files added in working tree.
2135
2034
    """
2136
2035
 
2137
2036
    hidden = True
2138
2037
    _see_also = ['status', 'ls']
2139
 
    takes_options = ['directory', 'null']
 
2038
    takes_options = [
 
2039
            Option('null',
 
2040
                   help='Write an ascii NUL (\\0) separator '
 
2041
                   'between files rather than a newline.')
 
2042
            ]
2140
2043
 
2141
2044
    @display_command
2142
 
    def run(self, null=False, directory=u'.'):
2143
 
        wt = WorkingTree.open_containing(directory)[0]
2144
 
        self.add_cleanup(wt.lock_read().unlock)
 
2045
    def run(self, null=False):
 
2046
        wt = WorkingTree.open_containing(u'.')[0]
 
2047
        wt.lock_read()
 
2048
        self.add_cleanup(wt.unlock)
2145
2049
        basis = wt.basis_tree()
2146
 
        self.add_cleanup(basis.lock_read().unlock)
 
2050
        basis.lock_read()
 
2051
        self.add_cleanup(basis.unlock)
2147
2052
        basis_inv = basis.inventory
2148
2053
        inv = wt.inventory
2149
2054
        for file_id in inv:
2152
2057
            if inv.is_root(file_id) and len(basis_inv) == 0:
2153
2058
                continue
2154
2059
            path = inv.id2path(file_id)
2155
 
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
 
2060
            if not os.access(osutils.abspath(path), os.F_OK):
2156
2061
                continue
2157
2062
            if null:
2158
2063
                self.outf.write(path + '\0')
2161
2066
 
2162
2067
 
2163
2068
class cmd_root(Command):
2164
 
    __doc__ = """Show the tree root directory.
 
2069
    """Show the tree root directory.
2165
2070
 
2166
2071
    The root is the nearest enclosing directory with a .bzr control
2167
2072
    directory."""
2191
2096
 
2192
2097
 
2193
2098
class cmd_log(Command):
2194
 
    __doc__ = """Show historical log for a branch or subset of a branch.
 
2099
    """Show historical log for a branch or subset of a branch.
2195
2100
 
2196
2101
    log is bzr's default tool for exploring the history of a branch.
2197
2102
    The branch to use is taken from the first parameter. If no parameters
2358
2263
                   help='Show just the specified revision.'
2359
2264
                   ' See also "help revisionspec".'),
2360
2265
            'log-format',
2361
 
            RegistryOption('authors',
2362
 
                'What names to list as authors - first, all or committer.',
2363
 
                title='Authors',
2364
 
                lazy_registry=('bzrlib.log', 'author_list_registry'),
2365
 
            ),
2366
2266
            Option('levels',
2367
2267
                   short_name='n',
2368
2268
                   help='Number of levels to display - 0 for all, 1 for flat.',
2383
2283
                   help='Show changes made in each revision as a patch.'),
2384
2284
            Option('include-merges',
2385
2285
                   help='Show merged revisions like --levels 0 does.'),
2386
 
            Option('exclude-common-ancestry',
2387
 
                   help='Display only the revisions that are not part'
2388
 
                   ' of both ancestries (require -rX..Y)'
2389
 
                   )
2390
2286
            ]
2391
2287
    encoding_type = 'replace'
2392
2288
 
2402
2298
            message=None,
2403
2299
            limit=None,
2404
2300
            show_diff=False,
2405
 
            include_merges=False,
2406
 
            authors=None,
2407
 
            exclude_common_ancestry=False,
2408
 
            ):
 
2301
            include_merges=False):
2409
2302
        from bzrlib.log import (
2410
2303
            Logger,
2411
2304
            make_log_request_dict,
2412
2305
            _get_info_for_log_files,
2413
2306
            )
2414
2307
        direction = (forward and 'forward') or 'reverse'
2415
 
        if (exclude_common_ancestry
2416
 
            and (revision is None or len(revision) != 2)):
2417
 
            raise errors.BzrCommandError(
2418
 
                '--exclude-common-ancestry requires -r with two revisions')
2419
2308
        if include_merges:
2420
2309
            if levels is None:
2421
2310
                levels = 0
2437
2326
        if file_list:
2438
2327
            # find the file ids to log and check for directory filtering
2439
2328
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2440
 
                revision, file_list, self.add_cleanup)
 
2329
                revision, file_list)
 
2330
            self.add_cleanup(b.unlock)
2441
2331
            for relpath, file_id, kind in file_info_list:
2442
2332
                if file_id is None:
2443
2333
                    raise errors.BzrCommandError(
2461
2351
                location = '.'
2462
2352
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2463
2353
            b = dir.open_branch()
2464
 
            self.add_cleanup(b.lock_read().unlock)
 
2354
            b.lock_read()
 
2355
            self.add_cleanup(b.unlock)
2465
2356
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2466
2357
 
2467
2358
        # Decide on the type of delta & diff filtering to use
2487
2378
                        show_timezone=timezone,
2488
2379
                        delta_format=get_verbosity_level(),
2489
2380
                        levels=levels,
2490
 
                        show_advice=levels is None,
2491
 
                        author_list_handler=authors)
 
2381
                        show_advice=levels is None)
2492
2382
 
2493
2383
        # Choose the algorithm for doing the logging. It's annoying
2494
2384
        # having multiple code paths like this but necessary until
2513
2403
            direction=direction, specific_fileids=file_ids,
2514
2404
            start_revision=rev1, end_revision=rev2, limit=limit,
2515
2405
            message_search=message, delta_type=delta_type,
2516
 
            diff_type=diff_type, _match_using_deltas=match_using_deltas,
2517
 
            exclude_common_ancestry=exclude_common_ancestry,
2518
 
            )
 
2406
            diff_type=diff_type, _match_using_deltas=match_using_deltas)
2519
2407
        Logger(b, rqst).show(lf)
2520
2408
 
2521
2409
 
2540
2428
            raise errors.BzrCommandError(
2541
2429
                "bzr %s doesn't accept two revisions in different"
2542
2430
                " branches." % command_name)
2543
 
        if start_spec.spec is None:
2544
 
            # Avoid loading all the history.
2545
 
            rev1 = RevisionInfo(branch, None, None)
2546
 
        else:
2547
 
            rev1 = start_spec.in_history(branch)
 
2431
        rev1 = start_spec.in_history(branch)
2548
2432
        # Avoid loading all of history when we know a missing
2549
2433
        # end of range means the last revision ...
2550
2434
        if end_spec.spec is None:
2579
2463
 
2580
2464
 
2581
2465
class cmd_touching_revisions(Command):
2582
 
    __doc__ = """Return revision-ids which affected a particular file.
 
2466
    """Return revision-ids which affected a particular file.
2583
2467
 
2584
2468
    A more user-friendly interface is "bzr log FILE".
2585
2469
    """
2592
2476
        tree, relpath = WorkingTree.open_containing(filename)
2593
2477
        file_id = tree.path2id(relpath)
2594
2478
        b = tree.branch
2595
 
        self.add_cleanup(b.lock_read().unlock)
 
2479
        b.lock_read()
 
2480
        self.add_cleanup(b.unlock)
2596
2481
        touching_revs = log.find_touching_revisions(b, file_id)
2597
2482
        for revno, revision_id, what in touching_revs:
2598
2483
            self.outf.write("%6d %s\n" % (revno, what))
2599
2484
 
2600
2485
 
2601
2486
class cmd_ls(Command):
2602
 
    __doc__ = """List files in a tree.
 
2487
    """List files in a tree.
2603
2488
    """
2604
2489
 
2605
2490
    _see_also = ['status', 'cat']
2611
2496
                   help='Recurse into subdirectories.'),
2612
2497
            Option('from-root',
2613
2498
                   help='Print paths relative to the root of the branch.'),
2614
 
            Option('unknown', short_name='u',
2615
 
                help='Print unknown files.'),
 
2499
            Option('unknown', help='Print unknown files.'),
2616
2500
            Option('versioned', help='Print versioned files.',
2617
2501
                   short_name='V'),
2618
 
            Option('ignored', short_name='i',
2619
 
                help='Print ignored files.'),
2620
 
            Option('kind', short_name='k',
 
2502
            Option('ignored', help='Print ignored files.'),
 
2503
            Option('null',
 
2504
                   help='Write an ascii NUL (\\0) separator '
 
2505
                   'between files rather than a newline.'),
 
2506
            Option('kind',
2621
2507
                   help='List entries of a particular kind: file, directory, symlink.',
2622
2508
                   type=unicode),
2623
 
            'null',
2624
2509
            'show-ids',
2625
 
            'directory',
2626
2510
            ]
2627
2511
    @display_command
2628
2512
    def run(self, revision=None, verbose=False,
2629
2513
            recursive=False, from_root=False,
2630
2514
            unknown=False, versioned=False, ignored=False,
2631
 
            null=False, kind=None, show_ids=False, path=None, directory=None):
 
2515
            null=False, kind=None, show_ids=False, path=None):
2632
2516
 
2633
2517
        if kind and kind not in ('file', 'directory', 'symlink'):
2634
2518
            raise errors.BzrCommandError('invalid kind specified')
2646
2530
                raise errors.BzrCommandError('cannot specify both --from-root'
2647
2531
                                             ' and PATH')
2648
2532
            fs_path = path
2649
 
        tree, branch, relpath = \
2650
 
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
 
2533
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2534
            fs_path)
2651
2535
 
2652
2536
        # Calculate the prefix to use
2653
2537
        prefix = None
2668
2552
                view_str = views.view_display_str(view_files)
2669
2553
                note("Ignoring files outside view. View is %s" % view_str)
2670
2554
 
2671
 
        self.add_cleanup(tree.lock_read().unlock)
 
2555
        tree.lock_read()
 
2556
        self.add_cleanup(tree.unlock)
2672
2557
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2673
2558
            from_dir=relpath, recursive=recursive):
2674
2559
            # Apply additional masking
2716
2601
 
2717
2602
 
2718
2603
class cmd_unknowns(Command):
2719
 
    __doc__ = """List unknown files.
 
2604
    """List unknown files.
2720
2605
    """
2721
2606
 
2722
2607
    hidden = True
2723
2608
    _see_also = ['ls']
2724
 
    takes_options = ['directory']
2725
2609
 
2726
2610
    @display_command
2727
 
    def run(self, directory=u'.'):
2728
 
        for f in WorkingTree.open_containing(directory)[0].unknowns():
 
2611
    def run(self):
 
2612
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
2729
2613
            self.outf.write(osutils.quotefn(f) + '\n')
2730
2614
 
2731
2615
 
2732
2616
class cmd_ignore(Command):
2733
 
    __doc__ = """Ignore specified files or patterns.
 
2617
    """Ignore specified files or patterns.
2734
2618
 
2735
2619
    See ``bzr help patterns`` for details on the syntax of patterns.
2736
2620
 
2745
2629
    using this command or directly by using an editor, be sure to commit
2746
2630
    it.
2747
2631
    
2748
 
    Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2749
 
    the global ignore file can be found in the application data directory as
2750
 
    C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2751
 
    Global ignores are not touched by this command. The global ignore file
2752
 
    can be edited directly using an editor.
2753
 
 
2754
2632
    Patterns prefixed with '!' are exceptions to ignore patterns and take
2755
2633
    precedence over regular ignores.  Such exceptions are used to specify
2756
2634
    files that should be versioned which would otherwise be ignored.
2758
2636
    Patterns prefixed with '!!' act as regular ignore patterns, but have
2759
2637
    precedence over the '!' exception patterns.
2760
2638
 
2761
 
    :Notes: 
2762
 
        
2763
 
    * Ignore patterns containing shell wildcards must be quoted from
2764
 
      the shell on Unix.
2765
 
 
2766
 
    * Ignore patterns starting with "#" act as comments in the ignore file.
2767
 
      To ignore patterns that begin with that character, use the "RE:" prefix.
 
2639
    Note: ignore patterns containing shell wildcards must be quoted from
 
2640
    the shell on Unix.
2768
2641
 
2769
2642
    :Examples:
2770
2643
        Ignore the top level Makefile::
2779
2652
 
2780
2653
            bzr ignore "!special.class"
2781
2654
 
2782
 
        Ignore files whose name begins with the "#" character::
2783
 
 
2784
 
            bzr ignore "RE:^#"
2785
 
 
2786
2655
        Ignore .o files under the lib directory::
2787
2656
 
2788
2657
            bzr ignore "lib/**/*.o"
2796
2665
            bzr ignore "RE:(?!debian/).*"
2797
2666
        
2798
2667
        Ignore everything except the "local" toplevel directory,
2799
 
        but always ignore autosave files ending in ~, even under local/::
 
2668
        but always ignore "*~" autosave files, even under local/::
2800
2669
        
2801
2670
            bzr ignore "*"
2802
2671
            bzr ignore "!./local"
2805
2674
 
2806
2675
    _see_also = ['status', 'ignored', 'patterns']
2807
2676
    takes_args = ['name_pattern*']
2808
 
    takes_options = ['directory',
2809
 
        Option('default-rules',
2810
 
               help='Display the default ignore rules that bzr uses.')
 
2677
    takes_options = [
 
2678
        Option('old-default-rules',
 
2679
               help='Write out the ignore rules bzr < 0.9 always used.')
2811
2680
        ]
2812
2681
 
2813
 
    def run(self, name_pattern_list=None, default_rules=None,
2814
 
            directory=u'.'):
 
2682
    def run(self, name_pattern_list=None, old_default_rules=None):
2815
2683
        from bzrlib import ignores
2816
 
        if default_rules is not None:
2817
 
            # dump the default rules and exit
2818
 
            for pattern in ignores.USER_DEFAULTS:
2819
 
                self.outf.write("%s\n" % pattern)
 
2684
        if old_default_rules is not None:
 
2685
            # dump the rules and exit
 
2686
            for pattern in ignores.OLD_DEFAULTS:
 
2687
                print pattern
2820
2688
            return
2821
2689
        if not name_pattern_list:
2822
2690
            raise errors.BzrCommandError("ignore requires at least one "
2823
 
                "NAME_PATTERN or --default-rules.")
 
2691
                                  "NAME_PATTERN or --old-default-rules")
2824
2692
        name_pattern_list = [globbing.normalize_pattern(p)
2825
2693
                             for p in name_pattern_list]
2826
 
        bad_patterns = ''
2827
 
        for p in name_pattern_list:
2828
 
            if not globbing.Globster.is_pattern_valid(p):
2829
 
                bad_patterns += ('\n  %s' % p)
2830
 
        if bad_patterns:
2831
 
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2832
 
            ui.ui_factory.show_error(msg)
2833
 
            raise errors.InvalidPattern('')
2834
2694
        for name_pattern in name_pattern_list:
2835
2695
            if (name_pattern[0] == '/' or
2836
2696
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2837
2697
                raise errors.BzrCommandError(
2838
2698
                    "NAME_PATTERN should not be an absolute path")
2839
 
        tree, relpath = WorkingTree.open_containing(directory)
 
2699
        tree, relpath = WorkingTree.open_containing(u'.')
2840
2700
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2841
2701
        ignored = globbing.Globster(name_pattern_list)
2842
2702
        matches = []
2843
 
        self.add_cleanup(tree.lock_read().unlock)
 
2703
        tree.lock_read()
2844
2704
        for entry in tree.list_files():
2845
2705
            id = entry[3]
2846
2706
            if id is not None:
2847
2707
                filename = entry[0]
2848
2708
                if ignored.match(filename):
2849
 
                    matches.append(filename)
 
2709
                    matches.append(filename.encode('utf-8'))
 
2710
        tree.unlock()
2850
2711
        if len(matches) > 0:
2851
 
            self.outf.write("Warning: the following files are version controlled and"
2852
 
                  " match your ignore pattern:\n%s"
2853
 
                  "\nThese files will continue to be version controlled"
2854
 
                  " unless you 'bzr remove' them.\n" % ("\n".join(matches),))
 
2712
            print "Warning: the following files are version controlled and" \
 
2713
                  " match your ignore pattern:\n%s" \
 
2714
                  "\nThese files will continue to be version controlled" \
 
2715
                  " unless you 'bzr remove' them." % ("\n".join(matches),)
2855
2716
 
2856
2717
 
2857
2718
class cmd_ignored(Command):
2858
 
    __doc__ = """List ignored files and the patterns that matched them.
 
2719
    """List ignored files and the patterns that matched them.
2859
2720
 
2860
2721
    List all the ignored files and the ignore pattern that caused the file to
2861
2722
    be ignored.
2867
2728
 
2868
2729
    encoding_type = 'replace'
2869
2730
    _see_also = ['ignore', 'ls']
2870
 
    takes_options = ['directory']
2871
2731
 
2872
2732
    @display_command
2873
 
    def run(self, directory=u'.'):
2874
 
        tree = WorkingTree.open_containing(directory)[0]
2875
 
        self.add_cleanup(tree.lock_read().unlock)
 
2733
    def run(self):
 
2734
        tree = WorkingTree.open_containing(u'.')[0]
 
2735
        tree.lock_read()
 
2736
        self.add_cleanup(tree.unlock)
2876
2737
        for path, file_class, kind, file_id, entry in tree.list_files():
2877
2738
            if file_class != 'I':
2878
2739
                continue
2882
2743
 
2883
2744
 
2884
2745
class cmd_lookup_revision(Command):
2885
 
    __doc__ = """Lookup the revision-id from a revision-number
 
2746
    """Lookup the revision-id from a revision-number
2886
2747
 
2887
2748
    :Examples:
2888
2749
        bzr lookup-revision 33
2889
2750
    """
2890
2751
    hidden = True
2891
2752
    takes_args = ['revno']
2892
 
    takes_options = ['directory']
2893
2753
 
2894
2754
    @display_command
2895
 
    def run(self, revno, directory=u'.'):
 
2755
    def run(self, revno):
2896
2756
        try:
2897
2757
            revno = int(revno)
2898
2758
        except ValueError:
2899
 
            raise errors.BzrCommandError("not a valid revision-number: %r"
2900
 
                                         % revno)
2901
 
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2902
 
        self.outf.write("%s\n" % revid)
 
2759
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
 
2760
 
 
2761
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2903
2762
 
2904
2763
 
2905
2764
class cmd_export(Command):
2906
 
    __doc__ = """Export current or past revision to a destination directory or archive.
 
2765
    """Export current or past revision to a destination directory or archive.
2907
2766
 
2908
2767
    If no revision is specified this exports the last committed revision.
2909
2768
 
2930
2789
         zip                          .zip
2931
2790
      =================       =========================
2932
2791
    """
2933
 
    encoding = 'exact'
2934
2792
    takes_args = ['dest', 'branch_or_subdir?']
2935
 
    takes_options = ['directory',
 
2793
    takes_options = [
2936
2794
        Option('format',
2937
2795
               help="Type of file to export to.",
2938
2796
               type=unicode),
2942
2800
        Option('root',
2943
2801
               type=str,
2944
2802
               help="Name of the root directory inside the exported file."),
2945
 
        Option('per-file-timestamps',
2946
 
               help='Set modification time of files to that of the last '
2947
 
                    'revision in which it was changed.'),
2948
2803
        ]
2949
2804
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2950
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
2805
        root=None, filters=False):
2951
2806
        from bzrlib.export import export
2952
2807
 
2953
2808
        if branch_or_subdir is None:
2954
 
            tree = WorkingTree.open_containing(directory)[0]
 
2809
            tree = WorkingTree.open_containing(u'.')[0]
2955
2810
            b = tree.branch
2956
2811
            subdir = None
2957
2812
        else:
2960
2815
 
2961
2816
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2962
2817
        try:
2963
 
            export(rev_tree, dest, format, root, subdir, filtered=filters,
2964
 
                   per_file_timestamps=per_file_timestamps)
 
2818
            export(rev_tree, dest, format, root, subdir, filtered=filters)
2965
2819
        except errors.NoSuchExportFormat, e:
2966
2820
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2967
2821
 
2968
2822
 
2969
2823
class cmd_cat(Command):
2970
 
    __doc__ = """Write the contents of a file as of a given revision to standard output.
 
2824
    """Write the contents of a file as of a given revision to standard output.
2971
2825
 
2972
2826
    If no revision is nominated, the last revision is used.
2973
2827
 
2976
2830
    """
2977
2831
 
2978
2832
    _see_also = ['ls']
2979
 
    takes_options = ['directory',
 
2833
    takes_options = [
2980
2834
        Option('name-from-revision', help='The path name in the old tree.'),
2981
2835
        Option('filters', help='Apply content filters to display the '
2982
2836
                'convenience form.'),
2987
2841
 
2988
2842
    @display_command
2989
2843
    def run(self, filename, revision=None, name_from_revision=False,
2990
 
            filters=False, directory=None):
 
2844
            filters=False):
2991
2845
        if revision is not None and len(revision) != 1:
2992
2846
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2993
2847
                                         " one revision specifier")
2994
2848
        tree, branch, relpath = \
2995
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
2996
 
        self.add_cleanup(branch.lock_read().unlock)
 
2849
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
2850
        branch.lock_read()
 
2851
        self.add_cleanup(branch.unlock)
2997
2852
        return self._run(tree, branch, relpath, filename, revision,
2998
2853
                         name_from_revision, filters)
2999
2854
 
3002
2857
        if tree is None:
3003
2858
            tree = b.basis_tree()
3004
2859
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3005
 
        self.add_cleanup(rev_tree.lock_read().unlock)
 
2860
        rev_tree.lock_read()
 
2861
        self.add_cleanup(rev_tree.unlock)
3006
2862
 
3007
2863
        old_file_id = rev_tree.path2id(relpath)
3008
2864
 
3051
2907
 
3052
2908
 
3053
2909
class cmd_local_time_offset(Command):
3054
 
    __doc__ = """Show the offset in seconds from GMT to local time."""
 
2910
    """Show the offset in seconds from GMT to local time."""
3055
2911
    hidden = True
3056
2912
    @display_command
3057
2913
    def run(self):
3058
 
        self.outf.write("%s\n" % osutils.local_time_offset())
 
2914
        print osutils.local_time_offset()
3059
2915
 
3060
2916
 
3061
2917
 
3062
2918
class cmd_commit(Command):
3063
 
    __doc__ = """Commit changes into a new revision.
 
2919
    """Commit changes into a new revision.
3064
2920
 
3065
2921
    An explanatory message needs to be given for each commit. This is
3066
2922
    often done by using the --message option (getting the message from the
3114
2970
      to trigger updates to external systems like bug trackers. The --fixes
3115
2971
      option can be used to record the association between a revision and
3116
2972
      one or more bugs. See ``bzr help bugs`` for details.
 
2973
 
 
2974
      A selective commit may fail in some cases where the committed
 
2975
      tree would be invalid. Consider::
 
2976
  
 
2977
        bzr init foo
 
2978
        mkdir foo/bar
 
2979
        bzr add foo/bar
 
2980
        bzr commit foo -m "committing foo"
 
2981
        bzr mv foo/bar foo/baz
 
2982
        mkdir foo/bar
 
2983
        bzr add foo/bar
 
2984
        bzr commit foo/bar -m "committing bar but not baz"
 
2985
  
 
2986
      In the example above, the last commit will fail by design. This gives
 
2987
      the user the opportunity to decide whether they want to commit the
 
2988
      rename at the same time, separately first, or not at all. (As a general
 
2989
      rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
3117
2990
    """
 
2991
    # TODO: Run hooks on tree to-be-committed, and after commit.
 
2992
 
 
2993
    # TODO: Strict commit that fails if there are deleted files.
 
2994
    #       (what does "deleted files" mean ??)
 
2995
 
 
2996
    # TODO: Give better message for -s, --summary, used by tla people
 
2997
 
 
2998
    # XXX: verbose currently does nothing
3118
2999
 
3119
3000
    _see_also = ['add', 'bugs', 'hooks', 'uncommit']
3120
3001
    takes_args = ['selected*']
3149
3030
                         "the master branch until a normal commit "
3150
3031
                         "is performed."
3151
3032
                    ),
3152
 
             Option('show-diff', short_name='p',
 
3033
             Option('show-diff',
3153
3034
                    help='When no message is supplied, show the diff along'
3154
3035
                    ' with the status summary in the message editor.'),
3155
 
             Option('lossy', 
3156
 
                    help='When committing to a foreign version control '
3157
 
                    'system do not push data that can not be natively '
3158
 
                    'represented.'),
3159
3036
             ]
3160
3037
    aliases = ['ci', 'checkin']
3161
3038
 
3180
3057
 
3181
3058
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3182
3059
            unchanged=False, strict=False, local=False, fixes=None,
3183
 
            author=None, show_diff=False, exclude=None, commit_time=None,
3184
 
            lossy=False):
 
3060
            author=None, show_diff=False, exclude=None, commit_time=None):
3185
3061
        from bzrlib.errors import (
3186
3062
            PointlessCommit,
3187
3063
            ConflictsInTree,
3201
3077
                raise errors.BzrCommandError(
3202
3078
                    "Could not parse --commit-time: " + str(e))
3203
3079
 
 
3080
        # TODO: Need a blackbox test for invoking the external editor; may be
 
3081
        # slightly problematic to run this cross-platform.
 
3082
 
 
3083
        # TODO: do more checks that the commit will succeed before
 
3084
        # spending the user's valuable time typing a commit message.
 
3085
 
3204
3086
        properties = {}
3205
3087
 
3206
 
        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
 
3088
        tree, selected_list = tree_files(selected_list)
3207
3089
        if selected_list == ['']:
3208
3090
            # workaround - commit of root of tree should be exactly the same
3209
3091
            # as just default commit in that tree, and succeed even though
3234
3116
                    '(use --file "%(f)s" to take commit message from that file)'
3235
3117
                    % { 'f': message })
3236
3118
                ui.ui_factory.show_warning(warning_msg)
3237
 
            if '\r' in message:
3238
 
                message = message.replace('\r\n', '\n')
3239
 
                message = message.replace('\r', '\n')
3240
 
            if file:
3241
 
                raise errors.BzrCommandError(
3242
 
                    "please specify either --message or --file")
3243
3119
 
3244
3120
        def get_message(commit_obj):
3245
3121
            """Callback to get commit message"""
3246
 
            if file:
3247
 
                f = open(file)
3248
 
                try:
3249
 
                    my_message = f.read().decode(osutils.get_user_encoding())
3250
 
                finally:
3251
 
                    f.close()
3252
 
            elif message is not None:
3253
 
                my_message = message
3254
 
            else:
3255
 
                # No message supplied: make one up.
3256
 
                # text is the status of the tree
3257
 
                text = make_commit_message_template_encoded(tree,
 
3122
            my_message = message
 
3123
            if my_message is not None and '\r' in my_message:
 
3124
                my_message = my_message.replace('\r\n', '\n')
 
3125
                my_message = my_message.replace('\r', '\n')
 
3126
            if my_message is None and not file:
 
3127
                t = make_commit_message_template_encoded(tree,
3258
3128
                        selected_list, diff=show_diff,
3259
3129
                        output_encoding=osutils.get_user_encoding())
3260
 
                # start_message is the template generated from hooks
3261
 
                # XXX: Warning - looks like hooks return unicode,
3262
 
                # make_commit_message_template_encoded returns user encoding.
3263
 
                # We probably want to be using edit_commit_message instead to
3264
 
                # avoid this.
3265
3130
                start_message = generate_commit_message_template(commit_obj)
3266
 
                my_message = edit_commit_message_encoded(text,
 
3131
                my_message = edit_commit_message_encoded(t,
3267
3132
                    start_message=start_message)
3268
3133
                if my_message is None:
3269
3134
                    raise errors.BzrCommandError("please specify a commit"
3270
3135
                        " message with either --message or --file")
 
3136
            elif my_message and file:
 
3137
                raise errors.BzrCommandError(
 
3138
                    "please specify either --message or --file")
 
3139
            if file:
 
3140
                my_message = codecs.open(file, 'rt',
 
3141
                                         osutils.get_user_encoding()).read()
3271
3142
            if my_message == "":
3272
3143
                raise errors.BzrCommandError("empty commit message specified")
3273
3144
            return my_message
3283
3154
                        reporter=None, verbose=verbose, revprops=properties,
3284
3155
                        authors=author, timestamp=commit_stamp,
3285
3156
                        timezone=offset,
3286
 
                        exclude=tree.safe_relpath_files(exclude),
3287
 
                        lossy=lossy)
 
3157
                        exclude=safe_relpath_files(tree, exclude))
3288
3158
        except PointlessCommit:
 
3159
            # FIXME: This should really happen before the file is read in;
 
3160
            # perhaps prepare the commit; get the message; then actually commit
3289
3161
            raise errors.BzrCommandError("No changes to commit."
3290
 
                " Please 'bzr add' the files you want to commit, or use"
3291
 
                " --unchanged to force an empty commit.")
 
3162
                              " Use --unchanged to commit anyhow.")
3292
3163
        except ConflictsInTree:
3293
3164
            raise errors.BzrCommandError('Conflicts detected in working '
3294
3165
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
3297
3168
            raise errors.BzrCommandError("Commit refused because there are"
3298
3169
                              " unknown files in the working tree.")
3299
3170
        except errors.BoundBranchOutOfDate, e:
3300
 
            e.extra_help = ("\n"
3301
 
                'To commit to master branch, run update and then commit.\n'
3302
 
                'You can also pass --local to commit to continue working '
3303
 
                'disconnected.')
3304
 
            raise
 
3171
            raise errors.BzrCommandError(str(e) + "\n"
 
3172
            'To commit to master branch, run update and then commit.\n'
 
3173
            'You can also pass --local to commit to continue working '
 
3174
            'disconnected.')
3305
3175
 
3306
3176
 
3307
3177
class cmd_check(Command):
3308
 
    __doc__ = """Validate working tree structure, branch consistency and repository history.
 
3178
    """Validate working tree structure, branch consistency and repository history.
3309
3179
 
3310
3180
    This command checks various invariants about branch and repository storage
3311
3181
    to detect data corruption or bzr bugs.
3375
3245
 
3376
3246
 
3377
3247
class cmd_upgrade(Command):
3378
 
    __doc__ = """Upgrade a repository, branch or working tree to a newer format.
3379
 
 
3380
 
    When the default format has changed after a major new release of
3381
 
    Bazaar, you may be informed during certain operations that you
3382
 
    should upgrade. Upgrading to a newer format may improve performance
3383
 
    or make new features available. It may however limit interoperability
3384
 
    with older repositories or with older versions of Bazaar.
3385
 
 
3386
 
    If you wish to upgrade to a particular format rather than the
3387
 
    current default, that can be specified using the --format option.
3388
 
    As a consequence, you can use the upgrade command this way to
3389
 
    "downgrade" to an earlier format, though some conversions are
3390
 
    a one way process (e.g. changing from the 1.x default to the
3391
 
    2.x default) so downgrading is not always possible.
3392
 
 
3393
 
    A backup.bzr.~#~ directory is created at the start of the conversion
3394
 
    process (where # is a number). By default, this is left there on
3395
 
    completion. If the conversion fails, delete the new .bzr directory
3396
 
    and rename this one back in its place. Use the --clean option to ask
3397
 
    for the backup.bzr directory to be removed on successful conversion.
3398
 
    Alternatively, you can delete it by hand if everything looks good
3399
 
    afterwards.
3400
 
 
3401
 
    If the location given is a shared repository, dependent branches
3402
 
    are also converted provided the repository converts successfully.
3403
 
    If the conversion of a branch fails, remaining branches are still
3404
 
    tried.
3405
 
 
3406
 
    For more information on upgrades, see the Bazaar Upgrade Guide,
3407
 
    http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
 
3248
    """Upgrade branch storage to current format.
 
3249
 
 
3250
    The check command or bzr developers may sometimes advise you to run
 
3251
    this command. When the default format has changed you may also be warned
 
3252
    during other operations to upgrade.
3408
3253
    """
3409
3254
 
3410
 
    _see_also = ['check', 'reconcile', 'formats']
 
3255
    _see_also = ['check']
3411
3256
    takes_args = ['url?']
3412
3257
    takes_options = [
3413
 
        RegistryOption('format',
3414
 
            help='Upgrade to a specific format.  See "bzr help'
3415
 
                 ' formats" for details.',
3416
 
            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3417
 
            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3418
 
            value_switches=True, title='Branch format'),
3419
 
        Option('clean',
3420
 
            help='Remove the backup.bzr directory if successful.'),
3421
 
        Option('dry-run',
3422
 
            help="Show what would be done, but don't actually do anything."),
3423
 
    ]
 
3258
                    RegistryOption('format',
 
3259
                        help='Upgrade to a specific format.  See "bzr help'
 
3260
                             ' formats" for details.',
 
3261
                        lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
3262
                        converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
3263
                        value_switches=True, title='Branch format'),
 
3264
                    ]
3424
3265
 
3425
 
    def run(self, url='.', format=None, clean=False, dry_run=False):
 
3266
    def run(self, url='.', format=None):
3426
3267
        from bzrlib.upgrade import upgrade
3427
 
        exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3428
 
        if exceptions:
3429
 
            if len(exceptions) == 1:
3430
 
                # Compatibility with historical behavior
3431
 
                raise exceptions[0]
3432
 
            else:
3433
 
                return 3
 
3268
        upgrade(url, format)
3434
3269
 
3435
3270
 
3436
3271
class cmd_whoami(Command):
3437
 
    __doc__ = """Show or set bzr user id.
 
3272
    """Show or set bzr user id.
3438
3273
 
3439
3274
    :Examples:
3440
3275
        Show the email of the current user::
3445
3280
 
3446
3281
            bzr whoami "Frank Chu <fchu@example.com>"
3447
3282
    """
3448
 
    takes_options = [ 'directory',
3449
 
                      Option('email',
 
3283
    takes_options = [ Option('email',
3450
3284
                             help='Display email address only.'),
3451
3285
                      Option('branch',
3452
3286
                             help='Set identity for the current branch instead of '
3456
3290
    encoding_type = 'replace'
3457
3291
 
3458
3292
    @display_command
3459
 
    def run(self, email=False, branch=False, name=None, directory=None):
 
3293
    def run(self, email=False, branch=False, name=None):
3460
3294
        if name is None:
3461
 
            if directory is None:
3462
 
                # use branch if we're inside one; otherwise global config
3463
 
                try:
3464
 
                    c = Branch.open_containing(u'.')[0].get_config()
3465
 
                except errors.NotBranchError:
3466
 
                    c = _mod_config.GlobalConfig()
3467
 
            else:
3468
 
                c = Branch.open(directory).get_config()
 
3295
            # use branch if we're inside one; otherwise global config
 
3296
            try:
 
3297
                c = Branch.open_containing('.')[0].get_config()
 
3298
            except errors.NotBranchError:
 
3299
                c = config.GlobalConfig()
3469
3300
            if email:
3470
3301
                self.outf.write(c.user_email() + '\n')
3471
3302
            else:
3472
3303
                self.outf.write(c.username() + '\n')
3473
3304
            return
3474
3305
 
3475
 
        if email:
3476
 
            raise errors.BzrCommandError("--email can only be used to display existing "
3477
 
                                         "identity")
3478
 
 
3479
3306
        # display a warning if an email address isn't included in the given name.
3480
3307
        try:
3481
 
            _mod_config.extract_email_address(name)
 
3308
            config.extract_email_address(name)
3482
3309
        except errors.NoEmailInUsername, e:
3483
3310
            warning('"%s" does not seem to contain an email address.  '
3484
3311
                    'This is allowed, but not recommended.', name)
3485
3312
 
3486
3313
        # use global config unless --branch given
3487
3314
        if branch:
3488
 
            if directory is None:
3489
 
                c = Branch.open_containing(u'.')[0].get_config()
3490
 
            else:
3491
 
                c = Branch.open(directory).get_config()
 
3315
            c = Branch.open_containing('.')[0].get_config()
3492
3316
        else:
3493
 
            c = _mod_config.GlobalConfig()
 
3317
            c = config.GlobalConfig()
3494
3318
        c.set_user_option('email', name)
3495
3319
 
3496
3320
 
3497
3321
class cmd_nick(Command):
3498
 
    __doc__ = """Print or set the branch nickname.
 
3322
    """Print or set the branch nickname.
3499
3323
 
3500
3324
    If unset, the tree root directory name is used as the nickname.
3501
3325
    To print the current nickname, execute with no argument.
3506
3330
 
3507
3331
    _see_also = ['info']
3508
3332
    takes_args = ['nickname?']
3509
 
    takes_options = ['directory']
3510
 
    def run(self, nickname=None, directory=u'.'):
3511
 
        branch = Branch.open_containing(directory)[0]
 
3333
    def run(self, nickname=None):
 
3334
        branch = Branch.open_containing(u'.')[0]
3512
3335
        if nickname is None:
3513
3336
            self.printme(branch)
3514
3337
        else:
3516
3339
 
3517
3340
    @display_command
3518
3341
    def printme(self, branch):
3519
 
        self.outf.write('%s\n' % branch.nick)
 
3342
        print branch.nick
3520
3343
 
3521
3344
 
3522
3345
class cmd_alias(Command):
3523
 
    __doc__ = """Set/unset and display aliases.
 
3346
    """Set/unset and display aliases.
3524
3347
 
3525
3348
    :Examples:
3526
3349
        Show the current aliases::
3563
3386
                'bzr alias --remove expects an alias to remove.')
3564
3387
        # If alias is not found, print something like:
3565
3388
        # unalias: foo: not found
3566
 
        c = _mod_config.GlobalConfig()
 
3389
        c = config.GlobalConfig()
3567
3390
        c.unset_alias(alias_name)
3568
3391
 
3569
3392
    @display_command
3570
3393
    def print_aliases(self):
3571
3394
        """Print out the defined aliases in a similar format to bash."""
3572
 
        aliases = _mod_config.GlobalConfig().get_aliases()
 
3395
        aliases = config.GlobalConfig().get_aliases()
3573
3396
        for key, value in sorted(aliases.iteritems()):
3574
3397
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3575
3398
 
3585
3408
 
3586
3409
    def set_alias(self, alias_name, alias_command):
3587
3410
        """Save the alias in the global config."""
3588
 
        c = _mod_config.GlobalConfig()
 
3411
        c = config.GlobalConfig()
3589
3412
        c.set_alias(alias_name, alias_command)
3590
3413
 
3591
3414
 
3592
3415
class cmd_selftest(Command):
3593
 
    __doc__ = """Run internal test suite.
 
3416
    """Run internal test suite.
3594
3417
 
3595
3418
    If arguments are given, they are regular expressions that say which tests
3596
3419
    should run.  Tests matching any expression are run, and other tests are
3626
3449
    If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3627
3450
    into a pdb postmortem session.
3628
3451
 
3629
 
    The --coverage=DIRNAME global option produces a report with covered code
3630
 
    indicated.
3631
 
 
3632
3452
    :Examples:
3633
3453
        Run only tests relating to 'ignore'::
3634
3454
 
3667
3487
                                 'throughout the test suite.',
3668
3488
                            type=get_transport_type),
3669
3489
                     Option('benchmark',
3670
 
                            help='Run the benchmarks rather than selftests.',
3671
 
                            hidden=True),
 
3490
                            help='Run the benchmarks rather than selftests.'),
3672
3491
                     Option('lsprof-timed',
3673
3492
                            help='Generate lsprof output for benchmarked'
3674
3493
                                 ' sections of code.'),
3675
3494
                     Option('lsprof-tests',
3676
3495
                            help='Generate lsprof output for each test.'),
 
3496
                     Option('cache-dir', type=str,
 
3497
                            help='Cache intermediate benchmark output in this '
 
3498
                                 'directory.'),
3677
3499
                     Option('first',
3678
3500
                            help='Run all tests, but run specified tests first.',
3679
3501
                            short_name='f',
3713
3535
 
3714
3536
    def run(self, testspecs_list=None, verbose=False, one=False,
3715
3537
            transport=None, benchmark=None,
3716
 
            lsprof_timed=None,
 
3538
            lsprof_timed=None, cache_dir=None,
3717
3539
            first=False, list_only=False,
3718
3540
            randomize=None, exclude=None, strict=False,
3719
3541
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3720
3542
            parallel=None, lsprof_tests=False):
3721
 
        from bzrlib import tests
3722
 
 
 
3543
        from bzrlib.tests import selftest
 
3544
        import bzrlib.benchmarks as benchmarks
 
3545
        from bzrlib.benchmarks import tree_creator
 
3546
 
 
3547
        # Make deprecation warnings visible, unless -Werror is set
 
3548
        symbol_versioning.activate_deprecation_warnings(override=False)
 
3549
 
 
3550
        if cache_dir is not None:
 
3551
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3723
3552
        if testspecs_list is not None:
3724
3553
            pattern = '|'.join(testspecs_list)
3725
3554
        else:
3731
3560
                raise errors.BzrCommandError("subunit not available. subunit "
3732
3561
                    "needs to be installed to use --subunit.")
3733
3562
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3734
 
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3735
 
            # stdout, which would corrupt the subunit stream. 
3736
 
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3737
 
            # following code can be deleted when it's sufficiently deployed
3738
 
            # -- vila/mgz 20100514
3739
 
            if (sys.platform == "win32"
3740
 
                and getattr(sys.stdout, 'fileno', None) is not None):
3741
 
                import msvcrt
3742
 
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3743
3563
        if parallel:
3744
3564
            self.additional_selftest_args.setdefault(
3745
3565
                'suite_decorators', []).append(parallel)
3746
3566
        if benchmark:
3747
 
            raise errors.BzrCommandError(
3748
 
                "--benchmark is no longer supported from bzr 2.2; "
3749
 
                "use bzr-usertest instead")
3750
 
        test_suite_factory = None
 
3567
            test_suite_factory = benchmarks.test_suite
 
3568
            # Unless user explicitly asks for quiet, be verbose in benchmarks
 
3569
            verbose = not is_quiet()
 
3570
            # TODO: should possibly lock the history file...
 
3571
            benchfile = open(".perf_history", "at", buffering=1)
 
3572
            self.add_cleanup(benchfile.close)
 
3573
        else:
 
3574
            test_suite_factory = None
 
3575
            benchfile = None
3751
3576
        selftest_kwargs = {"verbose": verbose,
3752
3577
                          "pattern": pattern,
3753
3578
                          "stop_on_failure": one,
3755
3580
                          "test_suite_factory": test_suite_factory,
3756
3581
                          "lsprof_timed": lsprof_timed,
3757
3582
                          "lsprof_tests": lsprof_tests,
 
3583
                          "bench_history": benchfile,
3758
3584
                          "matching_tests_first": first,
3759
3585
                          "list_only": list_only,
3760
3586
                          "random_seed": randomize,
3765
3591
                          "starting_with": starting_with
3766
3592
                          }
3767
3593
        selftest_kwargs.update(self.additional_selftest_args)
3768
 
 
3769
 
        # Make deprecation warnings visible, unless -Werror is set
3770
 
        cleanup = symbol_versioning.activate_deprecation_warnings(
3771
 
            override=False)
3772
 
        try:
3773
 
            result = tests.selftest(**selftest_kwargs)
3774
 
        finally:
3775
 
            cleanup()
 
3594
        result = selftest(**selftest_kwargs)
3776
3595
        return int(not result)
3777
3596
 
3778
3597
 
3779
3598
class cmd_version(Command):
3780
 
    __doc__ = """Show version of bzr."""
 
3599
    """Show version of bzr."""
3781
3600
 
3782
3601
    encoding_type = 'replace'
3783
3602
    takes_options = [
3794
3613
 
3795
3614
 
3796
3615
class cmd_rocks(Command):
3797
 
    __doc__ = """Statement of optimism."""
 
3616
    """Statement of optimism."""
3798
3617
 
3799
3618
    hidden = True
3800
3619
 
3801
3620
    @display_command
3802
3621
    def run(self):
3803
 
        self.outf.write("It sure does!\n")
 
3622
        print "It sure does!"
3804
3623
 
3805
3624
 
3806
3625
class cmd_find_merge_base(Command):
3807
 
    __doc__ = """Find and print a base revision for merging two branches."""
 
3626
    """Find and print a base revision for merging two branches."""
3808
3627
    # TODO: Options to specify revisions on either side, as if
3809
3628
    #       merging only part of the history.
3810
3629
    takes_args = ['branch', 'other']
3816
3635
 
3817
3636
        branch1 = Branch.open_containing(branch)[0]
3818
3637
        branch2 = Branch.open_containing(other)[0]
3819
 
        self.add_cleanup(branch1.lock_read().unlock)
3820
 
        self.add_cleanup(branch2.lock_read().unlock)
 
3638
        branch1.lock_read()
 
3639
        self.add_cleanup(branch1.unlock)
 
3640
        branch2.lock_read()
 
3641
        self.add_cleanup(branch2.unlock)
3821
3642
        last1 = ensure_null(branch1.last_revision())
3822
3643
        last2 = ensure_null(branch2.last_revision())
3823
3644
 
3824
3645
        graph = branch1.repository.get_graph(branch2.repository)
3825
3646
        base_rev_id = graph.find_unique_lca(last1, last2)
3826
3647
 
3827
 
        self.outf.write('merge base is revision %s\n' % base_rev_id)
 
3648
        print 'merge base is revision %s' % base_rev_id
3828
3649
 
3829
3650
 
3830
3651
class cmd_merge(Command):
3831
 
    __doc__ = """Perform a three-way merge.
 
3652
    """Perform a three-way merge.
3832
3653
 
3833
3654
    The source of the merge can be specified either in the form of a branch,
3834
3655
    or in the form of a path to a file containing a merge directive generated
3835
3656
    with bzr send. If neither is specified, the default is the upstream branch
3836
3657
    or the branch most recently merged using --remember.
3837
3658
 
3838
 
    When merging from a branch, by default bzr will try to merge in all new
3839
 
    work from the other branch, automatically determining an appropriate base
3840
 
    revision.  If this fails, you may need to give an explicit base.
3841
 
 
3842
 
    To pick a different ending revision, pass "--revision OTHER".  bzr will
3843
 
    try to merge in all new work up to and including revision OTHER.
3844
 
 
3845
 
    If you specify two values, "--revision BASE..OTHER", only revisions BASE
3846
 
    through OTHER, excluding BASE but including OTHER, will be merged.  If this
3847
 
    causes some revisions to be skipped, i.e. if the destination branch does
3848
 
    not already contain revision BASE, such a merge is commonly referred to as
3849
 
    a "cherrypick".
3850
 
 
3851
 
    Revision numbers are always relative to the source branch.
 
3659
    When merging a branch, by default the tip will be merged. To pick a different
 
3660
    revision, pass --revision. If you specify two values, the first will be used as
 
3661
    BASE and the second one as OTHER. Merging individual revisions, or a subset of
 
3662
    available revisions, like this is commonly referred to as "cherrypicking".
 
3663
 
 
3664
    Revision numbers are always relative to the branch being merged.
 
3665
 
 
3666
    By default, bzr will try to merge in all new work from the other
 
3667
    branch, automatically determining an appropriate base.  If this
 
3668
    fails, you may need to give an explicit base.
3852
3669
 
3853
3670
    Merge will do its best to combine the changes in two branches, but there
3854
3671
    are some kinds of problems only a human can fix.  When it encounters those,
3878
3695
    you to apply each diff hunk and file change, similar to "shelve".
3879
3696
 
3880
3697
    :Examples:
3881
 
        To merge all new revisions from bzr.dev::
 
3698
        To merge the latest revision from bzr.dev::
3882
3699
 
3883
3700
            bzr merge ../bzr.dev
3884
3701
 
3921
3738
                ' completely merged into the source, pull from the'
3922
3739
                ' source rather than merging.  When this happens,'
3923
3740
                ' you do not need to commit the result.'),
3924
 
        custom_help('directory',
 
3741
        Option('directory',
3925
3742
               help='Branch to merge into, '
3926
 
                    'rather than the one containing the working directory.'),
 
3743
                    'rather than the one containing the working directory.',
 
3744
               short_name='d',
 
3745
               type=unicode,
 
3746
               ),
3927
3747
        Option('preview', help='Instead of merging, show a diff of the'
3928
3748
               ' merge.'),
3929
3749
        Option('interactive', help='Select changes interactively.',
3962
3782
            unversioned_filter=tree.is_ignored, view_info=view_info)
3963
3783
        pb = ui.ui_factory.nested_progress_bar()
3964
3784
        self.add_cleanup(pb.finished)
3965
 
        self.add_cleanup(tree.lock_write().unlock)
 
3785
        tree.lock_write()
 
3786
        self.add_cleanup(tree.unlock)
3966
3787
        if location is not None:
3967
3788
            try:
3968
3789
                mergeable = bundle.read_mergeable_from_url(location,
3999
3820
            merger.other_rev_id is not None):
4000
3821
            note('Nothing to do.')
4001
3822
            return 0
4002
 
        if pull and not preview:
 
3823
        if pull:
4003
3824
            if merger.interesting_files is not None:
4004
3825
                raise errors.BzrCommandError('Cannot pull individual files')
4005
3826
            if (merger.base_rev_id == tree.last_revision()):
4029
3850
    def _do_preview(self, merger):
4030
3851
        from bzrlib.diff import show_diff_trees
4031
3852
        result_tree = self._get_preview(merger)
4032
 
        path_encoding = osutils.get_diff_header_encoding()
4033
3853
        show_diff_trees(merger.this_tree, result_tree, self.outf,
4034
 
                        old_label='', new_label='',
4035
 
                        path_encoding=path_encoding)
 
3854
                        old_label='', new_label='')
4036
3855
 
4037
3856
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
4038
3857
        merger.change_reporter = change_reporter
4118
3937
        if ((remember or tree.branch.get_submit_branch() is None) and
4119
3938
             user_location is not None):
4120
3939
            tree.branch.set_submit_branch(other_branch.base)
4121
 
        # Merge tags (but don't set them in the master branch yet, the user
4122
 
        # might revert this merge).  Commit will propagate them.
4123
 
        _merge_tags_if_possible(other_branch, tree.branch, ignore_master=True)
 
3940
        _merge_tags_if_possible(other_branch, tree.branch)
4124
3941
        merger = _mod_merge.Merger.from_revision_ids(pb, tree,
4125
3942
            other_revision_id, base_revision_id, other_branch, base_branch)
4126
3943
        if other_path != '':
4193
4010
 
4194
4011
 
4195
4012
class cmd_remerge(Command):
4196
 
    __doc__ = """Redo a merge.
 
4013
    """Redo a merge.
4197
4014
 
4198
4015
    Use this if you want to try a different merge technique while resolving
4199
4016
    conflicts.  Some merge techniques are better than others, and remerge
4224
4041
 
4225
4042
    def run(self, file_list=None, merge_type=None, show_base=False,
4226
4043
            reprocess=False):
4227
 
        from bzrlib.conflicts import restore
4228
4044
        if merge_type is None:
4229
4045
            merge_type = _mod_merge.Merge3Merger
4230
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4231
 
        self.add_cleanup(tree.lock_write().unlock)
 
4046
        tree, file_list = tree_files(file_list)
 
4047
        tree.lock_write()
 
4048
        self.add_cleanup(tree.unlock)
4232
4049
        parents = tree.get_parent_ids()
4233
4050
        if len(parents) != 2:
4234
4051
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4287
4104
 
4288
4105
 
4289
4106
class cmd_revert(Command):
4290
 
    __doc__ = """Revert files to a previous revision.
 
4107
    """Revert files to a previous revision.
4291
4108
 
4292
4109
    Giving a list of files will revert only those files.  Otherwise, all files
4293
4110
    will be reverted.  If the revision is not specified with '--revision', the
4294
4111
    last committed revision is used.
4295
4112
 
4296
4113
    To remove only some changes, without reverting to a prior version, use
4297
 
    merge instead.  For example, "merge . -r -2..-3" (don't forget the ".")
4298
 
    will remove the changes introduced by the second last commit (-2), without
4299
 
    affecting the changes introduced by the last commit (-1).  To remove
4300
 
    certain changes on a hunk-by-hunk basis, see the shelve command.
 
4114
    merge instead.  For example, "merge . --revision -2..-3" will remove the
 
4115
    changes introduced by -2, without affecting the changes introduced by -1.
 
4116
    Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
4301
4117
 
4302
4118
    By default, any files that have been manually changed will be backed up
4303
4119
    first.  (Files changed only by merge are not backed up.)  Backup files have
4333
4149
    target branches.
4334
4150
    """
4335
4151
 
4336
 
    _see_also = ['cat', 'export', 'merge', 'shelve']
 
4152
    _see_also = ['cat', 'export']
4337
4153
    takes_options = [
4338
4154
        'revision',
4339
4155
        Option('no-backup', "Do not save backups of reverted files."),
4344
4160
 
4345
4161
    def run(self, revision=None, no_backup=False, file_list=None,
4346
4162
            forget_merges=None):
4347
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4348
 
        self.add_cleanup(tree.lock_tree_write().unlock)
 
4163
        tree, file_list = tree_files(file_list)
 
4164
        tree.lock_write()
 
4165
        self.add_cleanup(tree.unlock)
4349
4166
        if forget_merges:
4350
4167
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4351
4168
        else:
4359
4176
 
4360
4177
 
4361
4178
class cmd_assert_fail(Command):
4362
 
    __doc__ = """Test reporting of assertion failures"""
 
4179
    """Test reporting of assertion failures"""
4363
4180
    # intended just for use in testing
4364
4181
 
4365
4182
    hidden = True
4369
4186
 
4370
4187
 
4371
4188
class cmd_help(Command):
4372
 
    __doc__ = """Show help on a command or other topic.
 
4189
    """Show help on a command or other topic.
4373
4190
    """
4374
4191
 
4375
4192
    _see_also = ['topics']
4388
4205
 
4389
4206
 
4390
4207
class cmd_shell_complete(Command):
4391
 
    __doc__ = """Show appropriate completions for context.
 
4208
    """Show appropriate completions for context.
4392
4209
 
4393
4210
    For a list of all available commands, say 'bzr shell-complete'.
4394
4211
    """
4403
4220
 
4404
4221
 
4405
4222
class cmd_missing(Command):
4406
 
    __doc__ = """Show unmerged/unpulled revisions between two branches.
 
4223
    """Show unmerged/unpulled revisions between two branches.
4407
4224
 
4408
4225
    OTHER_BRANCH may be local or remote.
4409
4226
 
4440
4257
    _see_also = ['merge', 'pull']
4441
4258
    takes_args = ['other_branch?']
4442
4259
    takes_options = [
4443
 
        'directory',
4444
4260
        Option('reverse', 'Reverse the order of revisions.'),
4445
4261
        Option('mine-only',
4446
4262
               'Display changes in the local branch only.'),
4468
4284
            theirs_only=False,
4469
4285
            log_format=None, long=False, short=False, line=False,
4470
4286
            show_ids=False, verbose=False, this=False, other=False,
4471
 
            include_merges=False, revision=None, my_revision=None,
4472
 
            directory=u'.'):
 
4287
            include_merges=False, revision=None, my_revision=None):
4473
4288
        from bzrlib.missing import find_unmerged, iter_log_revisions
4474
4289
        def message(s):
4475
4290
            if not is_quiet():
4488
4303
        elif theirs_only:
4489
4304
            restrict = 'remote'
4490
4305
 
4491
 
        local_branch = Branch.open_containing(directory)[0]
4492
 
        self.add_cleanup(local_branch.lock_read().unlock)
4493
 
 
 
4306
        local_branch = Branch.open_containing(u".")[0]
4494
4307
        parent = local_branch.get_parent()
4495
4308
        if other_branch is None:
4496
4309
            other_branch = parent
4505
4318
        remote_branch = Branch.open(other_branch)
4506
4319
        if remote_branch.base == local_branch.base:
4507
4320
            remote_branch = local_branch
4508
 
        else:
4509
 
            self.add_cleanup(remote_branch.lock_read().unlock)
4510
4321
 
 
4322
        local_branch.lock_read()
 
4323
        self.add_cleanup(local_branch.unlock)
4511
4324
        local_revid_range = _revision_range_to_revid_range(
4512
4325
            _get_revision_range(my_revision, local_branch,
4513
4326
                self.name()))
4514
4327
 
 
4328
        remote_branch.lock_read()
 
4329
        self.add_cleanup(remote_branch.unlock)
4515
4330
        remote_revid_range = _revision_range_to_revid_range(
4516
4331
            _get_revision_range(revision,
4517
4332
                remote_branch, self.name()))
4567
4382
            message("Branches are up to date.\n")
4568
4383
        self.cleanup_now()
4569
4384
        if not status_code and parent is None and other_branch is not None:
4570
 
            self.add_cleanup(local_branch.lock_write().unlock)
 
4385
            local_branch.lock_write()
 
4386
            self.add_cleanup(local_branch.unlock)
4571
4387
            # handle race conditions - a parent might be set while we run.
4572
4388
            if local_branch.get_parent() is None:
4573
4389
                local_branch.set_parent(remote_branch.base)
4575
4391
 
4576
4392
 
4577
4393
class cmd_pack(Command):
4578
 
    __doc__ = """Compress the data within a repository.
4579
 
 
4580
 
    This operation compresses the data within a bazaar repository. As
4581
 
    bazaar supports automatic packing of repository, this operation is
4582
 
    normally not required to be done manually.
4583
 
 
4584
 
    During the pack operation, bazaar takes a backup of existing repository
4585
 
    data, i.e. pack files. This backup is eventually removed by bazaar
4586
 
    automatically when it is safe to do so. To save disk space by removing
4587
 
    the backed up pack files, the --clean-obsolete-packs option may be
4588
 
    used.
4589
 
 
4590
 
    Warning: If you use --clean-obsolete-packs and your machine crashes
4591
 
    during or immediately after repacking, you may be left with a state
4592
 
    where the deletion has been written to disk but the new packs have not
4593
 
    been. In this case the repository may be unusable.
4594
 
    """
 
4394
    """Compress the data within a repository."""
4595
4395
 
4596
4396
    _see_also = ['repositories']
4597
4397
    takes_args = ['branch_or_repo?']
4598
 
    takes_options = [
4599
 
        Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4600
 
        ]
4601
4398
 
4602
 
    def run(self, branch_or_repo='.', clean_obsolete_packs=False):
 
4399
    def run(self, branch_or_repo='.'):
4603
4400
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4604
4401
        try:
4605
4402
            branch = dir.open_branch()
4606
4403
            repository = branch.repository
4607
4404
        except errors.NotBranchError:
4608
4405
            repository = dir.open_repository()
4609
 
        repository.pack(clean_obsolete_packs=clean_obsolete_packs)
 
4406
        repository.pack()
4610
4407
 
4611
4408
 
4612
4409
class cmd_plugins(Command):
4613
 
    __doc__ = """List the installed plugins.
 
4410
    """List the installed plugins.
4614
4411
 
4615
4412
    This command displays the list of installed plugins including
4616
4413
    version of plugin and a short description of each.
4632
4429
 
4633
4430
    @display_command
4634
4431
    def run(self, verbose=False):
4635
 
        from bzrlib import plugin
4636
 
        self.outf.writelines(
4637
 
            plugin.describe_plugins(show_paths=verbose))
 
4432
        import bzrlib.plugin
 
4433
        from inspect import getdoc
 
4434
        result = []
 
4435
        for name, plugin in bzrlib.plugin.plugins().items():
 
4436
            version = plugin.__version__
 
4437
            if version == 'unknown':
 
4438
                version = ''
 
4439
            name_ver = '%s %s' % (name, version)
 
4440
            d = getdoc(plugin.module)
 
4441
            if d:
 
4442
                doc = d.split('\n')[0]
 
4443
            else:
 
4444
                doc = '(no description)'
 
4445
            result.append((name_ver, doc, plugin.path()))
 
4446
        for name_ver, doc, path in sorted(result):
 
4447
            print name_ver
 
4448
            print '   ', doc
 
4449
            if verbose:
 
4450
                print '   ', path
 
4451
            print
4638
4452
 
4639
4453
 
4640
4454
class cmd_testament(Command):
4641
 
    __doc__ = """Show testament (signing-form) of a revision."""
 
4455
    """Show testament (signing-form) of a revision."""
4642
4456
    takes_options = [
4643
4457
            'revision',
4644
4458
            Option('long', help='Produce long-format testament.'),
4656
4470
            b = Branch.open_containing(branch)[0]
4657
4471
        else:
4658
4472
            b = Branch.open(branch)
4659
 
        self.add_cleanup(b.lock_read().unlock)
 
4473
        b.lock_read()
 
4474
        self.add_cleanup(b.unlock)
4660
4475
        if revision is None:
4661
4476
            rev_id = b.last_revision()
4662
4477
        else:
4669
4484
 
4670
4485
 
4671
4486
class cmd_annotate(Command):
4672
 
    __doc__ = """Show the origin of each line in a file.
 
4487
    """Show the origin of each line in a file.
4673
4488
 
4674
4489
    This prints out the given file with an annotation on the left side
4675
4490
    indicating which revision, author and date introduced the change.
4686
4501
                     Option('long', help='Show commit date in annotations.'),
4687
4502
                     'revision',
4688
4503
                     'show-ids',
4689
 
                     'directory',
4690
4504
                     ]
4691
4505
    encoding_type = 'exact'
4692
4506
 
4693
4507
    @display_command
4694
4508
    def run(self, filename, all=False, long=False, revision=None,
4695
 
            show_ids=False, directory=None):
4696
 
        from bzrlib.annotate import (
4697
 
            annotate_file_tree,
4698
 
            )
 
4509
            show_ids=False):
 
4510
        from bzrlib.annotate import annotate_file, annotate_file_tree
4699
4511
        wt, branch, relpath = \
4700
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
 
4512
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4701
4513
        if wt is not None:
4702
 
            self.add_cleanup(wt.lock_read().unlock)
 
4514
            wt.lock_read()
 
4515
            self.add_cleanup(wt.unlock)
4703
4516
        else:
4704
 
            self.add_cleanup(branch.lock_read().unlock)
 
4517
            branch.lock_read()
 
4518
            self.add_cleanup(branch.unlock)
4705
4519
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4706
 
        self.add_cleanup(tree.lock_read().unlock)
4707
 
        if wt is not None and revision is None:
 
4520
        tree.lock_read()
 
4521
        self.add_cleanup(tree.unlock)
 
4522
        if wt is not None:
4708
4523
            file_id = wt.path2id(relpath)
4709
4524
        else:
4710
4525
            file_id = tree.path2id(relpath)
4711
4526
        if file_id is None:
4712
4527
            raise errors.NotVersionedError(filename)
 
4528
        file_version = tree.inventory[file_id].revision
4713
4529
        if wt is not None and revision is None:
4714
4530
            # If there is a tree and we're not annotating historical
4715
4531
            # versions, annotate the working tree's content.
4716
4532
            annotate_file_tree(wt, file_id, self.outf, long, all,
4717
4533
                show_ids=show_ids)
4718
4534
        else:
4719
 
            annotate_file_tree(tree, file_id, self.outf, long, all,
4720
 
                show_ids=show_ids, branch=branch)
 
4535
            annotate_file(branch, file_version, file_id, long, all, self.outf,
 
4536
                          show_ids=show_ids)
4721
4537
 
4722
4538
 
4723
4539
class cmd_re_sign(Command):
4724
 
    __doc__ = """Create a digital signature for an existing revision."""
 
4540
    """Create a digital signature for an existing revision."""
4725
4541
    # TODO be able to replace existing ones.
4726
4542
 
4727
4543
    hidden = True # is this right ?
4728
4544
    takes_args = ['revision_id*']
4729
 
    takes_options = ['directory', 'revision']
 
4545
    takes_options = ['revision']
4730
4546
 
4731
 
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
 
4547
    def run(self, revision_id_list=None, revision=None):
4732
4548
        if revision_id_list is not None and revision is not None:
4733
4549
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4734
4550
        if revision_id_list is None and revision is None:
4735
4551
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4736
 
        b = WorkingTree.open_containing(directory)[0].branch
4737
 
        self.add_cleanup(b.lock_write().unlock)
 
4552
        b = WorkingTree.open_containing(u'.')[0].branch
 
4553
        b.lock_write()
 
4554
        self.add_cleanup(b.unlock)
4738
4555
        return self._run(b, revision_id_list, revision)
4739
4556
 
4740
4557
    def _run(self, b, revision_id_list, revision):
4786
4603
 
4787
4604
 
4788
4605
class cmd_bind(Command):
4789
 
    __doc__ = """Convert the current branch into a checkout of the supplied branch.
4790
 
    If no branch is supplied, rebind to the last bound location.
 
4606
    """Convert the current branch into a checkout of the supplied branch.
4791
4607
 
4792
4608
    Once converted into a checkout, commits must succeed on the master branch
4793
4609
    before they will be applied to the local branch.
4799
4615
 
4800
4616
    _see_also = ['checkouts', 'unbind']
4801
4617
    takes_args = ['location?']
4802
 
    takes_options = ['directory']
 
4618
    takes_options = []
4803
4619
 
4804
 
    def run(self, location=None, directory=u'.'):
4805
 
        b, relpath = Branch.open_containing(directory)
 
4620
    def run(self, location=None):
 
4621
        b, relpath = Branch.open_containing(u'.')
4806
4622
        if location is None:
4807
4623
            try:
4808
4624
                location = b.get_old_bound_location()
4827
4643
 
4828
4644
 
4829
4645
class cmd_unbind(Command):
4830
 
    __doc__ = """Convert the current checkout into a regular branch.
 
4646
    """Convert the current checkout into a regular branch.
4831
4647
 
4832
4648
    After unbinding, the local branch is considered independent and subsequent
4833
4649
    commits will be local only.
4835
4651
 
4836
4652
    _see_also = ['checkouts', 'bind']
4837
4653
    takes_args = []
4838
 
    takes_options = ['directory']
 
4654
    takes_options = []
4839
4655
 
4840
 
    def run(self, directory=u'.'):
4841
 
        b, relpath = Branch.open_containing(directory)
 
4656
    def run(self):
 
4657
        b, relpath = Branch.open_containing(u'.')
4842
4658
        if not b.unbind():
4843
4659
            raise errors.BzrCommandError('Local branch is not bound')
4844
4660
 
4845
4661
 
4846
4662
class cmd_uncommit(Command):
4847
 
    __doc__ = """Remove the last committed revision.
 
4663
    """Remove the last committed revision.
4848
4664
 
4849
4665
    --verbose will print out what is being removed.
4850
4666
    --dry-run will go through all the motions, but not actually
4890
4706
            b = control.open_branch()
4891
4707
 
4892
4708
        if tree is not None:
4893
 
            self.add_cleanup(tree.lock_write().unlock)
 
4709
            tree.lock_write()
 
4710
            self.add_cleanup(tree.unlock)
4894
4711
        else:
4895
 
            self.add_cleanup(b.lock_write().unlock)
 
4712
            b.lock_write()
 
4713
            self.add_cleanup(b.unlock)
4896
4714
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4897
4715
 
4898
4716
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4916
4734
                rev_id = b.get_rev_id(revno)
4917
4735
 
4918
4736
        if rev_id is None or _mod_revision.is_null(rev_id):
4919
 
            self.outf.write('No revisions to uncommit.\n')
 
4737
            ui.ui_factory.note('No revisions to uncommit.')
4920
4738
            return 1
4921
4739
 
 
4740
        log_collector = ui.ui_factory.make_output_stream()
4922
4741
        lf = log_formatter('short',
4923
 
                           to_file=self.outf,
 
4742
                           to_file=log_collector,
4924
4743
                           show_timezone='original')
4925
4744
 
4926
4745
        show_log(b,
4931
4750
                 end_revision=last_revno)
4932
4751
 
4933
4752
        if dry_run:
4934
 
            self.outf.write('Dry-run, pretending to remove'
4935
 
                            ' the above revisions.\n')
 
4753
            ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
4936
4754
        else:
4937
 
            self.outf.write('The above revision(s) will be removed.\n')
 
4755
            ui.ui_factory.note('The above revision(s) will be removed.')
4938
4756
 
4939
4757
        if not force:
4940
 
            if not ui.ui_factory.confirm_action(
4941
 
                    'Uncommit these revisions',
4942
 
                    'bzrlib.builtins.uncommit',
4943
 
                    {}):
4944
 
                self.outf.write('Canceled\n')
 
4758
            if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
 
4759
                ui.ui_factory.note('Canceled')
4945
4760
                return 0
4946
4761
 
4947
4762
        mutter('Uncommitting from {%s} to {%s}',
4948
4763
               last_rev_id, rev_id)
4949
4764
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4950
4765
                 revno=revno, local=local)
4951
 
        self.outf.write('You can restore the old tip by running:\n'
4952
 
             '  bzr pull . -r revid:%s\n' % last_rev_id)
 
4766
        ui.ui_factory.note('You can restore the old tip by running:\n'
 
4767
             '  bzr pull . -r revid:%s' % last_rev_id)
4953
4768
 
4954
4769
 
4955
4770
class cmd_break_lock(Command):
4956
 
    __doc__ = """Break a dead lock.
4957
 
 
4958
 
    This command breaks a lock on a repository, branch, working directory or
4959
 
    config file.
 
4771
    """Break a dead lock on a repository, branch or working directory.
4960
4772
 
4961
4773
    CAUTION: Locks should only be broken when you are sure that the process
4962
4774
    holding the lock has been stopped.
4967
4779
    :Examples:
4968
4780
        bzr break-lock
4969
4781
        bzr break-lock bzr+ssh://example.com/bzr/foo
4970
 
        bzr break-lock --conf ~/.bazaar
4971
4782
    """
4972
 
 
4973
4783
    takes_args = ['location?']
4974
 
    takes_options = [
4975
 
        Option('config',
4976
 
               help='LOCATION is the directory where the config lock is.'),
4977
 
        Option('force',
4978
 
            help='Do not ask for confirmation before breaking the lock.'),
4979
 
        ]
4980
4784
 
4981
 
    def run(self, location=None, config=False, force=False):
 
4785
    def run(self, location=None, show=False):
4982
4786
        if location is None:
4983
4787
            location = u'.'
4984
 
        if force:
4985
 
            ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
4986
 
                None,
4987
 
                {'bzrlib.lockdir.break': True})
4988
 
        if config:
4989
 
            conf = _mod_config.LockableConfig(file_name=location)
4990
 
            conf.break_lock()
4991
 
        else:
4992
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
4993
 
            try:
4994
 
                control.break_lock()
4995
 
            except NotImplementedError:
4996
 
                pass
 
4788
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
4789
        try:
 
4790
            control.break_lock()
 
4791
        except NotImplementedError:
 
4792
            pass
4997
4793
 
4998
4794
 
4999
4795
class cmd_wait_until_signalled(Command):
5000
 
    __doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
 
4796
    """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
5001
4797
 
5002
4798
    This just prints a line to signal when it is ready, then blocks on stdin.
5003
4799
    """
5011
4807
 
5012
4808
 
5013
4809
class cmd_serve(Command):
5014
 
    __doc__ = """Run the bzr server."""
 
4810
    """Run the bzr server."""
5015
4811
 
5016
4812
    aliases = ['server']
5017
4813
 
5028
4824
                    'result in a dynamically allocated port.  The default port '
5029
4825
                    'depends on the protocol.',
5030
4826
               type=str),
5031
 
        custom_help('directory',
5032
 
               help='Serve contents of this directory.'),
 
4827
        Option('directory',
 
4828
               help='Serve contents of this directory.',
 
4829
               type=unicode),
5033
4830
        Option('allow-writes',
5034
4831
               help='By default the server is a readonly server.  Supplying '
5035
4832
                    '--allow-writes enables write access to the contents of '
5062
4859
 
5063
4860
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
5064
4861
            protocol=None):
5065
 
        from bzrlib import transport
 
4862
        from bzrlib.transport import get_transport, transport_server_registry
5066
4863
        if directory is None:
5067
4864
            directory = os.getcwd()
5068
4865
        if protocol is None:
5069
 
            protocol = transport.transport_server_registry.get()
 
4866
            protocol = transport_server_registry.get()
5070
4867
        host, port = self.get_host_and_port(port)
5071
4868
        url = urlutils.local_path_to_url(directory)
5072
4869
        if not allow_writes:
5073
4870
            url = 'readonly+' + url
5074
 
        t = transport.get_transport(url)
5075
 
        protocol(t, host, port, inet)
 
4871
        transport = get_transport(url)
 
4872
        protocol(transport, host, port, inet)
5076
4873
 
5077
4874
 
5078
4875
class cmd_join(Command):
5079
 
    __doc__ = """Combine a tree into its containing tree.
 
4876
    """Combine a tree into its containing tree.
5080
4877
 
5081
4878
    This command requires the target tree to be in a rich-root format.
5082
4879
 
5084
4881
    not part of it.  (Such trees can be produced by "bzr split", but also by
5085
4882
    running "bzr branch" with the target inside a tree.)
5086
4883
 
5087
 
    The result is a combined tree, with the subtree no longer an independent
 
4884
    The result is a combined tree, with the subtree no longer an independant
5088
4885
    part.  This is marked as a merge of the subtree into the containing tree,
5089
4886
    and all history is preserved.
5090
4887
    """
5122
4919
 
5123
4920
 
5124
4921
class cmd_split(Command):
5125
 
    __doc__ = """Split a subdirectory of a tree into a separate tree.
 
4922
    """Split a subdirectory of a tree into a separate tree.
5126
4923
 
5127
4924
    This command will produce a target tree in a format that supports
5128
4925
    rich roots, like 'rich-root' or 'rich-root-pack'.  These formats cannot be
5148
4945
 
5149
4946
 
5150
4947
class cmd_merge_directive(Command):
5151
 
    __doc__ = """Generate a merge directive for auto-merge tools.
 
4948
    """Generate a merge directive for auto-merge tools.
5152
4949
 
5153
4950
    A directive requests a merge to be performed, and also provides all the
5154
4951
    information necessary to do so.  This means it must either include a
5171
4968
    _see_also = ['send']
5172
4969
 
5173
4970
    takes_options = [
5174
 
        'directory',
5175
4971
        RegistryOption.from_kwargs('patch-type',
5176
4972
            'The type of patch to include in the directive.',
5177
4973
            title='Patch type',
5190
4986
    encoding_type = 'exact'
5191
4987
 
5192
4988
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5193
 
            sign=False, revision=None, mail_to=None, message=None,
5194
 
            directory=u'.'):
 
4989
            sign=False, revision=None, mail_to=None, message=None):
5195
4990
        from bzrlib.revision import ensure_null, NULL_REVISION
5196
4991
        include_patch, include_bundle = {
5197
4992
            'plain': (False, False),
5198
4993
            'diff': (True, False),
5199
4994
            'bundle': (True, True),
5200
4995
            }[patch_type]
5201
 
        branch = Branch.open(directory)
 
4996
        branch = Branch.open('.')
5202
4997
        stored_submit_branch = branch.get_submit_branch()
5203
4998
        if submit_branch is None:
5204
4999
            submit_branch = stored_submit_branch
5249
5044
 
5250
5045
 
5251
5046
class cmd_send(Command):
5252
 
    __doc__ = """Mail or create a merge-directive for submitting changes.
 
5047
    """Mail or create a merge-directive for submitting changes.
5253
5048
 
5254
5049
    A merge directive provides many things needed for requesting merges:
5255
5050
 
5289
5084
    given, in which case it is sent to a file.
5290
5085
 
5291
5086
    Mail is sent using your preferred mail program.  This should be transparent
5292
 
    on Windows (it uses MAPI).  On Unix, it requires the xdg-email utility.
 
5087
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
5293
5088
    If the preferred client can't be found (or used), your editor will be used.
5294
5089
 
5295
5090
    To use a specific mail program, set the mail_client configuration option.
5337
5132
               short_name='f',
5338
5133
               type=unicode),
5339
5134
        Option('output', short_name='o',
5340
 
               help='Write merge directive to this file or directory; '
 
5135
               help='Write merge directive to this file; '
5341
5136
                    'use - for stdout.',
5342
5137
               type=unicode),
5343
5138
        Option('strict',
5366
5161
 
5367
5162
 
5368
5163
class cmd_bundle_revisions(cmd_send):
5369
 
    __doc__ = """Create a merge-directive for submitting changes.
 
5164
    """Create a merge-directive for submitting changes.
5370
5165
 
5371
5166
    A merge directive provides many things needed for requesting merges:
5372
5167
 
5439
5234
 
5440
5235
 
5441
5236
class cmd_tag(Command):
5442
 
    __doc__ = """Create, remove or modify a tag naming a revision.
 
5237
    """Create, remove or modify a tag naming a revision.
5443
5238
 
5444
5239
    Tags give human-meaningful names to revisions.  Commands that take a -r
5445
5240
    (--revision) option can be given -rtag:X, where X is any previously
5453
5248
 
5454
5249
    To rename a tag (change the name but keep it on the same revsion), run ``bzr
5455
5250
    tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5456
 
 
5457
 
    If no tag name is specified it will be determined through the 
5458
 
    'automatic_tag_name' hook. This can e.g. be used to automatically tag
5459
 
    upstream releases by reading configure.ac. See ``bzr help hooks`` for
5460
 
    details.
5461
5251
    """
5462
5252
 
5463
5253
    _see_also = ['commit', 'tags']
5464
 
    takes_args = ['tag_name?']
 
5254
    takes_args = ['tag_name']
5465
5255
    takes_options = [
5466
5256
        Option('delete',
5467
5257
            help='Delete this tag rather than placing it.',
5468
5258
            ),
5469
 
        custom_help('directory',
5470
 
            help='Branch in which to place the tag.'),
 
5259
        Option('directory',
 
5260
            help='Branch in which to place the tag.',
 
5261
            short_name='d',
 
5262
            type=unicode,
 
5263
            ),
5471
5264
        Option('force',
5472
5265
            help='Replace existing tags.',
5473
5266
            ),
5474
5267
        'revision',
5475
5268
        ]
5476
5269
 
5477
 
    def run(self, tag_name=None,
 
5270
    def run(self, tag_name,
5478
5271
            delete=None,
5479
5272
            directory='.',
5480
5273
            force=None,
5481
5274
            revision=None,
5482
5275
            ):
5483
5276
        branch, relpath = Branch.open_containing(directory)
5484
 
        self.add_cleanup(branch.lock_write().unlock)
 
5277
        branch.lock_write()
 
5278
        self.add_cleanup(branch.unlock)
5485
5279
        if delete:
5486
 
            if tag_name is None:
5487
 
                raise errors.BzrCommandError("No tag specified to delete.")
5488
5280
            branch.tags.delete_tag(tag_name)
5489
 
            note('Deleted tag %s.' % tag_name)
 
5281
            self.outf.write('Deleted tag %s.\n' % tag_name)
5490
5282
        else:
5491
5283
            if revision:
5492
5284
                if len(revision) != 1:
5496
5288
                revision_id = revision[0].as_revision_id(branch)
5497
5289
            else:
5498
5290
                revision_id = branch.last_revision()
5499
 
            if tag_name is None:
5500
 
                tag_name = branch.automatic_tag_name(revision_id)
5501
 
                if tag_name is None:
5502
 
                    raise errors.BzrCommandError(
5503
 
                        "Please specify a tag name.")
5504
5291
            if (not force) and branch.tags.has_tag(tag_name):
5505
5292
                raise errors.TagAlreadyExists(tag_name)
5506
5293
            branch.tags.set_tag(tag_name, revision_id)
5507
 
            note('Created tag %s.' % tag_name)
 
5294
            self.outf.write('Created tag %s.\n' % tag_name)
5508
5295
 
5509
5296
 
5510
5297
class cmd_tags(Command):
5511
 
    __doc__ = """List tags.
 
5298
    """List tags.
5512
5299
 
5513
5300
    This command shows a table of tag names and the revisions they reference.
5514
5301
    """
5515
5302
 
5516
5303
    _see_also = ['tag']
5517
5304
    takes_options = [
5518
 
        custom_help('directory',
5519
 
            help='Branch whose tags should be displayed.'),
5520
 
        RegistryOption('sort',
 
5305
        Option('directory',
 
5306
            help='Branch whose tags should be displayed.',
 
5307
            short_name='d',
 
5308
            type=unicode,
 
5309
            ),
 
5310
        RegistryOption.from_kwargs('sort',
5521
5311
            'Sort tags by different criteria.', title='Sorting',
5522
 
            lazy_registry=('bzrlib.tag', 'tag_sort_methods')
 
5312
            alpha='Sort tags lexicographically (default).',
 
5313
            time='Sort tags chronologically.',
5523
5314
            ),
5524
5315
        'show-ids',
5525
5316
        'revision',
5526
5317
    ]
5527
5318
 
5528
5319
    @display_command
5529
 
    def run(self, directory='.', sort=None, show_ids=False, revision=None):
5530
 
        from bzrlib.tag import tag_sort_methods
 
5320
    def run(self,
 
5321
            directory='.',
 
5322
            sort='alpha',
 
5323
            show_ids=False,
 
5324
            revision=None,
 
5325
            ):
5531
5326
        branch, relpath = Branch.open_containing(directory)
5532
5327
 
5533
5328
        tags = branch.tags.get_tag_dict().items()
5534
5329
        if not tags:
5535
5330
            return
5536
5331
 
5537
 
        self.add_cleanup(branch.lock_read().unlock)
 
5332
        branch.lock_read()
 
5333
        self.add_cleanup(branch.unlock)
5538
5334
        if revision:
5539
5335
            graph = branch.repository.get_graph()
5540
5336
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5542
5338
            # only show revisions between revid1 and revid2 (inclusive)
5543
5339
            tags = [(tag, revid) for tag, revid in tags if
5544
5340
                graph.is_between(revid, revid1, revid2)]
5545
 
        if sort is None:
5546
 
            sort = tag_sort_methods.get()
5547
 
        sort(branch, tags)
 
5341
        if sort == 'alpha':
 
5342
            tags.sort()
 
5343
        elif sort == 'time':
 
5344
            timestamps = {}
 
5345
            for tag, revid in tags:
 
5346
                try:
 
5347
                    revobj = branch.repository.get_revision(revid)
 
5348
                except errors.NoSuchRevision:
 
5349
                    timestamp = sys.maxint # place them at the end
 
5350
                else:
 
5351
                    timestamp = revobj.timestamp
 
5352
                timestamps[revid] = timestamp
 
5353
            tags.sort(key=lambda x: timestamps[x[1]])
5548
5354
        if not show_ids:
5549
5355
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5550
5356
            for index, (tag, revid) in enumerate(tags):
5552
5358
                    revno = branch.revision_id_to_dotted_revno(revid)
5553
5359
                    if isinstance(revno, tuple):
5554
5360
                        revno = '.'.join(map(str, revno))
5555
 
                except (errors.NoSuchRevision, errors.GhostRevisionsHaveNoRevno):
 
5361
                except errors.NoSuchRevision:
5556
5362
                    # Bad tag data/merges can lead to tagged revisions
5557
5363
                    # which are not in this branch. Fail gracefully ...
5558
5364
                    revno = '?'
5563
5369
 
5564
5370
 
5565
5371
class cmd_reconfigure(Command):
5566
 
    __doc__ = """Reconfigure the type of a bzr directory.
 
5372
    """Reconfigure the type of a bzr directory.
5567
5373
 
5568
5374
    A target configuration must be specified.
5569
5375
 
5654
5460
 
5655
5461
 
5656
5462
class cmd_switch(Command):
5657
 
    __doc__ = """Set the branch of a checkout and update.
 
5463
    """Set the branch of a checkout and update.
5658
5464
 
5659
5465
    For lightweight checkouts, this changes the branch being referenced.
5660
5466
    For heavyweight checkouts, this checks that there are no local commits
5677
5483
    """
5678
5484
 
5679
5485
    takes_args = ['to_location?']
5680
 
    takes_options = ['directory',
5681
 
                     Option('force',
 
5486
    takes_options = [Option('force',
5682
5487
                        help='Switch even if local commits will be lost.'),
5683
5488
                     'revision',
5684
5489
                     Option('create-branch', short_name='b',
5687
5492
                    ]
5688
5493
 
5689
5494
    def run(self, to_location=None, force=False, create_branch=False,
5690
 
            revision=None, directory=u'.'):
 
5495
            revision=None):
5691
5496
        from bzrlib import switch
5692
 
        tree_location = directory
 
5497
        tree_location = '.'
5693
5498
        revision = _get_one_revision('switch', revision)
5694
5499
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5695
5500
        if to_location is None:
5696
5501
            if revision is None:
5697
5502
                raise errors.BzrCommandError('You must supply either a'
5698
5503
                                             ' revision or a location')
5699
 
            to_location = tree_location
 
5504
            to_location = '.'
5700
5505
        try:
5701
5506
            branch = control_dir.open_branch()
5702
5507
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5751
5556
 
5752
5557
 
5753
5558
class cmd_view(Command):
5754
 
    __doc__ = """Manage filtered views.
 
5559
    """Manage filtered views.
5755
5560
 
5756
5561
    Views provide a mask over the tree so that users can focus on
5757
5562
    a subset of a tree when doing their work. After creating a view,
5837
5642
            name=None,
5838
5643
            switch=None,
5839
5644
            ):
5840
 
        tree, file_list = WorkingTree.open_containing_paths(file_list,
5841
 
            apply_view=False)
 
5645
        tree, file_list = tree_files(file_list, apply_view=False)
5842
5646
        current_view, view_dict = tree.views.get_view_info()
5843
5647
        if name is None:
5844
5648
            name = current_view
5906
5710
 
5907
5711
 
5908
5712
class cmd_hooks(Command):
5909
 
    __doc__ = """Show hooks."""
 
5713
    """Show hooks."""
5910
5714
 
5911
5715
    hidden = True
5912
5716
 
5925
5729
                    self.outf.write("    <no hooks installed>\n")
5926
5730
 
5927
5731
 
5928
 
class cmd_remove_branch(Command):
5929
 
    __doc__ = """Remove a branch.
5930
 
 
5931
 
    This will remove the branch from the specified location but 
5932
 
    will keep any working tree or repository in place.
5933
 
 
5934
 
    :Examples:
5935
 
 
5936
 
      Remove the branch at repo/trunk::
5937
 
 
5938
 
        bzr remove-branch repo/trunk
5939
 
 
5940
 
    """
5941
 
 
5942
 
    takes_args = ["location?"]
5943
 
 
5944
 
    aliases = ["rmbranch"]
5945
 
 
5946
 
    def run(self, location=None):
5947
 
        if location is None:
5948
 
            location = "."
5949
 
        branch = Branch.open_containing(location)[0]
5950
 
        branch.bzrdir.destroy_branch()
5951
 
 
5952
 
 
5953
5732
class cmd_shelve(Command):
5954
 
    __doc__ = """Temporarily set aside some changes from the current tree.
 
5733
    """Temporarily set aside some changes from the current tree.
5955
5734
 
5956
5735
    Shelve allows you to temporarily put changes you've made "on the shelf",
5957
5736
    ie. out of the way, until a later time when you can bring them back from
5973
5752
 
5974
5753
    You can put multiple items on the shelf, and by default, 'unshelve' will
5975
5754
    restore the most recently shelved changes.
5976
 
 
5977
 
    For complicated changes, it is possible to edit the changes in a separate
5978
 
    editor program to decide what the file remaining in the working copy
5979
 
    should look like.  To do this, add the configuration option
5980
 
 
5981
 
        change_editor = PROGRAM @new_path @old_path
5982
 
 
5983
 
    where @new_path is replaced with the path of the new version of the 
5984
 
    file and @old_path is replaced with the path of the old version of 
5985
 
    the file.  The PROGRAM should save the new file with the desired 
5986
 
    contents of the file in the working tree.
5987
 
        
5988
5755
    """
5989
5756
 
5990
5757
    takes_args = ['file*']
5991
5758
 
5992
5759
    takes_options = [
5993
 
        'directory',
5994
5760
        'revision',
5995
5761
        Option('all', help='Shelve all changes.'),
5996
5762
        'message',
6002
5768
        Option('destroy',
6003
5769
               help='Destroy removed changes instead of shelving them.'),
6004
5770
    ]
6005
 
    _see_also = ['unshelve', 'configuration']
 
5771
    _see_also = ['unshelve']
6006
5772
 
6007
5773
    def run(self, revision=None, all=False, file_list=None, message=None,
6008
 
            writer=None, list=False, destroy=False, directory=None):
 
5774
            writer=None, list=False, destroy=False):
6009
5775
        if list:
6010
 
            return self.run_for_list(directory=directory)
 
5776
            return self.run_for_list()
6011
5777
        from bzrlib.shelf_ui import Shelver
6012
5778
        if writer is None:
6013
5779
            writer = bzrlib.option.diff_writer_registry.get()
6014
5780
        try:
6015
5781
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
6016
 
                file_list, message, destroy=destroy, directory=directory)
 
5782
                file_list, message, destroy=destroy)
6017
5783
            try:
6018
5784
                shelver.run()
6019
5785
            finally:
6021
5787
        except errors.UserAbort:
6022
5788
            return 0
6023
5789
 
6024
 
    def run_for_list(self, directory=None):
6025
 
        if directory is None:
6026
 
            directory = u'.'
6027
 
        tree = WorkingTree.open_containing(directory)[0]
6028
 
        self.add_cleanup(tree.lock_read().unlock)
 
5790
    def run_for_list(self):
 
5791
        tree = WorkingTree.open_containing('.')[0]
 
5792
        tree.lock_read()
 
5793
        self.add_cleanup(tree.unlock)
6029
5794
        manager = tree.get_shelf_manager()
6030
5795
        shelves = manager.active_shelves()
6031
5796
        if len(shelves) == 0:
6040
5805
 
6041
5806
 
6042
5807
class cmd_unshelve(Command):
6043
 
    __doc__ = """Restore shelved changes.
 
5808
    """Restore shelved changes.
6044
5809
 
6045
5810
    By default, the most recently shelved changes are restored. However if you
6046
5811
    specify a shelf by id those changes will be restored instead.  This works
6049
5814
 
6050
5815
    takes_args = ['shelf_id?']
6051
5816
    takes_options = [
6052
 
        'directory',
6053
5817
        RegistryOption.from_kwargs(
6054
5818
            'action', help="The action to perform.",
6055
5819
            enum_switch=False, value_switches=True,
6063
5827
    ]
6064
5828
    _see_also = ['shelve']
6065
5829
 
6066
 
    def run(self, shelf_id=None, action='apply', directory=u'.'):
 
5830
    def run(self, shelf_id=None, action='apply'):
6067
5831
        from bzrlib.shelf_ui import Unshelver
6068
 
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
 
5832
        unshelver = Unshelver.from_args(shelf_id, action)
6069
5833
        try:
6070
5834
            unshelver.run()
6071
5835
        finally:
6073
5837
 
6074
5838
 
6075
5839
class cmd_clean_tree(Command):
6076
 
    __doc__ = """Remove unwanted files from working tree.
 
5840
    """Remove unwanted files from working tree.
6077
5841
 
6078
5842
    By default, only unknown files, not ignored files, are deleted.  Versioned
6079
5843
    files are never deleted.
6087
5851
 
6088
5852
    To check what clean-tree will do, use --dry-run.
6089
5853
    """
6090
 
    takes_options = ['directory',
6091
 
                     Option('ignored', help='Delete all ignored files.'),
6092
 
                     Option('detritus', help='Delete conflict files, merge and revert'
 
5854
    takes_options = [Option('ignored', help='Delete all ignored files.'),
 
5855
                     Option('detritus', help='Delete conflict files, merge'
6093
5856
                            ' backups, and failed selftest dirs.'),
6094
5857
                     Option('unknown',
6095
5858
                            help='Delete files unknown to bzr (default).'),
6097
5860
                            ' deleting them.'),
6098
5861
                     Option('force', help='Do not prompt before deleting.')]
6099
5862
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6100
 
            force=False, directory=u'.'):
 
5863
            force=False):
6101
5864
        from bzrlib.clean_tree import clean_tree
6102
5865
        if not (unknown or ignored or detritus):
6103
5866
            unknown = True
6104
5867
        if dry_run:
6105
5868
            force = True
6106
 
        clean_tree(directory, unknown=unknown, ignored=ignored,
6107
 
                   detritus=detritus, dry_run=dry_run, no_prompt=force)
 
5869
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
 
5870
                   dry_run=dry_run, no_prompt=force)
6108
5871
 
6109
5872
 
6110
5873
class cmd_reference(Command):
6111
 
    __doc__ = """list, view and set branch locations for nested trees.
 
5874
    """list, view and set branch locations for nested trees.
6112
5875
 
6113
5876
    If no arguments are provided, lists the branch locations for nested trees.
6114
5877
    If one argument is provided, display the branch location for that tree.
6154
5917
            self.outf.write('%s %s\n' % (path, location))
6155
5918
 
6156
5919
 
6157
 
class cmd_export_pot(Command):
6158
 
    __doc__ = """Export command helps and error messages in po format."""
6159
 
 
6160
 
    hidden = True
6161
 
 
6162
 
    def run(self):
6163
 
        from bzrlib.export_pot import export_pot
6164
 
        export_pot(self.outf)
6165
 
 
6166
 
 
6167
 
def _register_lazy_builtins():
6168
 
    # register lazy builtins from other modules; called at startup and should
6169
 
    # be only called once.
6170
 
    for (name, aliases, module_name) in [
6171
 
        ('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6172
 
        ('cmd_config', [], 'bzrlib.config'),
6173
 
        ('cmd_dpush', [], 'bzrlib.foreign'),
6174
 
        ('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6175
 
        ('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6176
 
        ('cmd_conflicts', [], 'bzrlib.conflicts'),
6177
 
        ('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6178
 
        ('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6179
 
        ]:
6180
 
        builtin_command_registry.register_lazy(name, aliases, module_name)
 
5920
# these get imported and then picked up by the scan for cmd_*
 
5921
# TODO: Some more consistent way to split command definitions across files;
 
5922
# we do need to load at least some information about them to know of
 
5923
# aliases.  ideally we would avoid loading the implementation until the
 
5924
# details were needed.
 
5925
from bzrlib.cmd_version_info import cmd_version_info
 
5926
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
 
5927
from bzrlib.bundle.commands import (
 
5928
    cmd_bundle_info,
 
5929
    )
 
5930
from bzrlib.foreign import cmd_dpush
 
5931
from bzrlib.sign_my_commits import cmd_sign_my_commits