/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: John Arbash Meinel
  • Date: 2010-08-13 19:08:57 UTC
  • mto: (5050.17.7 2.2)
  • mto: This revision was merged to the branch mainline in revision 5379.
  • Revision ID: john@arbash-meinel.com-20100813190857-mvzwnimrxvm0zimp
Lots of documentation updates.

We had a lot of http links pointing to the old domain. They should
all now be properly updated to the new domain. (only bazaar-vcs.org
entry left is for pqm, which seems to still reside at the old url.)

Also removed one 'TODO' doc entry about switching to binary xdelta, since
we basically did just that with groupcompress.

Show diffs side-by-side

added added

removed removed

Lines of Context:
180
180
                view_str = views.view_display_str(view_files)
181
181
                note("Ignoring files outside view. View is %s" % view_str)
182
182
        return tree, file_list
183
 
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
 
183
    tree = WorkingTree.open_containing(file_list[0])[0]
184
184
    return tree, safe_relpath_files(tree, file_list, canonicalize,
185
185
        apply_view=apply_view)
186
186
 
232
232
    return view_info
233
233
 
234
234
 
 
235
def _open_directory_or_containing_tree_or_branch(filename, directory):
 
236
    """Open the tree or branch containing the specified file, unless
 
237
    the --directory option is used to specify a different branch."""
 
238
    if directory is not None:
 
239
        return (None, Branch.open(directory), filename)
 
240
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
241
 
 
242
 
235
243
# TODO: Make sure no commands unconditionally use the working directory as a
236
244
# branch.  If a filename argument is used, the first of them should be used to
237
245
# specify the branch.  (Perhaps this can be factored out into some kind of
340
348
 
341
349
    hidden = True
342
350
    takes_args = ['revision_id?']
343
 
    takes_options = ['revision']
 
351
    takes_options = ['directory', 'revision']
344
352
    # cat-revision is more for frontends so should be exact
345
353
    encoding = 'strict'
346
354
 
353
361
        self.outf.write(revtext.decode('utf-8'))
354
362
 
355
363
    @display_command
356
 
    def run(self, revision_id=None, revision=None):
 
364
    def run(self, revision_id=None, revision=None, directory=u'.'):
357
365
        if revision_id is not None and revision is not None:
358
366
            raise errors.BzrCommandError('You can only supply one of'
359
367
                                         ' revision_id or --revision')
360
368
        if revision_id is None and revision is None:
361
369
            raise errors.BzrCommandError('You must supply either'
362
370
                                         ' --revision or a revision_id')
363
 
        b = WorkingTree.open_containing(u'.')[0].branch
 
371
        b = WorkingTree.open_containing(directory)[0].branch
364
372
 
365
373
        revisions = b.repository.revisions
366
374
        if revisions is None:
483
491
    takes_options = [
484
492
        Option('force',
485
493
               help='Remove the working tree even if it has '
486
 
                    'uncommitted changes.'),
 
494
                    'uncommitted or shelved changes.'),
487
495
        ]
488
496
 
489
497
    def run(self, location_list, force=False):
503
511
            if not force:
504
512
                if (working.has_changes()):
505
513
                    raise errors.UncommittedChanges(working)
 
514
                if working.get_shelf_manager().last_shelf() is not None:
 
515
                    raise errors.ShelvedChanges(working)
506
516
 
507
517
            if working.user_url != working.branch.user_url:
508
518
                raise errors.BzrCommandError("You cannot remove the working tree"
528
538
        if tree:
529
539
            try:
530
540
                wt = WorkingTree.open_containing(location)[0]
531
 
                wt.lock_read()
 
541
                self.add_cleanup(wt.lock_read().unlock)
532
542
            except (errors.NoWorkingTree, errors.NotLocalUrl):
533
543
                raise errors.NoWorkingTree(location)
534
 
            self.add_cleanup(wt.unlock)
535
544
            revid = wt.last_revision()
536
545
            try:
537
546
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
540
549
            revno = ".".join(str(n) for n in revno_t)
541
550
        else:
542
551
            b = Branch.open_containing(location)[0]
543
 
            b.lock_read()
544
 
            self.add_cleanup(b.unlock)
 
552
            self.add_cleanup(b.lock_read().unlock)
545
553
            revno = b.revno()
546
554
        self.cleanup_now()
547
555
        self.outf.write(str(revno) + '\n')
554
562
    takes_args = ['revision_info*']
555
563
    takes_options = [
556
564
        'revision',
557
 
        Option('directory',
 
565
        custom_help('directory',
558
566
            help='Branch to examine, '
559
 
                 'rather than the one containing the working directory.',
560
 
            short_name='d',
561
 
            type=unicode,
562
 
            ),
 
567
                 'rather than the one containing the working directory.'),
563
568
        Option('tree', help='Show revno of working tree'),
564
569
        ]
565
570
 
570
575
        try:
571
576
            wt = WorkingTree.open_containing(directory)[0]
572
577
            b = wt.branch
573
 
            wt.lock_read()
574
 
            self.add_cleanup(wt.unlock)
 
578
            self.add_cleanup(wt.lock_read().unlock)
575
579
        except (errors.NoWorkingTree, errors.NotLocalUrl):
576
580
            wt = None
577
581
            b = Branch.open_containing(directory)[0]
578
 
            b.lock_read()
579
 
            self.add_cleanup(b.unlock)
 
582
            self.add_cleanup(b.lock_read().unlock)
580
583
        revision_ids = []
581
584
        if revision is not None:
582
585
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
681
684
                should_print=(not is_quiet()))
682
685
 
683
686
        if base_tree:
684
 
            base_tree.lock_read()
685
 
            self.add_cleanup(base_tree.unlock)
 
687
            self.add_cleanup(base_tree.lock_read().unlock)
686
688
        tree, file_list = tree_files_for_add(file_list)
687
689
        added, ignored = tree.smart_add(file_list, not
688
690
            no_recurse, action=action, save=not dry_run)
760
762
 
761
763
        revision = _get_one_revision('inventory', revision)
762
764
        work_tree, file_list = tree_files(file_list)
763
 
        work_tree.lock_read()
764
 
        self.add_cleanup(work_tree.unlock)
 
765
        self.add_cleanup(work_tree.lock_read().unlock)
765
766
        if revision is not None:
766
767
            tree = revision.as_tree(work_tree.branch)
767
768
 
768
769
            extra_trees = [work_tree]
769
 
            tree.lock_read()
770
 
            self.add_cleanup(tree.unlock)
 
770
            self.add_cleanup(tree.lock_read().unlock)
771
771
        else:
772
772
            tree = work_tree
773
773
            extra_trees = []
833
833
        if len(names_list) < 2:
834
834
            raise errors.BzrCommandError("missing file argument")
835
835
        tree, rel_names = tree_files(names_list, canonicalize=False)
836
 
        tree.lock_tree_write()
837
 
        self.add_cleanup(tree.unlock)
 
836
        self.add_cleanup(tree.lock_tree_write().unlock)
838
837
        self._run(tree, names_list, rel_names, after)
839
838
 
840
839
    def run_auto(self, names_list, after, dry_run):
845
844
            raise errors.BzrCommandError('--after cannot be specified with'
846
845
                                         ' --auto.')
847
846
        work_tree, file_list = tree_files(names_list, default_branch='.')
848
 
        work_tree.lock_tree_write()
849
 
        self.add_cleanup(work_tree.unlock)
 
847
        self.add_cleanup(work_tree.lock_tree_write().unlock)
850
848
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
851
849
 
852
850
    def _run(self, tree, names_list, rel_names, after):
960
958
    takes_options = ['remember', 'overwrite', 'revision',
961
959
        custom_help('verbose',
962
960
            help='Show logs of pulled revisions.'),
963
 
        Option('directory',
 
961
        custom_help('directory',
964
962
            help='Branch to pull into, '
965
 
                 'rather than the one containing the working directory.',
966
 
            short_name='d',
967
 
            type=unicode,
968
 
            ),
 
963
                 'rather than the one containing the working directory.'),
969
964
        Option('local',
970
965
            help="Perform a local pull in a bound "
971
966
                 "branch.  Local pulls are not applied to "
986
981
        try:
987
982
            tree_to = WorkingTree.open_containing(directory)[0]
988
983
            branch_to = tree_to.branch
989
 
            tree_to.lock_write()
990
 
            self.add_cleanup(tree_to.unlock)
 
984
            self.add_cleanup(tree_to.lock_write().unlock)
991
985
        except errors.NoWorkingTree:
992
986
            tree_to = None
993
987
            branch_to = Branch.open_containing(directory)[0]
994
 
            branch_to.lock_write()
995
 
            self.add_cleanup(branch_to.unlock)
 
988
            self.add_cleanup(branch_to.lock_write().unlock)
996
989
 
997
990
        if local and not branch_to.get_bound_location():
998
991
            raise errors.LocalRequiresBoundBranch()
1029
1022
        else:
1030
1023
            branch_from = Branch.open(location,
1031
1024
                possible_transports=possible_transports)
1032
 
            branch_from.lock_read()
1033
 
            self.add_cleanup(branch_from.unlock)
 
1025
            self.add_cleanup(branch_from.lock_read().unlock)
1034
1026
 
1035
1027
            if branch_to.get_parent() is None or remember:
1036
1028
                branch_to.set_parent(branch_from.base)
1088
1080
        Option('create-prefix',
1089
1081
               help='Create the path leading up to the branch '
1090
1082
                    'if it does not already exist.'),
1091
 
        Option('directory',
 
1083
        custom_help('directory',
1092
1084
            help='Branch to push from, '
1093
 
                 'rather than the one containing the working directory.',
1094
 
            short_name='d',
1095
 
            type=unicode,
1096
 
            ),
 
1085
                 'rather than the one containing the working directory.'),
1097
1086
        Option('use-existing-dir',
1098
1087
               help='By default push will fail if the target'
1099
1088
                    ' directory exists, but does not already'
1219
1208
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1220
1209
            from_location)
1221
1210
        revision = _get_one_revision('branch', revision)
1222
 
        br_from.lock_read()
1223
 
        self.add_cleanup(br_from.unlock)
 
1211
        self.add_cleanup(br_from.lock_read().unlock)
1224
1212
        if revision is not None:
1225
1213
            revision_id = revision.as_revision_id(br_from)
1226
1214
        else:
1366
1354
    @display_command
1367
1355
    def run(self, dir=u'.'):
1368
1356
        tree = WorkingTree.open_containing(dir)[0]
1369
 
        tree.lock_read()
1370
 
        self.add_cleanup(tree.unlock)
 
1357
        self.add_cleanup(tree.lock_read().unlock)
1371
1358
        new_inv = tree.inventory
1372
1359
        old_tree = tree.basis_tree()
1373
 
        old_tree.lock_read()
1374
 
        self.add_cleanup(old_tree.unlock)
 
1360
        self.add_cleanup(old_tree.lock_read().unlock)
1375
1361
        old_inv = old_tree.inventory
1376
1362
        renames = []
1377
1363
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1415
1401
        master = branch.get_master_branch(
1416
1402
            possible_transports=possible_transports)
1417
1403
        if master is not None:
1418
 
            tree.lock_write()
1419
1404
            branch_location = master.base
 
1405
            tree.lock_write()
1420
1406
        else:
 
1407
            branch_location = tree.branch.base
1421
1408
            tree.lock_tree_write()
1422
 
            branch_location = tree.branch.base
1423
1409
        self.add_cleanup(tree.unlock)
1424
1410
        # get rid of the final '/' and be ready for display
1425
1411
        branch_location = urlutils.unescape_for_display(
1545
1531
        if file_list is not None:
1546
1532
            file_list = [f for f in file_list]
1547
1533
 
1548
 
        tree.lock_write()
1549
 
        self.add_cleanup(tree.unlock)
 
1534
        self.add_cleanup(tree.lock_write().unlock)
1550
1535
        # Heuristics should probably all move into tree.remove_smart or
1551
1536
        # some such?
1552
1537
        if new:
1985
1970
         old_branch, new_branch,
1986
1971
         specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1987
1972
            file_list, revision, old, new, self.add_cleanup, apply_view=True)
 
1973
        # GNU diff on Windows uses ANSI encoding for filenames
 
1974
        path_encoding = osutils.get_diff_header_encoding()
1988
1975
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1989
1976
                               specific_files=specific_files,
1990
1977
                               external_diff_options=diff_options,
1991
1978
                               old_label=old_label, new_label=new_label,
1992
 
                               extra_trees=extra_trees, using=using,
 
1979
                               extra_trees=extra_trees,
 
1980
                               path_encoding=path_encoding,
 
1981
                               using=using,
1993
1982
                               format_cls=format)
1994
1983
 
1995
1984
 
2003
1992
    # level of effort but possibly much less IO.  (Or possibly not,
2004
1993
    # if the directories are very large...)
2005
1994
    _see_also = ['status', 'ls']
2006
 
    takes_options = ['show-ids']
 
1995
    takes_options = ['directory', 'show-ids']
2007
1996
 
2008
1997
    @display_command
2009
 
    def run(self, show_ids=False):
2010
 
        tree = WorkingTree.open_containing(u'.')[0]
2011
 
        tree.lock_read()
2012
 
        self.add_cleanup(tree.unlock)
 
1998
    def run(self, show_ids=False, directory=u'.'):
 
1999
        tree = WorkingTree.open_containing(directory)[0]
 
2000
        self.add_cleanup(tree.lock_read().unlock)
2013
2001
        old = tree.basis_tree()
2014
 
        old.lock_read()
2015
 
        self.add_cleanup(old.unlock)
 
2002
        self.add_cleanup(old.lock_read().unlock)
2016
2003
        for path, ie in old.inventory.iter_entries():
2017
2004
            if not tree.has_id(ie.file_id):
2018
2005
                self.outf.write(path)
2028
2015
 
2029
2016
    hidden = True
2030
2017
    _see_also = ['status', 'ls']
2031
 
    takes_options = [
2032
 
            Option('null',
2033
 
                   help='Write an ascii NUL (\\0) separator '
2034
 
                   'between files rather than a newline.')
2035
 
            ]
 
2018
    takes_options = ['directory', 'null']
2036
2019
 
2037
2020
    @display_command
2038
 
    def run(self, null=False):
2039
 
        tree = WorkingTree.open_containing(u'.')[0]
 
2021
    def run(self, null=False, directory=u'.'):
 
2022
        tree = WorkingTree.open_containing(directory)[0]
2040
2023
        td = tree.changes_from(tree.basis_tree())
2041
2024
        for path, id, kind, text_modified, meta_modified in td.modified:
2042
2025
            if null:
2051
2034
 
2052
2035
    hidden = True
2053
2036
    _see_also = ['status', 'ls']
2054
 
    takes_options = [
2055
 
            Option('null',
2056
 
                   help='Write an ascii NUL (\\0) separator '
2057
 
                   'between files rather than a newline.')
2058
 
            ]
 
2037
    takes_options = ['directory', 'null']
2059
2038
 
2060
2039
    @display_command
2061
 
    def run(self, null=False):
2062
 
        wt = WorkingTree.open_containing(u'.')[0]
2063
 
        wt.lock_read()
2064
 
        self.add_cleanup(wt.unlock)
 
2040
    def run(self, null=False, directory=u'.'):
 
2041
        wt = WorkingTree.open_containing(directory)[0]
 
2042
        self.add_cleanup(wt.lock_read().unlock)
2065
2043
        basis = wt.basis_tree()
2066
 
        basis.lock_read()
2067
 
        self.add_cleanup(basis.unlock)
 
2044
        self.add_cleanup(basis.lock_read().unlock)
2068
2045
        basis_inv = basis.inventory
2069
2046
        inv = wt.inventory
2070
2047
        for file_id in inv:
2073
2050
            if inv.is_root(file_id) and len(basis_inv) == 0:
2074
2051
                continue
2075
2052
            path = inv.id2path(file_id)
2076
 
            if not os.access(osutils.abspath(path), os.F_OK):
 
2053
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2077
2054
                continue
2078
2055
            if null:
2079
2056
                self.outf.write(path + '\0')
2279
2256
                   help='Show just the specified revision.'
2280
2257
                   ' See also "help revisionspec".'),
2281
2258
            'log-format',
 
2259
            RegistryOption('authors',
 
2260
                'What names to list as authors - first, all or committer.',
 
2261
                title='Authors',
 
2262
                lazy_registry=('bzrlib.log', 'author_list_registry'),
 
2263
            ),
2282
2264
            Option('levels',
2283
2265
                   short_name='n',
2284
2266
                   help='Number of levels to display - 0 for all, 1 for flat.',
2319
2301
            limit=None,
2320
2302
            show_diff=False,
2321
2303
            include_merges=False,
 
2304
            authors=None,
2322
2305
            exclude_common_ancestry=False,
2323
2306
            ):
2324
2307
        from bzrlib.log import (
2352
2335
        if file_list:
2353
2336
            # find the file ids to log and check for directory filtering
2354
2337
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2355
 
                revision, file_list)
2356
 
            self.add_cleanup(b.unlock)
 
2338
                revision, file_list, self.add_cleanup)
2357
2339
            for relpath, file_id, kind in file_info_list:
2358
2340
                if file_id is None:
2359
2341
                    raise errors.BzrCommandError(
2377
2359
                location = '.'
2378
2360
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2379
2361
            b = dir.open_branch()
2380
 
            b.lock_read()
2381
 
            self.add_cleanup(b.unlock)
 
2362
            self.add_cleanup(b.lock_read().unlock)
2382
2363
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2383
2364
 
2384
2365
        # Decide on the type of delta & diff filtering to use
2404
2385
                        show_timezone=timezone,
2405
2386
                        delta_format=get_verbosity_level(),
2406
2387
                        levels=levels,
2407
 
                        show_advice=levels is None)
 
2388
                        show_advice=levels is None,
 
2389
                        author_list_handler=authors)
2408
2390
 
2409
2391
        # Choose the algorithm for doing the logging. It's annoying
2410
2392
        # having multiple code paths like this but necessary until
2508
2490
        tree, relpath = WorkingTree.open_containing(filename)
2509
2491
        file_id = tree.path2id(relpath)
2510
2492
        b = tree.branch
2511
 
        b.lock_read()
2512
 
        self.add_cleanup(b.unlock)
 
2493
        self.add_cleanup(b.lock_read().unlock)
2513
2494
        touching_revs = log.find_touching_revisions(b, file_id)
2514
2495
        for revno, revision_id, what in touching_revs:
2515
2496
            self.outf.write("%6d %s\n" % (revno, what))
2528
2509
                   help='Recurse into subdirectories.'),
2529
2510
            Option('from-root',
2530
2511
                   help='Print paths relative to the root of the branch.'),
2531
 
            Option('unknown', help='Print unknown files.'),
 
2512
            Option('unknown', short_name='u',
 
2513
                help='Print unknown files.'),
2532
2514
            Option('versioned', help='Print versioned files.',
2533
2515
                   short_name='V'),
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',
 
2516
            Option('ignored', short_name='i',
 
2517
                help='Print ignored files.'),
 
2518
            Option('kind', short_name='k',
2539
2519
                   help='List entries of a particular kind: file, directory, symlink.',
2540
2520
                   type=unicode),
 
2521
            'null',
2541
2522
            'show-ids',
 
2523
            'directory',
2542
2524
            ]
2543
2525
    @display_command
2544
2526
    def run(self, revision=None, verbose=False,
2545
2527
            recursive=False, from_root=False,
2546
2528
            unknown=False, versioned=False, ignored=False,
2547
 
            null=False, kind=None, show_ids=False, path=None):
 
2529
            null=False, kind=None, show_ids=False, path=None, directory=None):
2548
2530
 
2549
2531
        if kind and kind not in ('file', 'directory', 'symlink'):
2550
2532
            raise errors.BzrCommandError('invalid kind specified')
2562
2544
                raise errors.BzrCommandError('cannot specify both --from-root'
2563
2545
                                             ' and PATH')
2564
2546
            fs_path = path
2565
 
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2566
 
            fs_path)
 
2547
        tree, branch, relpath = \
 
2548
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
2567
2549
 
2568
2550
        # Calculate the prefix to use
2569
2551
        prefix = None
2584
2566
                view_str = views.view_display_str(view_files)
2585
2567
                note("Ignoring files outside view. View is %s" % view_str)
2586
2568
 
2587
 
        tree.lock_read()
2588
 
        self.add_cleanup(tree.unlock)
 
2569
        self.add_cleanup(tree.lock_read().unlock)
2589
2570
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2590
2571
            from_dir=relpath, recursive=recursive):
2591
2572
            # Apply additional masking
2638
2619
 
2639
2620
    hidden = True
2640
2621
    _see_also = ['ls']
 
2622
    takes_options = ['directory']
2641
2623
 
2642
2624
    @display_command
2643
 
    def run(self):
2644
 
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
 
2625
    def run(self, directory=u'.'):
 
2626
        for f in WorkingTree.open_containing(directory)[0].unknowns():
2645
2627
            self.outf.write(osutils.quotefn(f) + '\n')
2646
2628
 
2647
2629
 
2712
2694
 
2713
2695
    _see_also = ['status', 'ignored', 'patterns']
2714
2696
    takes_args = ['name_pattern*']
2715
 
    takes_options = [
 
2697
    takes_options = ['directory',
2716
2698
        Option('default-rules',
2717
2699
               help='Display the default ignore rules that bzr uses.')
2718
2700
        ]
2719
2701
 
2720
 
    def run(self, name_pattern_list=None, default_rules=None):
 
2702
    def run(self, name_pattern_list=None, default_rules=None,
 
2703
            directory=u'.'):
2721
2704
        from bzrlib import ignores
2722
2705
        if default_rules is not None:
2723
2706
            # dump the default rules and exit
2729
2712
                "NAME_PATTERN or --default-rules.")
2730
2713
        name_pattern_list = [globbing.normalize_pattern(p)
2731
2714
                             for p in name_pattern_list]
 
2715
        bad_patterns = ''
 
2716
        for p in name_pattern_list:
 
2717
            if not globbing.Globster.is_pattern_valid(p):
 
2718
                bad_patterns += ('\n  %s' % p)
 
2719
        if bad_patterns:
 
2720
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
 
2721
            ui.ui_factory.show_error(msg)
 
2722
            raise errors.InvalidPattern('')
2732
2723
        for name_pattern in name_pattern_list:
2733
2724
            if (name_pattern[0] == '/' or
2734
2725
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2735
2726
                raise errors.BzrCommandError(
2736
2727
                    "NAME_PATTERN should not be an absolute path")
2737
 
        tree, relpath = WorkingTree.open_containing(u'.')
 
2728
        tree, relpath = WorkingTree.open_containing(directory)
2738
2729
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2739
2730
        ignored = globbing.Globster(name_pattern_list)
2740
2731
        matches = []
2741
 
        tree.lock_read()
 
2732
        self.add_cleanup(tree.lock_read().unlock)
2742
2733
        for entry in tree.list_files():
2743
2734
            id = entry[3]
2744
2735
            if id is not None:
2745
2736
                filename = entry[0]
2746
2737
                if ignored.match(filename):
2747
2738
                    matches.append(filename)
2748
 
        tree.unlock()
2749
2739
        if len(matches) > 0:
2750
2740
            self.outf.write("Warning: the following files are version controlled and"
2751
2741
                  " match your ignore pattern:\n%s"
2766
2756
 
2767
2757
    encoding_type = 'replace'
2768
2758
    _see_also = ['ignore', 'ls']
 
2759
    takes_options = ['directory']
2769
2760
 
2770
2761
    @display_command
2771
 
    def run(self):
2772
 
        tree = WorkingTree.open_containing(u'.')[0]
2773
 
        tree.lock_read()
2774
 
        self.add_cleanup(tree.unlock)
 
2762
    def run(self, directory=u'.'):
 
2763
        tree = WorkingTree.open_containing(directory)[0]
 
2764
        self.add_cleanup(tree.lock_read().unlock)
2775
2765
        for path, file_class, kind, file_id, entry in tree.list_files():
2776
2766
            if file_class != 'I':
2777
2767
                continue
2788
2778
    """
2789
2779
    hidden = True
2790
2780
    takes_args = ['revno']
 
2781
    takes_options = ['directory']
2791
2782
 
2792
2783
    @display_command
2793
 
    def run(self, revno):
 
2784
    def run(self, revno, directory=u'.'):
2794
2785
        try:
2795
2786
            revno = int(revno)
2796
2787
        except ValueError:
2797
2788
            raise errors.BzrCommandError("not a valid revision-number: %r"
2798
2789
                                         % revno)
2799
 
        revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
 
2790
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2800
2791
        self.outf.write("%s\n" % revid)
2801
2792
 
2802
2793
 
2829
2820
      =================       =========================
2830
2821
    """
2831
2822
    takes_args = ['dest', 'branch_or_subdir?']
2832
 
    takes_options = [
 
2823
    takes_options = ['directory',
2833
2824
        Option('format',
2834
2825
               help="Type of file to export to.",
2835
2826
               type=unicode),
2844
2835
                    'revision in which it was changed.'),
2845
2836
        ]
2846
2837
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2847
 
        root=None, filters=False, per_file_timestamps=False):
 
2838
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2848
2839
        from bzrlib.export import export
2849
2840
 
2850
2841
        if branch_or_subdir is None:
2851
 
            tree = WorkingTree.open_containing(u'.')[0]
 
2842
            tree = WorkingTree.open_containing(directory)[0]
2852
2843
            b = tree.branch
2853
2844
            subdir = None
2854
2845
        else:
2873
2864
    """
2874
2865
 
2875
2866
    _see_also = ['ls']
2876
 
    takes_options = [
 
2867
    takes_options = ['directory',
2877
2868
        Option('name-from-revision', help='The path name in the old tree.'),
2878
2869
        Option('filters', help='Apply content filters to display the '
2879
2870
                'convenience form.'),
2884
2875
 
2885
2876
    @display_command
2886
2877
    def run(self, filename, revision=None, name_from_revision=False,
2887
 
            filters=False):
 
2878
            filters=False, directory=None):
2888
2879
        if revision is not None and len(revision) != 1:
2889
2880
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2890
2881
                                         " one revision specifier")
2891
2882
        tree, branch, relpath = \
2892
 
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2893
 
        branch.lock_read()
2894
 
        self.add_cleanup(branch.unlock)
 
2883
            _open_directory_or_containing_tree_or_branch(filename, directory)
 
2884
        self.add_cleanup(branch.lock_read().unlock)
2895
2885
        return self._run(tree, branch, relpath, filename, revision,
2896
2886
                         name_from_revision, filters)
2897
2887
 
2900
2890
        if tree is None:
2901
2891
            tree = b.basis_tree()
2902
2892
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2903
 
        rev_tree.lock_read()
2904
 
        self.add_cleanup(rev_tree.unlock)
 
2893
        self.add_cleanup(rev_tree.lock_read().unlock)
2905
2894
 
2906
2895
        old_file_id = rev_tree.path2id(relpath)
2907
2896
 
3169
3158
        def get_message(commit_obj):
3170
3159
            """Callback to get commit message"""
3171
3160
            if file:
3172
 
                my_message = codecs.open(
3173
 
                    file, 'rt', osutils.get_user_encoding()).read()
 
3161
                f = codecs.open(file, 'rt', osutils.get_user_encoding())
 
3162
                try:
 
3163
                    my_message = f.read()
 
3164
                finally:
 
3165
                    f.close()
3174
3166
            elif message is not None:
3175
3167
                my_message = message
3176
3168
            else:
3330
3322
 
3331
3323
            bzr whoami "Frank Chu <fchu@example.com>"
3332
3324
    """
3333
 
    takes_options = [ Option('email',
 
3325
    takes_options = [ 'directory',
 
3326
                      Option('email',
3334
3327
                             help='Display email address only.'),
3335
3328
                      Option('branch',
3336
3329
                             help='Set identity for the current branch instead of '
3340
3333
    encoding_type = 'replace'
3341
3334
 
3342
3335
    @display_command
3343
 
    def run(self, email=False, branch=False, name=None):
 
3336
    def run(self, email=False, branch=False, name=None, directory=None):
3344
3337
        if name is None:
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()
 
3338
            if directory is None:
 
3339
                # use branch if we're inside one; otherwise global config
 
3340
                try:
 
3341
                    c = Branch.open_containing(u'.')[0].get_config()
 
3342
                except errors.NotBranchError:
 
3343
                    c = config.GlobalConfig()
 
3344
            else:
 
3345
                c = Branch.open(directory).get_config()
3350
3346
            if email:
3351
3347
                self.outf.write(c.user_email() + '\n')
3352
3348
            else:
3362
3358
 
3363
3359
        # use global config unless --branch given
3364
3360
        if branch:
3365
 
            c = Branch.open_containing('.')[0].get_config()
 
3361
            if directory is None:
 
3362
                c = Branch.open_containing(u'.')[0].get_config()
 
3363
            else:
 
3364
                c = Branch.open(directory).get_config()
3366
3365
        else:
3367
3366
            c = config.GlobalConfig()
3368
3367
        c.set_user_option('email', name)
3380
3379
 
3381
3380
    _see_also = ['info']
3382
3381
    takes_args = ['nickname?']
3383
 
    def run(self, nickname=None):
3384
 
        branch = Branch.open_containing(u'.')[0]
 
3382
    takes_options = ['directory']
 
3383
    def run(self, nickname=None, directory=u'.'):
 
3384
        branch = Branch.open_containing(directory)[0]
3385
3385
        if nickname is None:
3386
3386
            self.printme(branch)
3387
3387
        else:
3537
3537
                                 'throughout the test suite.',
3538
3538
                            type=get_transport_type),
3539
3539
                     Option('benchmark',
3540
 
                            help='Run the benchmarks rather than selftests.'),
 
3540
                            help='Run the benchmarks rather than selftests.',
 
3541
                            hidden=True),
3541
3542
                     Option('lsprof-timed',
3542
3543
                            help='Generate lsprof output for benchmarked'
3543
3544
                                 ' sections of code.'),
3544
3545
                     Option('lsprof-tests',
3545
3546
                            help='Generate lsprof output for each test.'),
3546
 
                     Option('cache-dir', type=str,
3547
 
                            help='Cache intermediate benchmark output in this '
3548
 
                                 'directory.'),
3549
3547
                     Option('first',
3550
3548
                            help='Run all tests, but run specified tests first.',
3551
3549
                            short_name='f',
3585
3583
 
3586
3584
    def run(self, testspecs_list=None, verbose=False, one=False,
3587
3585
            transport=None, benchmark=None,
3588
 
            lsprof_timed=None, cache_dir=None,
 
3586
            lsprof_timed=None,
3589
3587
            first=False, list_only=False,
3590
3588
            randomize=None, exclude=None, strict=False,
3591
3589
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3592
3590
            parallel=None, lsprof_tests=False):
3593
3591
        from bzrlib.tests import selftest
3594
 
        import bzrlib.benchmarks as benchmarks
3595
 
        from bzrlib.benchmarks import tree_creator
3596
3592
 
3597
3593
        # Make deprecation warnings visible, unless -Werror is set
3598
3594
        symbol_versioning.activate_deprecation_warnings(override=False)
3599
3595
 
3600
 
        if cache_dir is not None:
3601
 
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3602
3596
        if testspecs_list is not None:
3603
3597
            pattern = '|'.join(testspecs_list)
3604
3598
        else:
3612
3606
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3613
3607
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3614
3608
            # stdout, which would corrupt the subunit stream. 
3615
 
            if sys.platform == "win32" and sys.stdout.fileno() >= 0:
 
3609
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
 
3610
            # following code can be deleted when it's sufficiently deployed
 
3611
            # -- vila/mgz 20100514
 
3612
            if (sys.platform == "win32"
 
3613
                and getattr(sys.stdout, 'fileno', None) is not None):
3616
3614
                import msvcrt
3617
3615
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3618
3616
        if parallel:
3619
3617
            self.additional_selftest_args.setdefault(
3620
3618
                'suite_decorators', []).append(parallel)
3621
3619
        if benchmark:
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
 
3620
            raise errors.BzrCommandError(
 
3621
                "--benchmark is no longer supported from bzr 2.2; "
 
3622
                "use bzr-usertest instead")
 
3623
        test_suite_factory = None
3631
3624
        selftest_kwargs = {"verbose": verbose,
3632
3625
                          "pattern": pattern,
3633
3626
                          "stop_on_failure": one,
3635
3628
                          "test_suite_factory": test_suite_factory,
3636
3629
                          "lsprof_timed": lsprof_timed,
3637
3630
                          "lsprof_tests": lsprof_tests,
3638
 
                          "bench_history": benchfile,
3639
3631
                          "matching_tests_first": first,
3640
3632
                          "list_only": list_only,
3641
3633
                          "random_seed": randomize,
3690
3682
 
3691
3683
        branch1 = Branch.open_containing(branch)[0]
3692
3684
        branch2 = Branch.open_containing(other)[0]
3693
 
        branch1.lock_read()
3694
 
        self.add_cleanup(branch1.unlock)
3695
 
        branch2.lock_read()
3696
 
        self.add_cleanup(branch2.unlock)
 
3685
        self.add_cleanup(branch1.lock_read().unlock)
 
3686
        self.add_cleanup(branch2.lock_read().unlock)
3697
3687
        last1 = ensure_null(branch1.last_revision())
3698
3688
        last2 = ensure_null(branch2.last_revision())
3699
3689
 
3793
3783
                ' completely merged into the source, pull from the'
3794
3784
                ' source rather than merging.  When this happens,'
3795
3785
                ' you do not need to commit the result.'),
3796
 
        Option('directory',
 
3786
        custom_help('directory',
3797
3787
               help='Branch to merge into, '
3798
 
                    'rather than the one containing the working directory.',
3799
 
               short_name='d',
3800
 
               type=unicode,
3801
 
               ),
 
3788
                    'rather than the one containing the working directory.'),
3802
3789
        Option('preview', help='Instead of merging, show a diff of the'
3803
3790
               ' merge.'),
3804
3791
        Option('interactive', help='Select changes interactively.',
3837
3824
            unversioned_filter=tree.is_ignored, view_info=view_info)
3838
3825
        pb = ui.ui_factory.nested_progress_bar()
3839
3826
        self.add_cleanup(pb.finished)
3840
 
        tree.lock_write()
3841
 
        self.add_cleanup(tree.unlock)
 
3827
        self.add_cleanup(tree.lock_write().unlock)
3842
3828
        if location is not None:
3843
3829
            try:
3844
3830
                mergeable = bundle.read_mergeable_from_url(location,
3905
3891
    def _do_preview(self, merger):
3906
3892
        from bzrlib.diff import show_diff_trees
3907
3893
        result_tree = self._get_preview(merger)
 
3894
        path_encoding = osutils.get_diff_header_encoding()
3908
3895
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3909
 
                        old_label='', new_label='')
 
3896
                        old_label='', new_label='',
 
3897
                        path_encoding=path_encoding)
3910
3898
 
3911
3899
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3912
3900
        merger.change_reporter = change_reporter
4100
4088
        if merge_type is None:
4101
4089
            merge_type = _mod_merge.Merge3Merger
4102
4090
        tree, file_list = tree_files(file_list)
4103
 
        tree.lock_write()
4104
 
        self.add_cleanup(tree.unlock)
 
4091
        self.add_cleanup(tree.lock_write().unlock)
4105
4092
        parents = tree.get_parent_ids()
4106
4093
        if len(parents) != 2:
4107
4094
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4217
4204
    def run(self, revision=None, no_backup=False, file_list=None,
4218
4205
            forget_merges=None):
4219
4206
        tree, file_list = tree_files(file_list)
4220
 
        tree.lock_tree_write()
4221
 
        self.add_cleanup(tree.unlock)
 
4207
        self.add_cleanup(tree.lock_tree_write().unlock)
4222
4208
        if forget_merges:
4223
4209
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4224
4210
        else:
4313
4299
    _see_also = ['merge', 'pull']
4314
4300
    takes_args = ['other_branch?']
4315
4301
    takes_options = [
 
4302
        'directory',
4316
4303
        Option('reverse', 'Reverse the order of revisions.'),
4317
4304
        Option('mine-only',
4318
4305
               'Display changes in the local branch only.'),
4340
4327
            theirs_only=False,
4341
4328
            log_format=None, long=False, short=False, line=False,
4342
4329
            show_ids=False, verbose=False, this=False, other=False,
4343
 
            include_merges=False, revision=None, my_revision=None):
 
4330
            include_merges=False, revision=None, my_revision=None,
 
4331
            directory=u'.'):
4344
4332
        from bzrlib.missing import find_unmerged, iter_log_revisions
4345
4333
        def message(s):
4346
4334
            if not is_quiet():
4359
4347
        elif theirs_only:
4360
4348
            restrict = 'remote'
4361
4349
 
4362
 
        local_branch = Branch.open_containing(u".")[0]
4363
 
        local_branch.lock_read()
4364
 
        self.add_cleanup(local_branch.unlock)
 
4350
        local_branch = Branch.open_containing(directory)[0]
 
4351
        self.add_cleanup(local_branch.lock_read().unlock)
4365
4352
 
4366
4353
        parent = local_branch.get_parent()
4367
4354
        if other_branch is None:
4378
4365
        if remote_branch.base == local_branch.base:
4379
4366
            remote_branch = local_branch
4380
4367
        else:
4381
 
            remote_branch.lock_read()
4382
 
            self.add_cleanup(remote_branch.unlock)
 
4368
            self.add_cleanup(remote_branch.lock_read().unlock)
4383
4369
 
4384
4370
        local_revid_range = _revision_range_to_revid_range(
4385
4371
            _get_revision_range(my_revision, local_branch,
4440
4426
            message("Branches are up to date.\n")
4441
4427
        self.cleanup_now()
4442
4428
        if not status_code and parent is None and other_branch is not None:
4443
 
            local_branch.lock_write()
4444
 
            self.add_cleanup(local_branch.unlock)
 
4429
            self.add_cleanup(local_branch.lock_write().unlock)
4445
4430
            # handle race conditions - a parent might be set while we run.
4446
4431
            if local_branch.get_parent() is None:
4447
4432
                local_branch.set_parent(remote_branch.base)
4547
4532
            b = Branch.open_containing(branch)[0]
4548
4533
        else:
4549
4534
            b = Branch.open(branch)
4550
 
        b.lock_read()
4551
 
        self.add_cleanup(b.unlock)
 
4535
        self.add_cleanup(b.lock_read().unlock)
4552
4536
        if revision is None:
4553
4537
            rev_id = b.last_revision()
4554
4538
        else:
4578
4562
                     Option('long', help='Show commit date in annotations.'),
4579
4563
                     'revision',
4580
4564
                     'show-ids',
 
4565
                     'directory',
4581
4566
                     ]
4582
4567
    encoding_type = 'exact'
4583
4568
 
4584
4569
    @display_command
4585
4570
    def run(self, filename, all=False, long=False, revision=None,
4586
 
            show_ids=False):
 
4571
            show_ids=False, directory=None):
4587
4572
        from bzrlib.annotate import annotate_file, annotate_file_tree
4588
4573
        wt, branch, relpath = \
4589
 
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
4574
            _open_directory_or_containing_tree_or_branch(filename, directory)
4590
4575
        if wt is not None:
4591
 
            wt.lock_read()
4592
 
            self.add_cleanup(wt.unlock)
 
4576
            self.add_cleanup(wt.lock_read().unlock)
4593
4577
        else:
4594
 
            branch.lock_read()
4595
 
            self.add_cleanup(branch.unlock)
 
4578
            self.add_cleanup(branch.lock_read().unlock)
4596
4579
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4597
 
        tree.lock_read()
4598
 
        self.add_cleanup(tree.unlock)
 
4580
        self.add_cleanup(tree.lock_read().unlock)
4599
4581
        if wt is not None:
4600
4582
            file_id = wt.path2id(relpath)
4601
4583
        else:
4619
4601
 
4620
4602
    hidden = True # is this right ?
4621
4603
    takes_args = ['revision_id*']
4622
 
    takes_options = ['revision']
 
4604
    takes_options = ['directory', 'revision']
4623
4605
 
4624
 
    def run(self, revision_id_list=None, revision=None):
 
4606
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
4625
4607
        if revision_id_list is not None and revision is not None:
4626
4608
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4627
4609
        if revision_id_list is None and revision is None:
4628
4610
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4629
 
        b = WorkingTree.open_containing(u'.')[0].branch
4630
 
        b.lock_write()
4631
 
        self.add_cleanup(b.unlock)
 
4611
        b = WorkingTree.open_containing(directory)[0].branch
 
4612
        self.add_cleanup(b.lock_write().unlock)
4632
4613
        return self._run(b, revision_id_list, revision)
4633
4614
 
4634
4615
    def _run(self, b, revision_id_list, revision):
4693
4674
 
4694
4675
    _see_also = ['checkouts', 'unbind']
4695
4676
    takes_args = ['location?']
4696
 
    takes_options = []
 
4677
    takes_options = ['directory']
4697
4678
 
4698
 
    def run(self, location=None):
4699
 
        b, relpath = Branch.open_containing(u'.')
 
4679
    def run(self, location=None, directory=u'.'):
 
4680
        b, relpath = Branch.open_containing(directory)
4700
4681
        if location is None:
4701
4682
            try:
4702
4683
                location = b.get_old_bound_location()
4729
4710
 
4730
4711
    _see_also = ['checkouts', 'bind']
4731
4712
    takes_args = []
4732
 
    takes_options = []
 
4713
    takes_options = ['directory']
4733
4714
 
4734
 
    def run(self):
4735
 
        b, relpath = Branch.open_containing(u'.')
 
4715
    def run(self, directory=u'.'):
 
4716
        b, relpath = Branch.open_containing(directory)
4736
4717
        if not b.unbind():
4737
4718
            raise errors.BzrCommandError('Local branch is not bound')
4738
4719
 
4784
4765
            b = control.open_branch()
4785
4766
 
4786
4767
        if tree is not None:
4787
 
            tree.lock_write()
4788
 
            self.add_cleanup(tree.unlock)
 
4768
            self.add_cleanup(tree.lock_write().unlock)
4789
4769
        else:
4790
 
            b.lock_write()
4791
 
            self.add_cleanup(b.unlock)
 
4770
            self.add_cleanup(b.lock_write().unlock)
4792
4771
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4793
4772
 
4794
4773
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4902
4881
                    'result in a dynamically allocated port.  The default port '
4903
4882
                    'depends on the protocol.',
4904
4883
               type=str),
4905
 
        Option('directory',
4906
 
               help='Serve contents of this directory.',
4907
 
               type=unicode),
 
4884
        custom_help('directory',
 
4885
               help='Serve contents of this directory.'),
4908
4886
        Option('allow-writes',
4909
4887
               help='By default the server is a readonly server.  Supplying '
4910
4888
                    '--allow-writes enables write access to the contents of '
4937
4915
 
4938
4916
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
4939
4917
            protocol=None):
4940
 
        from bzrlib.transport import get_transport, transport_server_registry
 
4918
        from bzrlib import transport
4941
4919
        if directory is None:
4942
4920
            directory = os.getcwd()
4943
4921
        if protocol is None:
4944
 
            protocol = transport_server_registry.get()
 
4922
            protocol = transport.transport_server_registry.get()
4945
4923
        host, port = self.get_host_and_port(port)
4946
4924
        url = urlutils.local_path_to_url(directory)
4947
4925
        if not allow_writes:
4948
4926
            url = 'readonly+' + url
4949
 
        transport = get_transport(url)
4950
 
        protocol(transport, host, port, inet)
 
4927
        t = transport.get_transport(url)
 
4928
        protocol(t, host, port, inet)
4951
4929
 
4952
4930
 
4953
4931
class cmd_join(Command):
5046
5024
    _see_also = ['send']
5047
5025
 
5048
5026
    takes_options = [
 
5027
        'directory',
5049
5028
        RegistryOption.from_kwargs('patch-type',
5050
5029
            'The type of patch to include in the directive.',
5051
5030
            title='Patch type',
5064
5043
    encoding_type = 'exact'
5065
5044
 
5066
5045
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5067
 
            sign=False, revision=None, mail_to=None, message=None):
 
5046
            sign=False, revision=None, mail_to=None, message=None,
 
5047
            directory=u'.'):
5068
5048
        from bzrlib.revision import ensure_null, NULL_REVISION
5069
5049
        include_patch, include_bundle = {
5070
5050
            'plain': (False, False),
5071
5051
            'diff': (True, False),
5072
5052
            'bundle': (True, True),
5073
5053
            }[patch_type]
5074
 
        branch = Branch.open('.')
 
5054
        branch = Branch.open(directory)
5075
5055
        stored_submit_branch = branch.get_submit_branch()
5076
5056
        if submit_branch is None:
5077
5057
            submit_branch = stored_submit_branch
5162
5142
    given, in which case it is sent to a file.
5163
5143
 
5164
5144
    Mail is sent using your preferred mail program.  This should be transparent
5165
 
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
 
5145
    on Windows (it uses MAPI).  On Unix, it requires the xdg-email utility.
5166
5146
    If the preferred client can't be found (or used), your editor will be used.
5167
5147
 
5168
5148
    To use a specific mail program, set the mail_client configuration option.
5339
5319
        Option('delete',
5340
5320
            help='Delete this tag rather than placing it.',
5341
5321
            ),
5342
 
        Option('directory',
5343
 
            help='Branch in which to place the tag.',
5344
 
            short_name='d',
5345
 
            type=unicode,
5346
 
            ),
 
5322
        custom_help('directory',
 
5323
            help='Branch in which to place the tag.'),
5347
5324
        Option('force',
5348
5325
            help='Replace existing tags.',
5349
5326
            ),
5357
5334
            revision=None,
5358
5335
            ):
5359
5336
        branch, relpath = Branch.open_containing(directory)
5360
 
        branch.lock_write()
5361
 
        self.add_cleanup(branch.unlock)
 
5337
        self.add_cleanup(branch.lock_write().unlock)
5362
5338
        if delete:
5363
5339
            if tag_name is None:
5364
5340
                raise errors.BzrCommandError("No tag specified to delete.")
5392
5368
 
5393
5369
    _see_also = ['tag']
5394
5370
    takes_options = [
5395
 
        Option('directory',
5396
 
            help='Branch whose tags should be displayed.',
5397
 
            short_name='d',
5398
 
            type=unicode,
5399
 
            ),
 
5371
        custom_help('directory',
 
5372
            help='Branch whose tags should be displayed.'),
5400
5373
        RegistryOption.from_kwargs('sort',
5401
5374
            'Sort tags by different criteria.', title='Sorting',
5402
5375
            alpha='Sort tags lexicographically (default).',
5419
5392
        if not tags:
5420
5393
            return
5421
5394
 
5422
 
        branch.lock_read()
5423
 
        self.add_cleanup(branch.unlock)
 
5395
        self.add_cleanup(branch.lock_read().unlock)
5424
5396
        if revision:
5425
5397
            graph = branch.repository.get_graph()
5426
5398
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5573
5545
    """
5574
5546
 
5575
5547
    takes_args = ['to_location?']
5576
 
    takes_options = [Option('force',
 
5548
    takes_options = ['directory',
 
5549
                     Option('force',
5577
5550
                        help='Switch even if local commits will be lost.'),
5578
5551
                     'revision',
5579
5552
                     Option('create-branch', short_name='b',
5582
5555
                    ]
5583
5556
 
5584
5557
    def run(self, to_location=None, force=False, create_branch=False,
5585
 
            revision=None):
 
5558
            revision=None, directory=u'.'):
5586
5559
        from bzrlib import switch
5587
 
        tree_location = '.'
 
5560
        tree_location = directory
5588
5561
        revision = _get_one_revision('switch', revision)
5589
5562
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5590
5563
        if to_location is None:
5591
5564
            if revision is None:
5592
5565
                raise errors.BzrCommandError('You must supply either a'
5593
5566
                                             ' revision or a location')
5594
 
            to_location = '.'
 
5567
            to_location = tree_location
5595
5568
        try:
5596
5569
            branch = control_dir.open_branch()
5597
5570
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5872
5845
    takes_args = ['file*']
5873
5846
 
5874
5847
    takes_options = [
 
5848
        'directory',
5875
5849
        'revision',
5876
5850
        Option('all', help='Shelve all changes.'),
5877
5851
        'message',
5886
5860
    _see_also = ['unshelve']
5887
5861
 
5888
5862
    def run(self, revision=None, all=False, file_list=None, message=None,
5889
 
            writer=None, list=False, destroy=False):
 
5863
            writer=None, list=False, destroy=False, directory=u'.'):
5890
5864
        if list:
5891
5865
            return self.run_for_list()
5892
5866
        from bzrlib.shelf_ui import Shelver
5894
5868
            writer = bzrlib.option.diff_writer_registry.get()
5895
5869
        try:
5896
5870
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5897
 
                file_list, message, destroy=destroy)
 
5871
                file_list, message, destroy=destroy, directory=directory)
5898
5872
            try:
5899
5873
                shelver.run()
5900
5874
            finally:
5904
5878
 
5905
5879
    def run_for_list(self):
5906
5880
        tree = WorkingTree.open_containing('.')[0]
5907
 
        tree.lock_read()
5908
 
        self.add_cleanup(tree.unlock)
 
5881
        self.add_cleanup(tree.lock_read().unlock)
5909
5882
        manager = tree.get_shelf_manager()
5910
5883
        shelves = manager.active_shelves()
5911
5884
        if len(shelves) == 0:
5929
5902
 
5930
5903
    takes_args = ['shelf_id?']
5931
5904
    takes_options = [
 
5905
        'directory',
5932
5906
        RegistryOption.from_kwargs(
5933
5907
            'action', help="The action to perform.",
5934
5908
            enum_switch=False, value_switches=True,
5942
5916
    ]
5943
5917
    _see_also = ['shelve']
5944
5918
 
5945
 
    def run(self, shelf_id=None, action='apply'):
 
5919
    def run(self, shelf_id=None, action='apply', directory=u'.'):
5946
5920
        from bzrlib.shelf_ui import Unshelver
5947
 
        unshelver = Unshelver.from_args(shelf_id, action)
 
5921
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5948
5922
        try:
5949
5923
            unshelver.run()
5950
5924
        finally:
5966
5940
 
5967
5941
    To check what clean-tree will do, use --dry-run.
5968
5942
    """
5969
 
    takes_options = [Option('ignored', help='Delete all ignored files.'),
 
5943
    takes_options = ['directory',
 
5944
                     Option('ignored', help='Delete all ignored files.'),
5970
5945
                     Option('detritus', help='Delete conflict files, merge'
5971
5946
                            ' backups, and failed selftest dirs.'),
5972
5947
                     Option('unknown',
5975
5950
                            ' deleting them.'),
5976
5951
                     Option('force', help='Do not prompt before deleting.')]
5977
5952
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5978
 
            force=False):
 
5953
            force=False, directory=u'.'):
5979
5954
        from bzrlib.clean_tree import clean_tree
5980
5955
        if not (unknown or ignored or detritus):
5981
5956
            unknown = True
5982
5957
        if dry_run:
5983
5958
            force = True
5984
 
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5985
 
                   dry_run=dry_run, no_prompt=force)
 
5959
        clean_tree(directory, unknown=unknown, ignored=ignored,
 
5960
                   detritus=detritus, dry_run=dry_run, no_prompt=force)
5986
5961
 
5987
5962
 
5988
5963
class cmd_reference(Command):