/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
from bzrlib.lazy_import import lazy_import
22
22
lazy_import(globals(), """
 
23
import codecs
23
24
import cStringIO
24
 
import itertools
25
 
import re
26
25
import sys
27
26
import time
28
27
 
34
33
    bzrdir,
35
34
    directory_service,
36
35
    delta,
37
 
    config as _mod_config,
 
36
    config,
38
37
    errors,
39
38
    globbing,
40
39
    hooks,
76
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
77
76
 
78
77
 
79
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
80
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
81
79
    apply_view=True):
82
 
    return internal_tree_files(file_list, default_branch, canonicalize,
83
 
        apply_view)
 
80
    try:
 
81
        return internal_tree_files(file_list, default_branch, canonicalize,
 
82
            apply_view)
 
83
    except errors.FileInWrongBranch, e:
 
84
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
85
                                     (e.path, file_list[0]))
84
86
 
85
87
 
86
88
def tree_files_for_add(file_list):
150
152
 
151
153
# XXX: Bad function name; should possibly also be a class method of
152
154
# WorkingTree rather than a function.
153
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
154
155
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
155
156
    apply_view=True):
156
157
    """Convert command-line paths to a WorkingTree and relative paths.
157
158
 
158
 
    Deprecated: use WorkingTree.open_containing_paths instead.
159
 
 
160
159
    This is typically used for command-line processors that take one or
161
160
    more filenames, and infer the workingtree that contains them.
162
161
 
172
171
 
173
172
    :return: workingtree, [relative_paths]
174
173
    """
175
 
    return WorkingTree.open_containing_paths(
176
 
        file_list, default_directory='.',
177
 
        canonicalize=True,
178
 
        apply_view=True)
 
174
    if file_list is None or len(file_list) == 0:
 
175
        tree = WorkingTree.open_containing(default_branch)[0]
 
176
        if tree.supports_views() and apply_view:
 
177
            view_files = tree.views.lookup_view()
 
178
            if view_files:
 
179
                file_list = view_files
 
180
                view_str = views.view_display_str(view_files)
 
181
                note("Ignoring files outside view. View is %s" % view_str)
 
182
        return tree, file_list
 
183
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
 
184
    return tree, safe_relpath_files(tree, file_list, canonicalize,
 
185
        apply_view=apply_view)
 
186
 
 
187
 
 
188
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
 
189
    """Convert file_list into a list of relpaths in tree.
 
190
 
 
191
    :param tree: A tree to operate on.
 
192
    :param file_list: A list of user provided paths or None.
 
193
    :param apply_view: if True and a view is set, apply it or check that
 
194
        specified files are within it
 
195
    :return: A list of relative paths.
 
196
    :raises errors.PathNotChild: When a provided path is in a different tree
 
197
        than tree.
 
198
    """
 
199
    if file_list is None:
 
200
        return None
 
201
    if tree.supports_views() and apply_view:
 
202
        view_files = tree.views.lookup_view()
 
203
    else:
 
204
        view_files = []
 
205
    new_list = []
 
206
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
 
207
    # doesn't - fix that up here before we enter the loop.
 
208
    if canonicalize:
 
209
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
 
210
    else:
 
211
        fixer = tree.relpath
 
212
    for filename in file_list:
 
213
        try:
 
214
            relpath = fixer(osutils.dereference_path(filename))
 
215
            if  view_files and not osutils.is_inside_any(view_files, relpath):
 
216
                raise errors.FileOutsideView(filename, view_files)
 
217
            new_list.append(relpath)
 
218
        except errors.PathNotChild:
 
219
            raise errors.FileInWrongBranch(tree.branch, filename)
 
220
    return new_list
179
221
 
180
222
 
181
223
def _get_view_info_for_change_reporter(tree):
190
232
    return view_info
191
233
 
192
234
 
193
 
def _open_directory_or_containing_tree_or_branch(filename, directory):
194
 
    """Open the tree or branch containing the specified file, unless
195
 
    the --directory option is used to specify a different branch."""
196
 
    if directory is not None:
197
 
        return (None, Branch.open(directory), filename)
198
 
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
199
 
 
200
 
 
201
235
# TODO: Make sure no commands unconditionally use the working directory as a
202
236
# branch.  If a filename argument is used, the first of them should be used to
203
237
# specify the branch.  (Perhaps this can be factored out into some kind of
281
315
            raise errors.BzrCommandError('bzr status --revision takes exactly'
282
316
                                         ' one or two revision specifiers')
283
317
 
284
 
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
 
318
        tree, relfile_list = tree_files(file_list)
285
319
        # Avoid asking for specific files when that is not needed.
286
320
        if relfile_list == ['']:
287
321
            relfile_list = None
306
340
 
307
341
    hidden = True
308
342
    takes_args = ['revision_id?']
309
 
    takes_options = ['directory', 'revision']
 
343
    takes_options = ['revision']
310
344
    # cat-revision is more for frontends so should be exact
311
345
    encoding = 'strict'
312
346
 
319
353
        self.outf.write(revtext.decode('utf-8'))
320
354
 
321
355
    @display_command
322
 
    def run(self, revision_id=None, revision=None, directory=u'.'):
 
356
    def run(self, revision_id=None, revision=None):
323
357
        if revision_id is not None and revision is not None:
324
358
            raise errors.BzrCommandError('You can only supply one of'
325
359
                                         ' revision_id or --revision')
326
360
        if revision_id is None and revision is None:
327
361
            raise errors.BzrCommandError('You must supply either'
328
362
                                         ' --revision or a revision_id')
329
 
        b = WorkingTree.open_containing(directory)[0].branch
 
363
        b = WorkingTree.open_containing(u'.')[0].branch
330
364
 
331
365
        revisions = b.repository.revisions
332
366
        if revisions is None:
449
483
    takes_options = [
450
484
        Option('force',
451
485
               help='Remove the working tree even if it has '
452
 
                    'uncommitted or shelved changes.'),
 
486
                    'uncommitted changes.'),
453
487
        ]
454
488
 
455
489
    def run(self, location_list, force=False):
469
503
            if not force:
470
504
                if (working.has_changes()):
471
505
                    raise errors.UncommittedChanges(working)
472
 
                if working.get_shelf_manager().last_shelf() is not None:
473
 
                    raise errors.ShelvedChanges(working)
474
506
 
475
507
            if working.user_url != working.branch.user_url:
476
508
                raise errors.BzrCommandError("You cannot remove the working tree"
496
528
        if tree:
497
529
            try:
498
530
                wt = WorkingTree.open_containing(location)[0]
499
 
                self.add_cleanup(wt.lock_read().unlock)
 
531
                wt.lock_read()
500
532
            except (errors.NoWorkingTree, errors.NotLocalUrl):
501
533
                raise errors.NoWorkingTree(location)
 
534
            self.add_cleanup(wt.unlock)
502
535
            revid = wt.last_revision()
503
536
            try:
504
537
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
507
540
            revno = ".".join(str(n) for n in revno_t)
508
541
        else:
509
542
            b = Branch.open_containing(location)[0]
510
 
            self.add_cleanup(b.lock_read().unlock)
 
543
            b.lock_read()
 
544
            self.add_cleanup(b.unlock)
511
545
            revno = b.revno()
512
546
        self.cleanup_now()
513
547
        self.outf.write(str(revno) + '\n')
520
554
    takes_args = ['revision_info*']
521
555
    takes_options = [
522
556
        'revision',
523
 
        custom_help('directory',
 
557
        Option('directory',
524
558
            help='Branch to examine, '
525
 
                 'rather than the one containing the working directory.'),
 
559
                 'rather than the one containing the working directory.',
 
560
            short_name='d',
 
561
            type=unicode,
 
562
            ),
526
563
        Option('tree', help='Show revno of working tree'),
527
564
        ]
528
565
 
533
570
        try:
534
571
            wt = WorkingTree.open_containing(directory)[0]
535
572
            b = wt.branch
536
 
            self.add_cleanup(wt.lock_read().unlock)
 
573
            wt.lock_read()
 
574
            self.add_cleanup(wt.unlock)
537
575
        except (errors.NoWorkingTree, errors.NotLocalUrl):
538
576
            wt = None
539
577
            b = Branch.open_containing(directory)[0]
540
 
            self.add_cleanup(b.lock_read().unlock)
 
578
            b.lock_read()
 
579
            self.add_cleanup(b.unlock)
541
580
        revision_ids = []
542
581
        if revision is not None:
543
582
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
642
681
                should_print=(not is_quiet()))
643
682
 
644
683
        if base_tree:
645
 
            self.add_cleanup(base_tree.lock_read().unlock)
 
684
            base_tree.lock_read()
 
685
            self.add_cleanup(base_tree.unlock)
646
686
        tree, file_list = tree_files_for_add(file_list)
647
687
        added, ignored = tree.smart_add(file_list, not
648
688
            no_recurse, action=action, save=not dry_run)
719
759
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
720
760
 
721
761
        revision = _get_one_revision('inventory', revision)
722
 
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
723
 
        self.add_cleanup(work_tree.lock_read().unlock)
 
762
        work_tree, file_list = tree_files(file_list)
 
763
        work_tree.lock_read()
 
764
        self.add_cleanup(work_tree.unlock)
724
765
        if revision is not None:
725
766
            tree = revision.as_tree(work_tree.branch)
726
767
 
727
768
            extra_trees = [work_tree]
728
 
            self.add_cleanup(tree.lock_read().unlock)
 
769
            tree.lock_read()
 
770
            self.add_cleanup(tree.unlock)
729
771
        else:
730
772
            tree = work_tree
731
773
            extra_trees = []
790
832
            names_list = []
791
833
        if len(names_list) < 2:
792
834
            raise errors.BzrCommandError("missing file argument")
793
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
794
 
        self.add_cleanup(tree.lock_tree_write().unlock)
 
835
        tree, rel_names = tree_files(names_list, canonicalize=False)
 
836
        tree.lock_tree_write()
 
837
        self.add_cleanup(tree.unlock)
795
838
        self._run(tree, names_list, rel_names, after)
796
839
 
797
840
    def run_auto(self, names_list, after, dry_run):
801
844
        if after:
802
845
            raise errors.BzrCommandError('--after cannot be specified with'
803
846
                                         ' --auto.')
804
 
        work_tree, file_list = WorkingTree.open_containing_paths(
805
 
            names_list, default_directory='.')
806
 
        self.add_cleanup(work_tree.lock_tree_write().unlock)
 
847
        work_tree, file_list = tree_files(names_list, default_branch='.')
 
848
        work_tree.lock_tree_write()
 
849
        self.add_cleanup(work_tree.unlock)
807
850
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
808
851
 
809
852
    def _run(self, tree, names_list, rel_names, after):
917
960
    takes_options = ['remember', 'overwrite', 'revision',
918
961
        custom_help('verbose',
919
962
            help='Show logs of pulled revisions.'),
920
 
        custom_help('directory',
 
963
        Option('directory',
921
964
            help='Branch to pull into, '
922
 
                 'rather than the one containing the working directory.'),
 
965
                 'rather than the one containing the working directory.',
 
966
            short_name='d',
 
967
            type=unicode,
 
968
            ),
923
969
        Option('local',
924
970
            help="Perform a local pull in a bound "
925
971
                 "branch.  Local pulls are not applied to "
926
972
                 "the master branch."
927
973
            ),
928
 
        Option('show-base',
929
 
            help="Show base revision text in conflicts.")
930
974
        ]
931
975
    takes_args = ['location?']
932
976
    encoding_type = 'replace'
933
977
 
934
978
    def run(self, location=None, remember=False, overwrite=False,
935
979
            revision=None, verbose=False,
936
 
            directory=None, local=False,
937
 
            show_base=False):
 
980
            directory=None, local=False):
938
981
        # FIXME: too much stuff is in the command class
939
982
        revision_id = None
940
983
        mergeable = None
943
986
        try:
944
987
            tree_to = WorkingTree.open_containing(directory)[0]
945
988
            branch_to = tree_to.branch
946
 
            self.add_cleanup(tree_to.lock_write().unlock)
 
989
            tree_to.lock_write()
 
990
            self.add_cleanup(tree_to.unlock)
947
991
        except errors.NoWorkingTree:
948
992
            tree_to = None
949
993
            branch_to = Branch.open_containing(directory)[0]
950
 
            self.add_cleanup(branch_to.lock_write().unlock)
951
 
 
952
 
        if tree_to is None and show_base:
953
 
            raise errors.BzrCommandError("Need working tree for --show-base.")
 
994
            branch_to.lock_write()
 
995
            self.add_cleanup(branch_to.unlock)
954
996
 
955
997
        if local and not branch_to.get_bound_location():
956
998
            raise errors.LocalRequiresBoundBranch()
987
1029
        else:
988
1030
            branch_from = Branch.open(location,
989
1031
                possible_transports=possible_transports)
990
 
            self.add_cleanup(branch_from.lock_read().unlock)
 
1032
            branch_from.lock_read()
 
1033
            self.add_cleanup(branch_from.unlock)
991
1034
 
992
1035
            if branch_to.get_parent() is None or remember:
993
1036
                branch_to.set_parent(branch_from.base)
1002
1045
                view_info=view_info)
1003
1046
            result = tree_to.pull(
1004
1047
                branch_from, overwrite, revision_id, change_reporter,
1005
 
                possible_transports=possible_transports, local=local,
1006
 
                show_base=show_base)
 
1048
                possible_transports=possible_transports, local=local)
1007
1049
        else:
1008
1050
            result = branch_to.pull(
1009
1051
                branch_from, overwrite, revision_id, local=local)
1046
1088
        Option('create-prefix',
1047
1089
               help='Create the path leading up to the branch '
1048
1090
                    'if it does not already exist.'),
1049
 
        custom_help('directory',
 
1091
        Option('directory',
1050
1092
            help='Branch to push from, '
1051
 
                 'rather than the one containing the working directory.'),
 
1093
                 'rather than the one containing the working directory.',
 
1094
            short_name='d',
 
1095
            type=unicode,
 
1096
            ),
1052
1097
        Option('use-existing-dir',
1053
1098
               help='By default push will fail if the target'
1054
1099
                    ' directory exists, but does not already'
1143
1188
 
1144
1189
    _see_also = ['checkout']
1145
1190
    takes_args = ['from_location', 'to_location?']
1146
 
    takes_options = ['revision',
1147
 
        Option('hardlink', help='Hard-link working tree files where possible.'),
1148
 
        Option('files-from', type=str,
1149
 
               help="Get file contents from this tree."),
 
1191
    takes_options = ['revision', Option('hardlink',
 
1192
        help='Hard-link working tree files where possible.'),
1150
1193
        Option('no-tree',
1151
1194
            help="Create a branch without a working-tree."),
1152
1195
        Option('switch',
1170
1213
 
1171
1214
    def run(self, from_location, to_location=None, revision=None,
1172
1215
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1173
 
            use_existing_dir=False, switch=False, bind=False,
1174
 
            files_from=None):
 
1216
            use_existing_dir=False, switch=False, bind=False):
1175
1217
        from bzrlib import switch as _mod_switch
1176
1218
        from bzrlib.tag import _merge_tags_if_possible
1177
1219
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1178
1220
            from_location)
1179
 
        if not (hardlink or files_from):
1180
 
            # accelerator_tree is usually slower because you have to read N
1181
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1182
 
            # explicitly request it
1183
 
            accelerator_tree = None
1184
 
        if files_from is not None and files_from != from_location:
1185
 
            accelerator_tree = WorkingTree.open(files_from)
1186
1221
        revision = _get_one_revision('branch', revision)
1187
 
        self.add_cleanup(br_from.lock_read().unlock)
 
1222
        br_from.lock_read()
 
1223
        self.add_cleanup(br_from.unlock)
1188
1224
        if revision is not None:
1189
1225
            revision_id = revision.as_revision_id(br_from)
1190
1226
        else:
1295
1331
            to_location = branch_location
1296
1332
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1297
1333
            branch_location)
1298
 
        if not (hardlink or files_from):
1299
 
            # accelerator_tree is usually slower because you have to read N
1300
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1301
 
            # explicitly request it
1302
 
            accelerator_tree = None
1303
1334
        revision = _get_one_revision('checkout', revision)
1304
 
        if files_from is not None and files_from != branch_location:
 
1335
        if files_from is not None:
1305
1336
            accelerator_tree = WorkingTree.open(files_from)
1306
1337
        if revision is not None:
1307
1338
            revision_id = revision.as_revision_id(source)
1335
1366
    @display_command
1336
1367
    def run(self, dir=u'.'):
1337
1368
        tree = WorkingTree.open_containing(dir)[0]
1338
 
        self.add_cleanup(tree.lock_read().unlock)
 
1369
        tree.lock_read()
 
1370
        self.add_cleanup(tree.unlock)
1339
1371
        new_inv = tree.inventory
1340
1372
        old_tree = tree.basis_tree()
1341
 
        self.add_cleanup(old_tree.lock_read().unlock)
 
1373
        old_tree.lock_read()
 
1374
        self.add_cleanup(old_tree.unlock)
1342
1375
        old_inv = old_tree.inventory
1343
1376
        renames = []
1344
1377
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1363
1396
    If you want to discard your local changes, you can just do a
1364
1397
    'bzr revert' instead of 'bzr commit' after the update.
1365
1398
 
1366
 
    If you want to restore a file that has been removed locally, use
1367
 
    'bzr revert' instead of 'bzr update'.
1368
 
 
1369
1399
    If the tree's branch is bound to a master branch, it will also update
1370
1400
    the branch from the master.
1371
1401
    """
1372
1402
 
1373
1403
    _see_also = ['pull', 'working-trees', 'status-flags']
1374
1404
    takes_args = ['dir?']
1375
 
    takes_options = ['revision',
1376
 
                     Option('show-base',
1377
 
                            help="Show base revision text in conflicts."),
1378
 
                     ]
 
1405
    takes_options = ['revision']
1379
1406
    aliases = ['up']
1380
1407
 
1381
 
    def run(self, dir='.', revision=None, show_base=None):
 
1408
    def run(self, dir='.', revision=None):
1382
1409
        if revision is not None and len(revision) != 1:
1383
1410
            raise errors.BzrCommandError(
1384
1411
                        "bzr update --revision takes exactly one revision")
1388
1415
        master = branch.get_master_branch(
1389
1416
            possible_transports=possible_transports)
1390
1417
        if master is not None:
 
1418
            tree.lock_write()
1391
1419
            branch_location = master.base
1392
 
            tree.lock_write()
1393
1420
        else:
 
1421
            tree.lock_tree_write()
1394
1422
            branch_location = tree.branch.base
1395
 
            tree.lock_tree_write()
1396
1423
        self.add_cleanup(tree.unlock)
1397
1424
        # get rid of the final '/' and be ready for display
1398
1425
        branch_location = urlutils.unescape_for_display(
1424
1451
                change_reporter,
1425
1452
                possible_transports=possible_transports,
1426
1453
                revision=revision_id,
1427
 
                old_tip=old_tip,
1428
 
                show_base=show_base)
 
1454
                old_tip=old_tip)
1429
1455
        except errors.NoSuchRevision, e:
1430
1456
            raise errors.BzrCommandError(
1431
1457
                                  "branch has no revision %s\n"
1493
1519
class cmd_remove(Command):
1494
1520
    __doc__ = """Remove files or directories.
1495
1521
 
1496
 
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1497
 
    delete them if they can easily be recovered using revert otherwise they
1498
 
    will be backed up (adding an extention of the form .~#~). If no options or
1499
 
    parameters are given Bazaar will scan for files that are being tracked by
1500
 
    Bazaar but missing in your tree and stop tracking them for you.
 
1522
    This makes bzr stop tracking changes to the specified files. bzr will delete
 
1523
    them if they can easily be recovered using revert. If no options or
 
1524
    parameters are given bzr will scan for files that are being tracked by bzr
 
1525
    but missing in your tree and stop tracking them for you.
1501
1526
    """
1502
1527
    takes_args = ['file*']
1503
1528
    takes_options = ['verbose',
1505
1530
        RegistryOption.from_kwargs('file-deletion-strategy',
1506
1531
            'The file deletion mode to be used.',
1507
1532
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1508
 
            safe='Backup changed files (default).',
 
1533
            safe='Only delete files if they can be'
 
1534
                 ' safely recovered (default).',
1509
1535
            keep='Delete from bzr but leave the working copy.',
1510
 
            no_backup='Don\'t backup changed files.',
1511
1536
            force='Delete all the specified files, even if they can not be '
1512
 
                'recovered and even if they are non-empty directories. '
1513
 
                '(deprecated, use no-backup)')]
 
1537
                'recovered and even if they are non-empty directories.')]
1514
1538
    aliases = ['rm', 'del']
1515
1539
    encoding_type = 'replace'
1516
1540
 
1517
1541
    def run(self, file_list, verbose=False, new=False,
1518
1542
        file_deletion_strategy='safe'):
1519
 
        if file_deletion_strategy == 'force':
1520
 
            note("(The --force option is deprecated, rather use --no-backup "
1521
 
                "in future.)")
1522
 
            file_deletion_strategy = 'no-backup'
1523
 
 
1524
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
1543
        tree, file_list = tree_files(file_list)
1525
1544
 
1526
1545
        if file_list is not None:
1527
1546
            file_list = [f for f in file_list]
1528
1547
 
1529
 
        self.add_cleanup(tree.lock_write().unlock)
 
1548
        tree.lock_write()
 
1549
        self.add_cleanup(tree.unlock)
1530
1550
        # Heuristics should probably all move into tree.remove_smart or
1531
1551
        # some such?
1532
1552
        if new:
1547
1567
            file_deletion_strategy = 'keep'
1548
1568
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1549
1569
            keep_files=file_deletion_strategy=='keep',
1550
 
            force=(file_deletion_strategy=='no-backup'))
 
1570
            force=file_deletion_strategy=='force')
1551
1571
 
1552
1572
 
1553
1573
class cmd_file_id(Command):
1615
1635
 
1616
1636
    _see_also = ['check']
1617
1637
    takes_args = ['branch?']
1618
 
    takes_options = [
1619
 
        Option('canonicalize-chks',
1620
 
               help='Make sure CHKs are in canonical form (repairs '
1621
 
                    'bug 522637).',
1622
 
               hidden=True),
1623
 
        ]
1624
1638
 
1625
 
    def run(self, branch=".", canonicalize_chks=False):
 
1639
    def run(self, branch="."):
1626
1640
        from bzrlib.reconcile import reconcile
1627
1641
        dir = bzrdir.BzrDir.open(branch)
1628
 
        reconcile(dir, canonicalize_chks=canonicalize_chks)
 
1642
        reconcile(dir)
1629
1643
 
1630
1644
 
1631
1645
class cmd_revision_history(Command):
1907
1921
        Same as 'bzr diff' but prefix paths with old/ and new/::
1908
1922
 
1909
1923
            bzr diff --prefix old/:new/
1910
 
            
1911
 
        Show the differences using a custom diff program with options::
1912
 
        
1913
 
            bzr diff --using /usr/bin/diff --diff-options -wu
1914
1924
    """
1915
1925
    _see_also = ['status']
1916
1926
    takes_args = ['file*']
1975
1985
         old_branch, new_branch,
1976
1986
         specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1977
1987
            file_list, revision, old, new, self.add_cleanup, apply_view=True)
1978
 
        # GNU diff on Windows uses ANSI encoding for filenames
1979
 
        path_encoding = osutils.get_diff_header_encoding()
1980
1988
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1981
1989
                               specific_files=specific_files,
1982
1990
                               external_diff_options=diff_options,
1983
1991
                               old_label=old_label, new_label=new_label,
1984
 
                               extra_trees=extra_trees,
1985
 
                               path_encoding=path_encoding,
1986
 
                               using=using,
 
1992
                               extra_trees=extra_trees, using=using,
1987
1993
                               format_cls=format)
1988
1994
 
1989
1995
 
1997
2003
    # level of effort but possibly much less IO.  (Or possibly not,
1998
2004
    # if the directories are very large...)
1999
2005
    _see_also = ['status', 'ls']
2000
 
    takes_options = ['directory', 'show-ids']
 
2006
    takes_options = ['show-ids']
2001
2007
 
2002
2008
    @display_command
2003
 
    def run(self, show_ids=False, directory=u'.'):
2004
 
        tree = WorkingTree.open_containing(directory)[0]
2005
 
        self.add_cleanup(tree.lock_read().unlock)
 
2009
    def run(self, show_ids=False):
 
2010
        tree = WorkingTree.open_containing(u'.')[0]
 
2011
        tree.lock_read()
 
2012
        self.add_cleanup(tree.unlock)
2006
2013
        old = tree.basis_tree()
2007
 
        self.add_cleanup(old.lock_read().unlock)
 
2014
        old.lock_read()
 
2015
        self.add_cleanup(old.unlock)
2008
2016
        for path, ie in old.inventory.iter_entries():
2009
2017
            if not tree.has_id(ie.file_id):
2010
2018
                self.outf.write(path)
2020
2028
 
2021
2029
    hidden = True
2022
2030
    _see_also = ['status', 'ls']
2023
 
    takes_options = ['directory', 'null']
 
2031
    takes_options = [
 
2032
            Option('null',
 
2033
                   help='Write an ascii NUL (\\0) separator '
 
2034
                   'between files rather than a newline.')
 
2035
            ]
2024
2036
 
2025
2037
    @display_command
2026
 
    def run(self, null=False, directory=u'.'):
2027
 
        tree = WorkingTree.open_containing(directory)[0]
 
2038
    def run(self, null=False):
 
2039
        tree = WorkingTree.open_containing(u'.')[0]
2028
2040
        td = tree.changes_from(tree.basis_tree())
2029
2041
        for path, id, kind, text_modified, meta_modified in td.modified:
2030
2042
            if null:
2039
2051
 
2040
2052
    hidden = True
2041
2053
    _see_also = ['status', 'ls']
2042
 
    takes_options = ['directory', 'null']
 
2054
    takes_options = [
 
2055
            Option('null',
 
2056
                   help='Write an ascii NUL (\\0) separator '
 
2057
                   'between files rather than a newline.')
 
2058
            ]
2043
2059
 
2044
2060
    @display_command
2045
 
    def run(self, null=False, directory=u'.'):
2046
 
        wt = WorkingTree.open_containing(directory)[0]
2047
 
        self.add_cleanup(wt.lock_read().unlock)
 
2061
    def run(self, null=False):
 
2062
        wt = WorkingTree.open_containing(u'.')[0]
 
2063
        wt.lock_read()
 
2064
        self.add_cleanup(wt.unlock)
2048
2065
        basis = wt.basis_tree()
2049
 
        self.add_cleanup(basis.lock_read().unlock)
 
2066
        basis.lock_read()
 
2067
        self.add_cleanup(basis.unlock)
2050
2068
        basis_inv = basis.inventory
2051
2069
        inv = wt.inventory
2052
2070
        for file_id in inv:
2055
2073
            if inv.is_root(file_id) and len(basis_inv) == 0:
2056
2074
                continue
2057
2075
            path = inv.id2path(file_id)
2058
 
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
 
2076
            if not os.access(osutils.abspath(path), os.F_OK):
2059
2077
                continue
2060
2078
            if null:
2061
2079
                self.outf.write(path + '\0')
2261
2279
                   help='Show just the specified revision.'
2262
2280
                   ' See also "help revisionspec".'),
2263
2281
            'log-format',
2264
 
            RegistryOption('authors',
2265
 
                'What names to list as authors - first, all or committer.',
2266
 
                title='Authors',
2267
 
                lazy_registry=('bzrlib.log', 'author_list_registry'),
2268
 
            ),
2269
2282
            Option('levels',
2270
2283
                   short_name='n',
2271
2284
                   help='Number of levels to display - 0 for all, 1 for flat.',
2306
2319
            limit=None,
2307
2320
            show_diff=False,
2308
2321
            include_merges=False,
2309
 
            authors=None,
2310
2322
            exclude_common_ancestry=False,
2311
2323
            ):
2312
2324
        from bzrlib.log import (
2340
2352
        if file_list:
2341
2353
            # find the file ids to log and check for directory filtering
2342
2354
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2343
 
                revision, file_list, self.add_cleanup)
 
2355
                revision, file_list)
 
2356
            self.add_cleanup(b.unlock)
2344
2357
            for relpath, file_id, kind in file_info_list:
2345
2358
                if file_id is None:
2346
2359
                    raise errors.BzrCommandError(
2364
2377
                location = '.'
2365
2378
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2366
2379
            b = dir.open_branch()
2367
 
            self.add_cleanup(b.lock_read().unlock)
 
2380
            b.lock_read()
 
2381
            self.add_cleanup(b.unlock)
2368
2382
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2369
2383
 
2370
2384
        # Decide on the type of delta & diff filtering to use
2390
2404
                        show_timezone=timezone,
2391
2405
                        delta_format=get_verbosity_level(),
2392
2406
                        levels=levels,
2393
 
                        show_advice=levels is None,
2394
 
                        author_list_handler=authors)
 
2407
                        show_advice=levels is None)
2395
2408
 
2396
2409
        # Choose the algorithm for doing the logging. It's annoying
2397
2410
        # having multiple code paths like this but necessary until
2495
2508
        tree, relpath = WorkingTree.open_containing(filename)
2496
2509
        file_id = tree.path2id(relpath)
2497
2510
        b = tree.branch
2498
 
        self.add_cleanup(b.lock_read().unlock)
 
2511
        b.lock_read()
 
2512
        self.add_cleanup(b.unlock)
2499
2513
        touching_revs = log.find_touching_revisions(b, file_id)
2500
2514
        for revno, revision_id, what in touching_revs:
2501
2515
            self.outf.write("%6d %s\n" % (revno, what))
2514
2528
                   help='Recurse into subdirectories.'),
2515
2529
            Option('from-root',
2516
2530
                   help='Print paths relative to the root of the branch.'),
2517
 
            Option('unknown', short_name='u',
2518
 
                help='Print unknown files.'),
 
2531
            Option('unknown', help='Print unknown files.'),
2519
2532
            Option('versioned', help='Print versioned files.',
2520
2533
                   short_name='V'),
2521
 
            Option('ignored', short_name='i',
2522
 
                help='Print ignored files.'),
2523
 
            Option('kind', short_name='k',
 
2534
            Option('ignored', help='Print ignored files.'),
 
2535
            Option('null',
 
2536
                   help='Write an ascii NUL (\\0) separator '
 
2537
                   'between files rather than a newline.'),
 
2538
            Option('kind',
2524
2539
                   help='List entries of a particular kind: file, directory, symlink.',
2525
2540
                   type=unicode),
2526
 
            'null',
2527
2541
            'show-ids',
2528
 
            'directory',
2529
2542
            ]
2530
2543
    @display_command
2531
2544
    def run(self, revision=None, verbose=False,
2532
2545
            recursive=False, from_root=False,
2533
2546
            unknown=False, versioned=False, ignored=False,
2534
 
            null=False, kind=None, show_ids=False, path=None, directory=None):
 
2547
            null=False, kind=None, show_ids=False, path=None):
2535
2548
 
2536
2549
        if kind and kind not in ('file', 'directory', 'symlink'):
2537
2550
            raise errors.BzrCommandError('invalid kind specified')
2549
2562
                raise errors.BzrCommandError('cannot specify both --from-root'
2550
2563
                                             ' and PATH')
2551
2564
            fs_path = path
2552
 
        tree, branch, relpath = \
2553
 
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
 
2565
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2566
            fs_path)
2554
2567
 
2555
2568
        # Calculate the prefix to use
2556
2569
        prefix = None
2571
2584
                view_str = views.view_display_str(view_files)
2572
2585
                note("Ignoring files outside view. View is %s" % view_str)
2573
2586
 
2574
 
        self.add_cleanup(tree.lock_read().unlock)
 
2587
        tree.lock_read()
 
2588
        self.add_cleanup(tree.unlock)
2575
2589
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2576
2590
            from_dir=relpath, recursive=recursive):
2577
2591
            # Apply additional masking
2624
2638
 
2625
2639
    hidden = True
2626
2640
    _see_also = ['ls']
2627
 
    takes_options = ['directory']
2628
2641
 
2629
2642
    @display_command
2630
 
    def run(self, directory=u'.'):
2631
 
        for f in WorkingTree.open_containing(directory)[0].unknowns():
 
2643
    def run(self):
 
2644
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
2632
2645
            self.outf.write(osutils.quotefn(f) + '\n')
2633
2646
 
2634
2647
 
2699
2712
 
2700
2713
    _see_also = ['status', 'ignored', 'patterns']
2701
2714
    takes_args = ['name_pattern*']
2702
 
    takes_options = ['directory',
 
2715
    takes_options = [
2703
2716
        Option('default-rules',
2704
2717
               help='Display the default ignore rules that bzr uses.')
2705
2718
        ]
2706
2719
 
2707
 
    def run(self, name_pattern_list=None, default_rules=None,
2708
 
            directory=u'.'):
 
2720
    def run(self, name_pattern_list=None, default_rules=None):
2709
2721
        from bzrlib import ignores
2710
2722
        if default_rules is not None:
2711
2723
            # dump the default rules and exit
2717
2729
                "NAME_PATTERN or --default-rules.")
2718
2730
        name_pattern_list = [globbing.normalize_pattern(p)
2719
2731
                             for p in name_pattern_list]
2720
 
        bad_patterns = ''
2721
 
        for p in name_pattern_list:
2722
 
            if not globbing.Globster.is_pattern_valid(p):
2723
 
                bad_patterns += ('\n  %s' % p)
2724
 
        if bad_patterns:
2725
 
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2726
 
            ui.ui_factory.show_error(msg)
2727
 
            raise errors.InvalidPattern('')
2728
2732
        for name_pattern in name_pattern_list:
2729
2733
            if (name_pattern[0] == '/' or
2730
2734
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2731
2735
                raise errors.BzrCommandError(
2732
2736
                    "NAME_PATTERN should not be an absolute path")
2733
 
        tree, relpath = WorkingTree.open_containing(directory)
 
2737
        tree, relpath = WorkingTree.open_containing(u'.')
2734
2738
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2735
2739
        ignored = globbing.Globster(name_pattern_list)
2736
2740
        matches = []
2737
 
        self.add_cleanup(tree.lock_read().unlock)
 
2741
        tree.lock_read()
2738
2742
        for entry in tree.list_files():
2739
2743
            id = entry[3]
2740
2744
            if id is not None:
2741
2745
                filename = entry[0]
2742
2746
                if ignored.match(filename):
2743
2747
                    matches.append(filename)
 
2748
        tree.unlock()
2744
2749
        if len(matches) > 0:
2745
2750
            self.outf.write("Warning: the following files are version controlled and"
2746
2751
                  " match your ignore pattern:\n%s"
2761
2766
 
2762
2767
    encoding_type = 'replace'
2763
2768
    _see_also = ['ignore', 'ls']
2764
 
    takes_options = ['directory']
2765
2769
 
2766
2770
    @display_command
2767
 
    def run(self, directory=u'.'):
2768
 
        tree = WorkingTree.open_containing(directory)[0]
2769
 
        self.add_cleanup(tree.lock_read().unlock)
 
2771
    def run(self):
 
2772
        tree = WorkingTree.open_containing(u'.')[0]
 
2773
        tree.lock_read()
 
2774
        self.add_cleanup(tree.unlock)
2770
2775
        for path, file_class, kind, file_id, entry in tree.list_files():
2771
2776
            if file_class != 'I':
2772
2777
                continue
2783
2788
    """
2784
2789
    hidden = True
2785
2790
    takes_args = ['revno']
2786
 
    takes_options = ['directory']
2787
2791
 
2788
2792
    @display_command
2789
 
    def run(self, revno, directory=u'.'):
 
2793
    def run(self, revno):
2790
2794
        try:
2791
2795
            revno = int(revno)
2792
2796
        except ValueError:
2793
2797
            raise errors.BzrCommandError("not a valid revision-number: %r"
2794
2798
                                         % revno)
2795
 
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
 
2799
        revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2796
2800
        self.outf.write("%s\n" % revid)
2797
2801
 
2798
2802
 
2825
2829
      =================       =========================
2826
2830
    """
2827
2831
    takes_args = ['dest', 'branch_or_subdir?']
2828
 
    takes_options = ['directory',
 
2832
    takes_options = [
2829
2833
        Option('format',
2830
2834
               help="Type of file to export to.",
2831
2835
               type=unicode),
2840
2844
                    'revision in which it was changed.'),
2841
2845
        ]
2842
2846
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2843
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
2847
        root=None, filters=False, per_file_timestamps=False):
2844
2848
        from bzrlib.export import export
2845
2849
 
2846
2850
        if branch_or_subdir is None:
2847
 
            tree = WorkingTree.open_containing(directory)[0]
 
2851
            tree = WorkingTree.open_containing(u'.')[0]
2848
2852
            b = tree.branch
2849
2853
            subdir = None
2850
2854
        else:
2869
2873
    """
2870
2874
 
2871
2875
    _see_also = ['ls']
2872
 
    takes_options = ['directory',
 
2876
    takes_options = [
2873
2877
        Option('name-from-revision', help='The path name in the old tree.'),
2874
2878
        Option('filters', help='Apply content filters to display the '
2875
2879
                'convenience form.'),
2880
2884
 
2881
2885
    @display_command
2882
2886
    def run(self, filename, revision=None, name_from_revision=False,
2883
 
            filters=False, directory=None):
 
2887
            filters=False):
2884
2888
        if revision is not None and len(revision) != 1:
2885
2889
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2886
2890
                                         " one revision specifier")
2887
2891
        tree, branch, relpath = \
2888
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
2889
 
        self.add_cleanup(branch.lock_read().unlock)
 
2892
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
2893
        branch.lock_read()
 
2894
        self.add_cleanup(branch.unlock)
2890
2895
        return self._run(tree, branch, relpath, filename, revision,
2891
2896
                         name_from_revision, filters)
2892
2897
 
2895
2900
        if tree is None:
2896
2901
            tree = b.basis_tree()
2897
2902
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2898
 
        self.add_cleanup(rev_tree.lock_read().unlock)
 
2903
        rev_tree.lock_read()
 
2904
        self.add_cleanup(rev_tree.unlock)
2899
2905
 
2900
2906
        old_file_id = rev_tree.path2id(relpath)
2901
2907
 
3122
3128
 
3123
3129
        properties = {}
3124
3130
 
3125
 
        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
 
3131
        tree, selected_list = tree_files(selected_list)
3126
3132
        if selected_list == ['']:
3127
3133
            # workaround - commit of root of tree should be exactly the same
3128
3134
            # as just default commit in that tree, and succeed even though
3163
3169
        def get_message(commit_obj):
3164
3170
            """Callback to get commit message"""
3165
3171
            if file:
3166
 
                f = open(file)
3167
 
                try:
3168
 
                    my_message = f.read().decode(osutils.get_user_encoding())
3169
 
                finally:
3170
 
                    f.close()
 
3172
                my_message = codecs.open(
 
3173
                    file, 'rt', osutils.get_user_encoding()).read()
3171
3174
            elif message is not None:
3172
3175
                my_message = message
3173
3176
            else:
3202
3205
                        reporter=None, verbose=verbose, revprops=properties,
3203
3206
                        authors=author, timestamp=commit_stamp,
3204
3207
                        timezone=offset,
3205
 
                        exclude=tree.safe_relpath_files(exclude))
 
3208
                        exclude=safe_relpath_files(tree, exclude))
3206
3209
        except PointlessCommit:
3207
3210
            raise errors.BzrCommandError("No changes to commit."
3208
3211
                              " Use --unchanged to commit anyhow.")
3327
3330
 
3328
3331
            bzr whoami "Frank Chu <fchu@example.com>"
3329
3332
    """
3330
 
    takes_options = [ 'directory',
3331
 
                      Option('email',
 
3333
    takes_options = [ Option('email',
3332
3334
                             help='Display email address only.'),
3333
3335
                      Option('branch',
3334
3336
                             help='Set identity for the current branch instead of '
3338
3340
    encoding_type = 'replace'
3339
3341
 
3340
3342
    @display_command
3341
 
    def run(self, email=False, branch=False, name=None, directory=None):
 
3343
    def run(self, email=False, branch=False, name=None):
3342
3344
        if name is None:
3343
 
            if directory is None:
3344
 
                # use branch if we're inside one; otherwise global config
3345
 
                try:
3346
 
                    c = Branch.open_containing(u'.')[0].get_config()
3347
 
                except errors.NotBranchError:
3348
 
                    c = _mod_config.GlobalConfig()
3349
 
            else:
3350
 
                c = Branch.open(directory).get_config()
 
3345
            # use branch if we're inside one; otherwise global config
 
3346
            try:
 
3347
                c = Branch.open_containing('.')[0].get_config()
 
3348
            except errors.NotBranchError:
 
3349
                c = config.GlobalConfig()
3351
3350
            if email:
3352
3351
                self.outf.write(c.user_email() + '\n')
3353
3352
            else:
3356
3355
 
3357
3356
        # display a warning if an email address isn't included in the given name.
3358
3357
        try:
3359
 
            _mod_config.extract_email_address(name)
 
3358
            config.extract_email_address(name)
3360
3359
        except errors.NoEmailInUsername, e:
3361
3360
            warning('"%s" does not seem to contain an email address.  '
3362
3361
                    'This is allowed, but not recommended.', name)
3363
3362
 
3364
3363
        # use global config unless --branch given
3365
3364
        if branch:
3366
 
            if directory is None:
3367
 
                c = Branch.open_containing(u'.')[0].get_config()
3368
 
            else:
3369
 
                c = Branch.open(directory).get_config()
 
3365
            c = Branch.open_containing('.')[0].get_config()
3370
3366
        else:
3371
 
            c = _mod_config.GlobalConfig()
 
3367
            c = config.GlobalConfig()
3372
3368
        c.set_user_option('email', name)
3373
3369
 
3374
3370
 
3384
3380
 
3385
3381
    _see_also = ['info']
3386
3382
    takes_args = ['nickname?']
3387
 
    takes_options = ['directory']
3388
 
    def run(self, nickname=None, directory=u'.'):
3389
 
        branch = Branch.open_containing(directory)[0]
 
3383
    def run(self, nickname=None):
 
3384
        branch = Branch.open_containing(u'.')[0]
3390
3385
        if nickname is None:
3391
3386
            self.printme(branch)
3392
3387
        else:
3441
3436
                'bzr alias --remove expects an alias to remove.')
3442
3437
        # If alias is not found, print something like:
3443
3438
        # unalias: foo: not found
3444
 
        c = _mod_config.GlobalConfig()
 
3439
        c = config.GlobalConfig()
3445
3440
        c.unset_alias(alias_name)
3446
3441
 
3447
3442
    @display_command
3448
3443
    def print_aliases(self):
3449
3444
        """Print out the defined aliases in a similar format to bash."""
3450
 
        aliases = _mod_config.GlobalConfig().get_aliases()
 
3445
        aliases = config.GlobalConfig().get_aliases()
3451
3446
        for key, value in sorted(aliases.iteritems()):
3452
3447
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3453
3448
 
3463
3458
 
3464
3459
    def set_alias(self, alias_name, alias_command):
3465
3460
        """Save the alias in the global config."""
3466
 
        c = _mod_config.GlobalConfig()
 
3461
        c = config.GlobalConfig()
3467
3462
        c.set_alias(alias_name, alias_command)
3468
3463
 
3469
3464
 
3504
3499
    If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3505
3500
    into a pdb postmortem session.
3506
3501
 
3507
 
    The --coverage=DIRNAME global option produces a report with covered code
3508
 
    indicated.
3509
 
 
3510
3502
    :Examples:
3511
3503
        Run only tests relating to 'ignore'::
3512
3504
 
3545
3537
                                 'throughout the test suite.',
3546
3538
                            type=get_transport_type),
3547
3539
                     Option('benchmark',
3548
 
                            help='Run the benchmarks rather than selftests.',
3549
 
                            hidden=True),
 
3540
                            help='Run the benchmarks rather than selftests.'),
3550
3541
                     Option('lsprof-timed',
3551
3542
                            help='Generate lsprof output for benchmarked'
3552
3543
                                 ' sections of code.'),
3553
3544
                     Option('lsprof-tests',
3554
3545
                            help='Generate lsprof output for each test.'),
 
3546
                     Option('cache-dir', type=str,
 
3547
                            help='Cache intermediate benchmark output in this '
 
3548
                                 'directory.'),
3555
3549
                     Option('first',
3556
3550
                            help='Run all tests, but run specified tests first.',
3557
3551
                            short_name='f',
3591
3585
 
3592
3586
    def run(self, testspecs_list=None, verbose=False, one=False,
3593
3587
            transport=None, benchmark=None,
3594
 
            lsprof_timed=None,
 
3588
            lsprof_timed=None, cache_dir=None,
3595
3589
            first=False, list_only=False,
3596
3590
            randomize=None, exclude=None, strict=False,
3597
3591
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3598
3592
            parallel=None, lsprof_tests=False):
3599
 
        from bzrlib import tests
3600
 
 
 
3593
        from bzrlib.tests import selftest
 
3594
        import bzrlib.benchmarks as benchmarks
 
3595
        from bzrlib.benchmarks import tree_creator
 
3596
 
 
3597
        # Make deprecation warnings visible, unless -Werror is set
 
3598
        symbol_versioning.activate_deprecation_warnings(override=False)
 
3599
 
 
3600
        if cache_dir is not None:
 
3601
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3601
3602
        if testspecs_list is not None:
3602
3603
            pattern = '|'.join(testspecs_list)
3603
3604
        else:
3611
3612
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3612
3613
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3613
3614
            # stdout, which would corrupt the subunit stream. 
3614
 
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3615
 
            # following code can be deleted when it's sufficiently deployed
3616
 
            # -- vila/mgz 20100514
3617
 
            if (sys.platform == "win32"
3618
 
                and getattr(sys.stdout, 'fileno', None) is not None):
 
3615
            if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3619
3616
                import msvcrt
3620
3617
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3621
3618
        if parallel:
3622
3619
            self.additional_selftest_args.setdefault(
3623
3620
                'suite_decorators', []).append(parallel)
3624
3621
        if benchmark:
3625
 
            raise errors.BzrCommandError(
3626
 
                "--benchmark is no longer supported from bzr 2.2; "
3627
 
                "use bzr-usertest instead")
3628
 
        test_suite_factory = None
 
3622
            test_suite_factory = benchmarks.test_suite
 
3623
            # Unless user explicitly asks for quiet, be verbose in benchmarks
 
3624
            verbose = not is_quiet()
 
3625
            # TODO: should possibly lock the history file...
 
3626
            benchfile = open(".perf_history", "at", buffering=1)
 
3627
            self.add_cleanup(benchfile.close)
 
3628
        else:
 
3629
            test_suite_factory = None
 
3630
            benchfile = None
3629
3631
        selftest_kwargs = {"verbose": verbose,
3630
3632
                          "pattern": pattern,
3631
3633
                          "stop_on_failure": one,
3633
3635
                          "test_suite_factory": test_suite_factory,
3634
3636
                          "lsprof_timed": lsprof_timed,
3635
3637
                          "lsprof_tests": lsprof_tests,
 
3638
                          "bench_history": benchfile,
3636
3639
                          "matching_tests_first": first,
3637
3640
                          "list_only": list_only,
3638
3641
                          "random_seed": randomize,
3643
3646
                          "starting_with": starting_with
3644
3647
                          }
3645
3648
        selftest_kwargs.update(self.additional_selftest_args)
3646
 
 
3647
 
        # Make deprecation warnings visible, unless -Werror is set
3648
 
        cleanup = symbol_versioning.activate_deprecation_warnings(
3649
 
            override=False)
3650
 
        try:
3651
 
            result = tests.selftest(**selftest_kwargs)
3652
 
        finally:
3653
 
            cleanup()
 
3649
        result = selftest(**selftest_kwargs)
3654
3650
        return int(not result)
3655
3651
 
3656
3652
 
3694
3690
 
3695
3691
        branch1 = Branch.open_containing(branch)[0]
3696
3692
        branch2 = Branch.open_containing(other)[0]
3697
 
        self.add_cleanup(branch1.lock_read().unlock)
3698
 
        self.add_cleanup(branch2.lock_read().unlock)
 
3693
        branch1.lock_read()
 
3694
        self.add_cleanup(branch1.unlock)
 
3695
        branch2.lock_read()
 
3696
        self.add_cleanup(branch2.unlock)
3699
3697
        last1 = ensure_null(branch1.last_revision())
3700
3698
        last2 = ensure_null(branch2.last_revision())
3701
3699
 
3795
3793
                ' completely merged into the source, pull from the'
3796
3794
                ' source rather than merging.  When this happens,'
3797
3795
                ' you do not need to commit the result.'),
3798
 
        custom_help('directory',
 
3796
        Option('directory',
3799
3797
               help='Branch to merge into, '
3800
 
                    'rather than the one containing the working directory.'),
 
3798
                    'rather than the one containing the working directory.',
 
3799
               short_name='d',
 
3800
               type=unicode,
 
3801
               ),
3801
3802
        Option('preview', help='Instead of merging, show a diff of the'
3802
3803
               ' merge.'),
3803
3804
        Option('interactive', help='Select changes interactively.',
3836
3837
            unversioned_filter=tree.is_ignored, view_info=view_info)
3837
3838
        pb = ui.ui_factory.nested_progress_bar()
3838
3839
        self.add_cleanup(pb.finished)
3839
 
        self.add_cleanup(tree.lock_write().unlock)
 
3840
        tree.lock_write()
 
3841
        self.add_cleanup(tree.unlock)
3840
3842
        if location is not None:
3841
3843
            try:
3842
3844
                mergeable = bundle.read_mergeable_from_url(location,
3903
3905
    def _do_preview(self, merger):
3904
3906
        from bzrlib.diff import show_diff_trees
3905
3907
        result_tree = self._get_preview(merger)
3906
 
        path_encoding = osutils.get_diff_header_encoding()
3907
3908
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3908
 
                        old_label='', new_label='',
3909
 
                        path_encoding=path_encoding)
 
3909
                        old_label='', new_label='')
3910
3910
 
3911
3911
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3912
3912
        merger.change_reporter = change_reporter
4099
4099
        from bzrlib.conflicts import restore
4100
4100
        if merge_type is None:
4101
4101
            merge_type = _mod_merge.Merge3Merger
4102
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4103
 
        self.add_cleanup(tree.lock_write().unlock)
 
4102
        tree, file_list = tree_files(file_list)
 
4103
        tree.lock_write()
 
4104
        self.add_cleanup(tree.unlock)
4104
4105
        parents = tree.get_parent_ids()
4105
4106
        if len(parents) != 2:
4106
4107
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4215
4216
 
4216
4217
    def run(self, revision=None, no_backup=False, file_list=None,
4217
4218
            forget_merges=None):
4218
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4219
 
        self.add_cleanup(tree.lock_tree_write().unlock)
 
4219
        tree, file_list = tree_files(file_list)
 
4220
        tree.lock_tree_write()
 
4221
        self.add_cleanup(tree.unlock)
4220
4222
        if forget_merges:
4221
4223
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4222
4224
        else:
4311
4313
    _see_also = ['merge', 'pull']
4312
4314
    takes_args = ['other_branch?']
4313
4315
    takes_options = [
4314
 
        'directory',
4315
4316
        Option('reverse', 'Reverse the order of revisions.'),
4316
4317
        Option('mine-only',
4317
4318
               'Display changes in the local branch only.'),
4339
4340
            theirs_only=False,
4340
4341
            log_format=None, long=False, short=False, line=False,
4341
4342
            show_ids=False, verbose=False, this=False, other=False,
4342
 
            include_merges=False, revision=None, my_revision=None,
4343
 
            directory=u'.'):
 
4343
            include_merges=False, revision=None, my_revision=None):
4344
4344
        from bzrlib.missing import find_unmerged, iter_log_revisions
4345
4345
        def message(s):
4346
4346
            if not is_quiet():
4359
4359
        elif theirs_only:
4360
4360
            restrict = 'remote'
4361
4361
 
4362
 
        local_branch = Branch.open_containing(directory)[0]
4363
 
        self.add_cleanup(local_branch.lock_read().unlock)
 
4362
        local_branch = Branch.open_containing(u".")[0]
 
4363
        local_branch.lock_read()
 
4364
        self.add_cleanup(local_branch.unlock)
4364
4365
 
4365
4366
        parent = local_branch.get_parent()
4366
4367
        if other_branch is None:
4377
4378
        if remote_branch.base == local_branch.base:
4378
4379
            remote_branch = local_branch
4379
4380
        else:
4380
 
            self.add_cleanup(remote_branch.lock_read().unlock)
 
4381
            remote_branch.lock_read()
 
4382
            self.add_cleanup(remote_branch.unlock)
4381
4383
 
4382
4384
        local_revid_range = _revision_range_to_revid_range(
4383
4385
            _get_revision_range(my_revision, local_branch,
4438
4440
            message("Branches are up to date.\n")
4439
4441
        self.cleanup_now()
4440
4442
        if not status_code and parent is None and other_branch is not None:
4441
 
            self.add_cleanup(local_branch.lock_write().unlock)
 
4443
            local_branch.lock_write()
 
4444
            self.add_cleanup(local_branch.unlock)
4442
4445
            # handle race conditions - a parent might be set while we run.
4443
4446
            if local_branch.get_parent() is None:
4444
4447
                local_branch.set_parent(remote_branch.base)
4544
4547
            b = Branch.open_containing(branch)[0]
4545
4548
        else:
4546
4549
            b = Branch.open(branch)
4547
 
        self.add_cleanup(b.lock_read().unlock)
 
4550
        b.lock_read()
 
4551
        self.add_cleanup(b.unlock)
4548
4552
        if revision is None:
4549
4553
            rev_id = b.last_revision()
4550
4554
        else:
4574
4578
                     Option('long', help='Show commit date in annotations.'),
4575
4579
                     'revision',
4576
4580
                     'show-ids',
4577
 
                     'directory',
4578
4581
                     ]
4579
4582
    encoding_type = 'exact'
4580
4583
 
4581
4584
    @display_command
4582
4585
    def run(self, filename, all=False, long=False, revision=None,
4583
 
            show_ids=False, directory=None):
 
4586
            show_ids=False):
4584
4587
        from bzrlib.annotate import annotate_file, annotate_file_tree
4585
4588
        wt, branch, relpath = \
4586
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
 
4589
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4587
4590
        if wt is not None:
4588
 
            self.add_cleanup(wt.lock_read().unlock)
 
4591
            wt.lock_read()
 
4592
            self.add_cleanup(wt.unlock)
4589
4593
        else:
4590
 
            self.add_cleanup(branch.lock_read().unlock)
 
4594
            branch.lock_read()
 
4595
            self.add_cleanup(branch.unlock)
4591
4596
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4592
 
        self.add_cleanup(tree.lock_read().unlock)
 
4597
        tree.lock_read()
 
4598
        self.add_cleanup(tree.unlock)
4593
4599
        if wt is not None:
4594
4600
            file_id = wt.path2id(relpath)
4595
4601
        else:
4613
4619
 
4614
4620
    hidden = True # is this right ?
4615
4621
    takes_args = ['revision_id*']
4616
 
    takes_options = ['directory', 'revision']
 
4622
    takes_options = ['revision']
4617
4623
 
4618
 
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
 
4624
    def run(self, revision_id_list=None, revision=None):
4619
4625
        if revision_id_list is not None and revision is not None:
4620
4626
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4621
4627
        if revision_id_list is None and revision is None:
4622
4628
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4623
 
        b = WorkingTree.open_containing(directory)[0].branch
4624
 
        self.add_cleanup(b.lock_write().unlock)
 
4629
        b = WorkingTree.open_containing(u'.')[0].branch
 
4630
        b.lock_write()
 
4631
        self.add_cleanup(b.unlock)
4625
4632
        return self._run(b, revision_id_list, revision)
4626
4633
 
4627
4634
    def _run(self, b, revision_id_list, revision):
4686
4693
 
4687
4694
    _see_also = ['checkouts', 'unbind']
4688
4695
    takes_args = ['location?']
4689
 
    takes_options = ['directory']
 
4696
    takes_options = []
4690
4697
 
4691
 
    def run(self, location=None, directory=u'.'):
4692
 
        b, relpath = Branch.open_containing(directory)
 
4698
    def run(self, location=None):
 
4699
        b, relpath = Branch.open_containing(u'.')
4693
4700
        if location is None:
4694
4701
            try:
4695
4702
                location = b.get_old_bound_location()
4722
4729
 
4723
4730
    _see_also = ['checkouts', 'bind']
4724
4731
    takes_args = []
4725
 
    takes_options = ['directory']
 
4732
    takes_options = []
4726
4733
 
4727
 
    def run(self, directory=u'.'):
4728
 
        b, relpath = Branch.open_containing(directory)
 
4734
    def run(self):
 
4735
        b, relpath = Branch.open_containing(u'.')
4729
4736
        if not b.unbind():
4730
4737
            raise errors.BzrCommandError('Local branch is not bound')
4731
4738
 
4777
4784
            b = control.open_branch()
4778
4785
 
4779
4786
        if tree is not None:
4780
 
            self.add_cleanup(tree.lock_write().unlock)
 
4787
            tree.lock_write()
 
4788
            self.add_cleanup(tree.unlock)
4781
4789
        else:
4782
 
            self.add_cleanup(b.lock_write().unlock)
 
4790
            b.lock_write()
 
4791
            self.add_cleanup(b.unlock)
4783
4792
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4784
4793
 
4785
4794
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4824
4833
            self.outf.write('The above revision(s) will be removed.\n')
4825
4834
 
4826
4835
        if not force:
4827
 
            if not ui.ui_factory.confirm_action(
4828
 
                    'Uncommit these revisions',
4829
 
                    'bzrlib.builtins.uncommit',
4830
 
                    {}):
4831
 
                self.outf.write('Canceled\n')
 
4836
            if not ui.ui_factory.get_boolean('Are you sure'):
 
4837
                self.outf.write('Canceled')
4832
4838
                return 0
4833
4839
 
4834
4840
        mutter('Uncommitting from {%s} to {%s}',
4840
4846
 
4841
4847
 
4842
4848
class cmd_break_lock(Command):
4843
 
    __doc__ = """Break a dead lock.
4844
 
 
4845
 
    This command breaks a lock on a repository, branch, working directory or
4846
 
    config file.
 
4849
    __doc__ = """Break a dead lock on a repository, branch or working directory.
4847
4850
 
4848
4851
    CAUTION: Locks should only be broken when you are sure that the process
4849
4852
    holding the lock has been stopped.
4854
4857
    :Examples:
4855
4858
        bzr break-lock
4856
4859
        bzr break-lock bzr+ssh://example.com/bzr/foo
4857
 
        bzr break-lock --conf ~/.bazaar
4858
4860
    """
4859
 
 
4860
4861
    takes_args = ['location?']
4861
 
    takes_options = [
4862
 
        Option('config',
4863
 
               help='LOCATION is the directory where the config lock is.'),
4864
 
        Option('force',
4865
 
            help='Do not ask for confirmation before breaking the lock.'),
4866
 
        ]
4867
4862
 
4868
 
    def run(self, location=None, config=False, force=False):
 
4863
    def run(self, location=None, show=False):
4869
4864
        if location is None:
4870
4865
            location = u'.'
4871
 
        if force:
4872
 
            ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
4873
 
                None,
4874
 
                {'bzrlib.lockdir.break': True})
4875
 
        if config:
4876
 
            conf = _mod_config.LockableConfig(file_name=location)
4877
 
            conf.break_lock()
4878
 
        else:
4879
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
4880
 
            try:
4881
 
                control.break_lock()
4882
 
            except NotImplementedError:
4883
 
                pass
 
4866
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
4867
        try:
 
4868
            control.break_lock()
 
4869
        except NotImplementedError:
 
4870
            pass
4884
4871
 
4885
4872
 
4886
4873
class cmd_wait_until_signalled(Command):
4915
4902
                    'result in a dynamically allocated port.  The default port '
4916
4903
                    'depends on the protocol.',
4917
4904
               type=str),
4918
 
        custom_help('directory',
4919
 
               help='Serve contents of this directory.'),
 
4905
        Option('directory',
 
4906
               help='Serve contents of this directory.',
 
4907
               type=unicode),
4920
4908
        Option('allow-writes',
4921
4909
               help='By default the server is a readonly server.  Supplying '
4922
4910
                    '--allow-writes enables write access to the contents of '
4949
4937
 
4950
4938
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
4951
4939
            protocol=None):
4952
 
        from bzrlib import transport
 
4940
        from bzrlib.transport import get_transport, transport_server_registry
4953
4941
        if directory is None:
4954
4942
            directory = os.getcwd()
4955
4943
        if protocol is None:
4956
 
            protocol = transport.transport_server_registry.get()
 
4944
            protocol = transport_server_registry.get()
4957
4945
        host, port = self.get_host_and_port(port)
4958
4946
        url = urlutils.local_path_to_url(directory)
4959
4947
        if not allow_writes:
4960
4948
            url = 'readonly+' + url
4961
 
        t = transport.get_transport(url)
4962
 
        protocol(t, host, port, inet)
 
4949
        transport = get_transport(url)
 
4950
        protocol(transport, host, port, inet)
4963
4951
 
4964
4952
 
4965
4953
class cmd_join(Command):
4971
4959
    not part of it.  (Such trees can be produced by "bzr split", but also by
4972
4960
    running "bzr branch" with the target inside a tree.)
4973
4961
 
4974
 
    The result is a combined tree, with the subtree no longer an independent
 
4962
    The result is a combined tree, with the subtree no longer an independant
4975
4963
    part.  This is marked as a merge of the subtree into the containing tree,
4976
4964
    and all history is preserved.
4977
4965
    """
5058
5046
    _see_also = ['send']
5059
5047
 
5060
5048
    takes_options = [
5061
 
        'directory',
5062
5049
        RegistryOption.from_kwargs('patch-type',
5063
5050
            'The type of patch to include in the directive.',
5064
5051
            title='Patch type',
5077
5064
    encoding_type = 'exact'
5078
5065
 
5079
5066
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5080
 
            sign=False, revision=None, mail_to=None, message=None,
5081
 
            directory=u'.'):
 
5067
            sign=False, revision=None, mail_to=None, message=None):
5082
5068
        from bzrlib.revision import ensure_null, NULL_REVISION
5083
5069
        include_patch, include_bundle = {
5084
5070
            'plain': (False, False),
5085
5071
            'diff': (True, False),
5086
5072
            'bundle': (True, True),
5087
5073
            }[patch_type]
5088
 
        branch = Branch.open(directory)
 
5074
        branch = Branch.open('.')
5089
5075
        stored_submit_branch = branch.get_submit_branch()
5090
5076
        if submit_branch is None:
5091
5077
            submit_branch = stored_submit_branch
5176
5162
    given, in which case it is sent to a file.
5177
5163
 
5178
5164
    Mail is sent using your preferred mail program.  This should be transparent
5179
 
    on Windows (it uses MAPI).  On Unix, it requires the xdg-email utility.
 
5165
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
5180
5166
    If the preferred client can't be found (or used), your editor will be used.
5181
5167
 
5182
5168
    To use a specific mail program, set the mail_client configuration option.
5353
5339
        Option('delete',
5354
5340
            help='Delete this tag rather than placing it.',
5355
5341
            ),
5356
 
        custom_help('directory',
5357
 
            help='Branch in which to place the tag.'),
 
5342
        Option('directory',
 
5343
            help='Branch in which to place the tag.',
 
5344
            short_name='d',
 
5345
            type=unicode,
 
5346
            ),
5358
5347
        Option('force',
5359
5348
            help='Replace existing tags.',
5360
5349
            ),
5368
5357
            revision=None,
5369
5358
            ):
5370
5359
        branch, relpath = Branch.open_containing(directory)
5371
 
        self.add_cleanup(branch.lock_write().unlock)
 
5360
        branch.lock_write()
 
5361
        self.add_cleanup(branch.unlock)
5372
5362
        if delete:
5373
5363
            if tag_name is None:
5374
5364
                raise errors.BzrCommandError("No tag specified to delete.")
5402
5392
 
5403
5393
    _see_also = ['tag']
5404
5394
    takes_options = [
5405
 
        custom_help('directory',
5406
 
            help='Branch whose tags should be displayed.'),
 
5395
        Option('directory',
 
5396
            help='Branch whose tags should be displayed.',
 
5397
            short_name='d',
 
5398
            type=unicode,
 
5399
            ),
5407
5400
        RegistryOption.from_kwargs('sort',
5408
5401
            'Sort tags by different criteria.', title='Sorting',
5409
 
            natural='Sort numeric substrings as numbers:'
5410
 
                    ' suitable for version numbers. (default)',
5411
 
            alpha='Sort tags lexicographically.',
 
5402
            alpha='Sort tags lexicographically (default).',
5412
5403
            time='Sort tags chronologically.',
5413
5404
            ),
5414
5405
        'show-ids',
5418
5409
    @display_command
5419
5410
    def run(self,
5420
5411
            directory='.',
5421
 
            sort='natural',
 
5412
            sort='alpha',
5422
5413
            show_ids=False,
5423
5414
            revision=None,
5424
5415
            ):
5428
5419
        if not tags:
5429
5420
            return
5430
5421
 
5431
 
        self.add_cleanup(branch.lock_read().unlock)
 
5422
        branch.lock_read()
 
5423
        self.add_cleanup(branch.unlock)
5432
5424
        if revision:
5433
5425
            graph = branch.repository.get_graph()
5434
5426
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5436
5428
            # only show revisions between revid1 and revid2 (inclusive)
5437
5429
            tags = [(tag, revid) for tag, revid in tags if
5438
5430
                graph.is_between(revid, revid1, revid2)]
5439
 
        if sort == 'natural':
5440
 
            def natural_sort_key(tag):
5441
 
                return [f(s) for f,s in 
5442
 
                        zip(itertools.cycle((unicode.lower,int)),
5443
 
                                            re.split('([0-9]+)', tag[0]))]
5444
 
            tags.sort(key=natural_sort_key)
5445
 
        elif sort == 'alpha':
 
5431
        if sort == 'alpha':
5446
5432
            tags.sort()
5447
5433
        elif sort == 'time':
5448
5434
            timestamps = {}
5587
5573
    """
5588
5574
 
5589
5575
    takes_args = ['to_location?']
5590
 
    takes_options = ['directory',
5591
 
                     Option('force',
 
5576
    takes_options = [Option('force',
5592
5577
                        help='Switch even if local commits will be lost.'),
5593
5578
                     'revision',
5594
5579
                     Option('create-branch', short_name='b',
5597
5582
                    ]
5598
5583
 
5599
5584
    def run(self, to_location=None, force=False, create_branch=False,
5600
 
            revision=None, directory=u'.'):
 
5585
            revision=None):
5601
5586
        from bzrlib import switch
5602
 
        tree_location = directory
 
5587
        tree_location = '.'
5603
5588
        revision = _get_one_revision('switch', revision)
5604
5589
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5605
5590
        if to_location is None:
5606
5591
            if revision is None:
5607
5592
                raise errors.BzrCommandError('You must supply either a'
5608
5593
                                             ' revision or a location')
5609
 
            to_location = tree_location
 
5594
            to_location = '.'
5610
5595
        try:
5611
5596
            branch = control_dir.open_branch()
5612
5597
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5747
5732
            name=None,
5748
5733
            switch=None,
5749
5734
            ):
5750
 
        tree, file_list = WorkingTree.open_containing_paths(file_list,
5751
 
            apply_view=False)
 
5735
        tree, file_list = tree_files(file_list, apply_view=False)
5752
5736
        current_view, view_dict = tree.views.get_view_info()
5753
5737
        if name is None:
5754
5738
            name = current_view
5888
5872
    takes_args = ['file*']
5889
5873
 
5890
5874
    takes_options = [
5891
 
        'directory',
5892
5875
        'revision',
5893
5876
        Option('all', help='Shelve all changes.'),
5894
5877
        'message',
5903
5886
    _see_also = ['unshelve']
5904
5887
 
5905
5888
    def run(self, revision=None, all=False, file_list=None, message=None,
5906
 
            writer=None, list=False, destroy=False, directory=u'.'):
 
5889
            writer=None, list=False, destroy=False):
5907
5890
        if list:
5908
5891
            return self.run_for_list()
5909
5892
        from bzrlib.shelf_ui import Shelver
5911
5894
            writer = bzrlib.option.diff_writer_registry.get()
5912
5895
        try:
5913
5896
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5914
 
                file_list, message, destroy=destroy, directory=directory)
 
5897
                file_list, message, destroy=destroy)
5915
5898
            try:
5916
5899
                shelver.run()
5917
5900
            finally:
5921
5904
 
5922
5905
    def run_for_list(self):
5923
5906
        tree = WorkingTree.open_containing('.')[0]
5924
 
        self.add_cleanup(tree.lock_read().unlock)
 
5907
        tree.lock_read()
 
5908
        self.add_cleanup(tree.unlock)
5925
5909
        manager = tree.get_shelf_manager()
5926
5910
        shelves = manager.active_shelves()
5927
5911
        if len(shelves) == 0:
5945
5929
 
5946
5930
    takes_args = ['shelf_id?']
5947
5931
    takes_options = [
5948
 
        'directory',
5949
5932
        RegistryOption.from_kwargs(
5950
5933
            'action', help="The action to perform.",
5951
5934
            enum_switch=False, value_switches=True,
5959
5942
    ]
5960
5943
    _see_also = ['shelve']
5961
5944
 
5962
 
    def run(self, shelf_id=None, action='apply', directory=u'.'):
 
5945
    def run(self, shelf_id=None, action='apply'):
5963
5946
        from bzrlib.shelf_ui import Unshelver
5964
 
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
 
5947
        unshelver = Unshelver.from_args(shelf_id, action)
5965
5948
        try:
5966
5949
            unshelver.run()
5967
5950
        finally:
5983
5966
 
5984
5967
    To check what clean-tree will do, use --dry-run.
5985
5968
    """
5986
 
    takes_options = ['directory',
5987
 
                     Option('ignored', help='Delete all ignored files.'),
 
5969
    takes_options = [Option('ignored', help='Delete all ignored files.'),
5988
5970
                     Option('detritus', help='Delete conflict files, merge'
5989
5971
                            ' backups, and failed selftest dirs.'),
5990
5972
                     Option('unknown',
5993
5975
                            ' deleting them.'),
5994
5976
                     Option('force', help='Do not prompt before deleting.')]
5995
5977
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5996
 
            force=False, directory=u'.'):
 
5978
            force=False):
5997
5979
        from bzrlib.clean_tree import clean_tree
5998
5980
        if not (unknown or ignored or detritus):
5999
5981
            unknown = True
6000
5982
        if dry_run:
6001
5983
            force = True
6002
 
        clean_tree(directory, unknown=unknown, ignored=ignored,
6003
 
                   detritus=detritus, dry_run=dry_run, no_prompt=force)
 
5984
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
 
5985
                   dry_run=dry_run, no_prompt=force)
6004
5986
 
6005
5987
 
6006
5988
class cmd_reference(Command):