~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge prerequisite branch and tweak test to be more compact and faster.

Show diffs side-by-side

added added

removed removed

Lines of Context:
491
491
    takes_options = [
492
492
        Option('force',
493
493
               help='Remove the working tree even if it has '
494
 
                    'uncommitted changes.'),
 
494
                    'uncommitted or shelved changes.'),
495
495
        ]
496
496
 
497
497
    def run(self, location_list, force=False):
511
511
            if not force:
512
512
                if (working.has_changes()):
513
513
                    raise errors.UncommittedChanges(working)
 
514
                if working.get_shelf_manager().last_shelf() is not None:
 
515
                    raise errors.ShelvedChanges(working)
514
516
 
515
517
            if working.user_url != working.branch.user_url:
516
518
                raise errors.BzrCommandError("You cannot remove the working tree"
536
538
        if tree:
537
539
            try:
538
540
                wt = WorkingTree.open_containing(location)[0]
539
 
                wt.lock_read()
 
541
                self.add_cleanup(wt.lock_read().unlock)
540
542
            except (errors.NoWorkingTree, errors.NotLocalUrl):
541
543
                raise errors.NoWorkingTree(location)
542
 
            self.add_cleanup(wt.unlock)
543
544
            revid = wt.last_revision()
544
545
            try:
545
546
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
548
549
            revno = ".".join(str(n) for n in revno_t)
549
550
        else:
550
551
            b = Branch.open_containing(location)[0]
551
 
            b.lock_read()
552
 
            self.add_cleanup(b.unlock)
 
552
            self.add_cleanup(b.lock_read().unlock)
553
553
            revno = b.revno()
554
554
        self.cleanup_now()
555
555
        self.outf.write(str(revno) + '\n')
575
575
        try:
576
576
            wt = WorkingTree.open_containing(directory)[0]
577
577
            b = wt.branch
578
 
            wt.lock_read()
579
 
            self.add_cleanup(wt.unlock)
 
578
            self.add_cleanup(wt.lock_read().unlock)
580
579
        except (errors.NoWorkingTree, errors.NotLocalUrl):
581
580
            wt = None
582
581
            b = Branch.open_containing(directory)[0]
583
 
            b.lock_read()
584
 
            self.add_cleanup(b.unlock)
 
582
            self.add_cleanup(b.lock_read().unlock)
585
583
        revision_ids = []
586
584
        if revision is not None:
587
585
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
686
684
                should_print=(not is_quiet()))
687
685
 
688
686
        if base_tree:
689
 
            base_tree.lock_read()
690
 
            self.add_cleanup(base_tree.unlock)
 
687
            self.add_cleanup(base_tree.lock_read().unlock)
691
688
        tree, file_list = tree_files_for_add(file_list)
692
689
        added, ignored = tree.smart_add(file_list, not
693
690
            no_recurse, action=action, save=not dry_run)
765
762
 
766
763
        revision = _get_one_revision('inventory', revision)
767
764
        work_tree, file_list = tree_files(file_list)
768
 
        work_tree.lock_read()
769
 
        self.add_cleanup(work_tree.unlock)
 
765
        self.add_cleanup(work_tree.lock_read().unlock)
770
766
        if revision is not None:
771
767
            tree = revision.as_tree(work_tree.branch)
772
768
 
773
769
            extra_trees = [work_tree]
774
 
            tree.lock_read()
775
 
            self.add_cleanup(tree.unlock)
 
770
            self.add_cleanup(tree.lock_read().unlock)
776
771
        else:
777
772
            tree = work_tree
778
773
            extra_trees = []
838
833
        if len(names_list) < 2:
839
834
            raise errors.BzrCommandError("missing file argument")
840
835
        tree, rel_names = tree_files(names_list, canonicalize=False)
841
 
        tree.lock_tree_write()
842
 
        self.add_cleanup(tree.unlock)
 
836
        self.add_cleanup(tree.lock_tree_write().unlock)
843
837
        self._run(tree, names_list, rel_names, after)
844
838
 
845
839
    def run_auto(self, names_list, after, dry_run):
850
844
            raise errors.BzrCommandError('--after cannot be specified with'
851
845
                                         ' --auto.')
852
846
        work_tree, file_list = tree_files(names_list, default_branch='.')
853
 
        work_tree.lock_tree_write()
854
 
        self.add_cleanup(work_tree.unlock)
 
847
        self.add_cleanup(work_tree.lock_tree_write().unlock)
855
848
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
856
849
 
857
850
    def _run(self, tree, names_list, rel_names, after):
988
981
        try:
989
982
            tree_to = WorkingTree.open_containing(directory)[0]
990
983
            branch_to = tree_to.branch
991
 
            tree_to.lock_write()
992
 
            self.add_cleanup(tree_to.unlock)
 
984
            self.add_cleanup(tree_to.lock_write().unlock)
993
985
        except errors.NoWorkingTree:
994
986
            tree_to = None
995
987
            branch_to = Branch.open_containing(directory)[0]
996
 
            branch_to.lock_write()
997
 
            self.add_cleanup(branch_to.unlock)
 
988
            self.add_cleanup(branch_to.lock_write().unlock)
998
989
 
999
990
        if local and not branch_to.get_bound_location():
1000
991
            raise errors.LocalRequiresBoundBranch()
1031
1022
        else:
1032
1023
            branch_from = Branch.open(location,
1033
1024
                possible_transports=possible_transports)
1034
 
            branch_from.lock_read()
1035
 
            self.add_cleanup(branch_from.unlock)
 
1025
            self.add_cleanup(branch_from.lock_read().unlock)
1036
1026
 
1037
1027
            if branch_to.get_parent() is None or remember:
1038
1028
                branch_to.set_parent(branch_from.base)
1218
1208
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1219
1209
            from_location)
1220
1210
        revision = _get_one_revision('branch', revision)
1221
 
        br_from.lock_read()
1222
 
        self.add_cleanup(br_from.unlock)
 
1211
        self.add_cleanup(br_from.lock_read().unlock)
1223
1212
        if revision is not None:
1224
1213
            revision_id = revision.as_revision_id(br_from)
1225
1214
        else:
1349
1338
            except errors.NoWorkingTree:
1350
1339
                source.bzrdir.create_workingtree(revision_id)
1351
1340
                return
1352
 
 
1353
 
        if not lightweight:
1354
 
            message = ('Copying history to "%s". '
1355
 
                'To checkout without local history use --lightweight.' % to_location)
1356
 
            ui.ui_factory.show_message(message)
1357
1341
        source.create_checkout(to_location, revision_id, lightweight,
1358
1342
                               accelerator_tree, hardlink)
1359
1343
 
1370
1354
    @display_command
1371
1355
    def run(self, dir=u'.'):
1372
1356
        tree = WorkingTree.open_containing(dir)[0]
1373
 
        tree.lock_read()
1374
 
        self.add_cleanup(tree.unlock)
 
1357
        self.add_cleanup(tree.lock_read().unlock)
1375
1358
        new_inv = tree.inventory
1376
1359
        old_tree = tree.basis_tree()
1377
 
        old_tree.lock_read()
1378
 
        self.add_cleanup(old_tree.unlock)
 
1360
        self.add_cleanup(old_tree.lock_read().unlock)
1379
1361
        old_inv = old_tree.inventory
1380
1362
        renames = []
1381
1363
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1419
1401
        master = branch.get_master_branch(
1420
1402
            possible_transports=possible_transports)
1421
1403
        if master is not None:
1422
 
            tree.lock_write()
1423
1404
            branch_location = master.base
 
1405
            tree.lock_write()
1424
1406
        else:
 
1407
            branch_location = tree.branch.base
1425
1408
            tree.lock_tree_write()
1426
 
            branch_location = tree.branch.base
1427
1409
        self.add_cleanup(tree.unlock)
1428
1410
        # get rid of the final '/' and be ready for display
1429
1411
        branch_location = urlutils.unescape_for_display(
1549
1531
        if file_list is not None:
1550
1532
            file_list = [f for f in file_list]
1551
1533
 
1552
 
        tree.lock_write()
1553
 
        self.add_cleanup(tree.unlock)
 
1534
        self.add_cleanup(tree.lock_write().unlock)
1554
1535
        # Heuristics should probably all move into tree.remove_smart or
1555
1536
        # some such?
1556
1537
        if new:
1989
1970
         old_branch, new_branch,
1990
1971
         specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1991
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()
1992
1975
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1993
1976
                               specific_files=specific_files,
1994
1977
                               external_diff_options=diff_options,
1995
1978
                               old_label=old_label, new_label=new_label,
1996
 
                               extra_trees=extra_trees, using=using,
 
1979
                               extra_trees=extra_trees,
 
1980
                               path_encoding=path_encoding,
 
1981
                               using=using,
1997
1982
                               format_cls=format)
1998
1983
 
1999
1984
 
2012
1997
    @display_command
2013
1998
    def run(self, show_ids=False, directory=u'.'):
2014
1999
        tree = WorkingTree.open_containing(directory)[0]
2015
 
        tree.lock_read()
2016
 
        self.add_cleanup(tree.unlock)
 
2000
        self.add_cleanup(tree.lock_read().unlock)
2017
2001
        old = tree.basis_tree()
2018
 
        old.lock_read()
2019
 
        self.add_cleanup(old.unlock)
 
2002
        self.add_cleanup(old.lock_read().unlock)
2020
2003
        for path, ie in old.inventory.iter_entries():
2021
2004
            if not tree.has_id(ie.file_id):
2022
2005
                self.outf.write(path)
2032
2015
 
2033
2016
    hidden = True
2034
2017
    _see_also = ['status', 'ls']
2035
 
    takes_options = ['directory',
2036
 
            Option('null',
2037
 
                   help='Write an ascii NUL (\\0) separator '
2038
 
                   'between files rather than a newline.')
2039
 
            ]
 
2018
    takes_options = ['directory', 'null']
2040
2019
 
2041
2020
    @display_command
2042
2021
    def run(self, null=False, directory=u'.'):
2055
2034
 
2056
2035
    hidden = True
2057
2036
    _see_also = ['status', 'ls']
2058
 
    takes_options = ['directory',
2059
 
            Option('null',
2060
 
                   help='Write an ascii NUL (\\0) separator '
2061
 
                   'between files rather than a newline.')
2062
 
            ]
 
2037
    takes_options = ['directory', 'null']
2063
2038
 
2064
2039
    @display_command
2065
2040
    def run(self, null=False, directory=u'.'):
2066
2041
        wt = WorkingTree.open_containing(directory)[0]
2067
 
        wt.lock_read()
2068
 
        self.add_cleanup(wt.unlock)
 
2042
        self.add_cleanup(wt.lock_read().unlock)
2069
2043
        basis = wt.basis_tree()
2070
 
        basis.lock_read()
2071
 
        self.add_cleanup(basis.unlock)
 
2044
        self.add_cleanup(basis.lock_read().unlock)
2072
2045
        basis_inv = basis.inventory
2073
2046
        inv = wt.inventory
2074
2047
        for file_id in inv:
2362
2335
        if file_list:
2363
2336
            # find the file ids to log and check for directory filtering
2364
2337
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2365
 
                revision, file_list)
2366
 
            self.add_cleanup(b.unlock)
 
2338
                revision, file_list, self.add_cleanup)
2367
2339
            for relpath, file_id, kind in file_info_list:
2368
2340
                if file_id is None:
2369
2341
                    raise errors.BzrCommandError(
2387
2359
                location = '.'
2388
2360
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2389
2361
            b = dir.open_branch()
2390
 
            b.lock_read()
2391
 
            self.add_cleanup(b.unlock)
 
2362
            self.add_cleanup(b.lock_read().unlock)
2392
2363
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2393
2364
 
2394
2365
        # Decide on the type of delta & diff filtering to use
2519
2490
        tree, relpath = WorkingTree.open_containing(filename)
2520
2491
        file_id = tree.path2id(relpath)
2521
2492
        b = tree.branch
2522
 
        b.lock_read()
2523
 
        self.add_cleanup(b.unlock)
 
2493
        self.add_cleanup(b.lock_read().unlock)
2524
2494
        touching_revs = log.find_touching_revisions(b, file_id)
2525
2495
        for revno, revision_id, what in touching_revs:
2526
2496
            self.outf.write("%6d %s\n" % (revno, what))
2539
2509
                   help='Recurse into subdirectories.'),
2540
2510
            Option('from-root',
2541
2511
                   help='Print paths relative to the root of the branch.'),
2542
 
            Option('unknown', help='Print unknown files.'),
 
2512
            Option('unknown', short_name='u',
 
2513
                help='Print unknown files.'),
2543
2514
            Option('versioned', help='Print versioned files.',
2544
2515
                   short_name='V'),
2545
 
            Option('ignored', help='Print ignored files.'),
2546
 
            Option('null',
2547
 
                   help='Write an ascii NUL (\\0) separator '
2548
 
                   'between files rather than a newline.'),
2549
 
            Option('kind',
 
2516
            Option('ignored', short_name='i',
 
2517
                help='Print ignored files.'),
 
2518
            Option('kind', short_name='k',
2550
2519
                   help='List entries of a particular kind: file, directory, symlink.',
2551
2520
                   type=unicode),
 
2521
            'null',
2552
2522
            'show-ids',
2553
2523
            'directory',
2554
2524
            ]
2596
2566
                view_str = views.view_display_str(view_files)
2597
2567
                note("Ignoring files outside view. View is %s" % view_str)
2598
2568
 
2599
 
        tree.lock_read()
2600
 
        self.add_cleanup(tree.unlock)
 
2569
        self.add_cleanup(tree.lock_read().unlock)
2601
2570
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2602
2571
            from_dir=relpath, recursive=recursive):
2603
2572
            # Apply additional masking
2785
2754
    @display_command
2786
2755
    def run(self, directory=u'.'):
2787
2756
        tree = WorkingTree.open_containing(directory)[0]
2788
 
        tree.lock_read()
2789
 
        self.add_cleanup(tree.unlock)
 
2757
        self.add_cleanup(tree.lock_read().unlock)
2790
2758
        for path, file_class, kind, file_id, entry in tree.list_files():
2791
2759
            if file_class != 'I':
2792
2760
                continue
2906
2874
                                         " one revision specifier")
2907
2875
        tree, branch, relpath = \
2908
2876
            _open_directory_or_containing_tree_or_branch(filename, directory)
2909
 
        branch.lock_read()
2910
 
        self.add_cleanup(branch.unlock)
 
2877
        self.add_cleanup(branch.lock_read().unlock)
2911
2878
        return self._run(tree, branch, relpath, filename, revision,
2912
2879
                         name_from_revision, filters)
2913
2880
 
2916
2883
        if tree is None:
2917
2884
            tree = b.basis_tree()
2918
2885
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2919
 
        rev_tree.lock_read()
2920
 
        self.add_cleanup(rev_tree.unlock)
 
2886
        self.add_cleanup(rev_tree.lock_read().unlock)
2921
2887
 
2922
2888
        old_file_id = rev_tree.path2id(relpath)
2923
2889
 
3185
3151
        def get_message(commit_obj):
3186
3152
            """Callback to get commit message"""
3187
3153
            if file:
3188
 
                my_message = codecs.open(
3189
 
                    file, 'rt', osutils.get_user_encoding()).read()
 
3154
                f = codecs.open(file, 'rt', osutils.get_user_encoding())
 
3155
                try:
 
3156
                    my_message = f.read()
 
3157
                finally:
 
3158
                    f.close()
3190
3159
            elif message is not None:
3191
3160
                my_message = message
3192
3161
            else:
3346
3315
 
3347
3316
            bzr whoami "Frank Chu <fchu@example.com>"
3348
3317
    """
3349
 
    takes_options = [ Option('email',
 
3318
    takes_options = [ 'directory',
 
3319
                      Option('email',
3350
3320
                             help='Display email address only.'),
3351
3321
                      Option('branch',
3352
3322
                             help='Set identity for the current branch instead of '
3356
3326
    encoding_type = 'replace'
3357
3327
 
3358
3328
    @display_command
3359
 
    def run(self, email=False, branch=False, name=None):
 
3329
    def run(self, email=False, branch=False, name=None, directory=None):
3360
3330
        if name is None:
3361
 
            # use branch if we're inside one; otherwise global config
3362
 
            try:
3363
 
                c = Branch.open_containing('.')[0].get_config()
3364
 
            except errors.NotBranchError:
3365
 
                c = config.GlobalConfig()
 
3331
            if directory is None:
 
3332
                # use branch if we're inside one; otherwise global config
 
3333
                try:
 
3334
                    c = Branch.open_containing(u'.')[0].get_config()
 
3335
                except errors.NotBranchError:
 
3336
                    c = config.GlobalConfig()
 
3337
            else:
 
3338
                c = Branch.open(directory).get_config()
3366
3339
            if email:
3367
3340
                self.outf.write(c.user_email() + '\n')
3368
3341
            else:
3378
3351
 
3379
3352
        # use global config unless --branch given
3380
3353
        if branch:
3381
 
            c = Branch.open_containing('.')[0].get_config()
 
3354
            if directory is None:
 
3355
                c = Branch.open_containing(u'.')[0].get_config()
 
3356
            else:
 
3357
                c = Branch.open(directory).get_config()
3382
3358
        else:
3383
3359
            c = config.GlobalConfig()
3384
3360
        c.set_user_option('email', name)
3629
3605
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3630
3606
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3631
3607
            # stdout, which would corrupt the subunit stream. 
3632
 
            if sys.platform == "win32" and sys.stdout.fileno() >= 0:
 
3608
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
 
3609
            # following code can be deleted when it's sufficiently deployed
 
3610
            # -- vila/mgz 20100514
 
3611
            if (sys.platform == "win32"
 
3612
                and getattr(sys.stdout, 'fileno', None) is not None):
3633
3613
                import msvcrt
3634
3614
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3635
3615
        if parallel:
3707
3687
 
3708
3688
        branch1 = Branch.open_containing(branch)[0]
3709
3689
        branch2 = Branch.open_containing(other)[0]
3710
 
        branch1.lock_read()
3711
 
        self.add_cleanup(branch1.unlock)
3712
 
        branch2.lock_read()
3713
 
        self.add_cleanup(branch2.unlock)
 
3690
        self.add_cleanup(branch1.lock_read().unlock)
 
3691
        self.add_cleanup(branch2.lock_read().unlock)
3714
3692
        last1 = ensure_null(branch1.last_revision())
3715
3693
        last2 = ensure_null(branch2.last_revision())
3716
3694
 
3851
3829
            unversioned_filter=tree.is_ignored, view_info=view_info)
3852
3830
        pb = ui.ui_factory.nested_progress_bar()
3853
3831
        self.add_cleanup(pb.finished)
3854
 
        tree.lock_write()
3855
 
        self.add_cleanup(tree.unlock)
 
3832
        self.add_cleanup(tree.lock_write().unlock)
3856
3833
        if location is not None:
3857
3834
            try:
3858
3835
                mergeable = bundle.read_mergeable_from_url(location,
3919
3896
    def _do_preview(self, merger):
3920
3897
        from bzrlib.diff import show_diff_trees
3921
3898
        result_tree = self._get_preview(merger)
 
3899
        path_encoding = osutils.get_diff_header_encoding()
3922
3900
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3923
 
                        old_label='', new_label='')
 
3901
                        old_label='', new_label='',
 
3902
                        path_encoding=path_encoding)
3924
3903
 
3925
3904
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3926
3905
        merger.change_reporter = change_reporter
4114
4093
        if merge_type is None:
4115
4094
            merge_type = _mod_merge.Merge3Merger
4116
4095
        tree, file_list = tree_files(file_list)
4117
 
        tree.lock_write()
4118
 
        self.add_cleanup(tree.unlock)
 
4096
        self.add_cleanup(tree.lock_write().unlock)
4119
4097
        parents = tree.get_parent_ids()
4120
4098
        if len(parents) != 2:
4121
4099
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4231
4209
    def run(self, revision=None, no_backup=False, file_list=None,
4232
4210
            forget_merges=None):
4233
4211
        tree, file_list = tree_files(file_list)
4234
 
        tree.lock_tree_write()
4235
 
        self.add_cleanup(tree.unlock)
 
4212
        self.add_cleanup(tree.lock_tree_write().unlock)
4236
4213
        if forget_merges:
4237
4214
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4238
4215
        else:
4327
4304
    _see_also = ['merge', 'pull']
4328
4305
    takes_args = ['other_branch?']
4329
4306
    takes_options = [
 
4307
        'directory',
4330
4308
        Option('reverse', 'Reverse the order of revisions.'),
4331
4309
        Option('mine-only',
4332
4310
               'Display changes in the local branch only.'),
4354
4332
            theirs_only=False,
4355
4333
            log_format=None, long=False, short=False, line=False,
4356
4334
            show_ids=False, verbose=False, this=False, other=False,
4357
 
            include_merges=False, revision=None, my_revision=None):
 
4335
            include_merges=False, revision=None, my_revision=None,
 
4336
            directory=u'.'):
4358
4337
        from bzrlib.missing import find_unmerged, iter_log_revisions
4359
4338
        def message(s):
4360
4339
            if not is_quiet():
4373
4352
        elif theirs_only:
4374
4353
            restrict = 'remote'
4375
4354
 
4376
 
        local_branch = Branch.open_containing(u".")[0]
4377
 
        local_branch.lock_read()
4378
 
        self.add_cleanup(local_branch.unlock)
 
4355
        local_branch = Branch.open_containing(directory)[0]
 
4356
        self.add_cleanup(local_branch.lock_read().unlock)
4379
4357
 
4380
4358
        parent = local_branch.get_parent()
4381
4359
        if other_branch is None:
4392
4370
        if remote_branch.base == local_branch.base:
4393
4371
            remote_branch = local_branch
4394
4372
        else:
4395
 
            remote_branch.lock_read()
4396
 
            self.add_cleanup(remote_branch.unlock)
 
4373
            self.add_cleanup(remote_branch.lock_read().unlock)
4397
4374
 
4398
4375
        local_revid_range = _revision_range_to_revid_range(
4399
4376
            _get_revision_range(my_revision, local_branch,
4454
4431
            message("Branches are up to date.\n")
4455
4432
        self.cleanup_now()
4456
4433
        if not status_code and parent is None and other_branch is not None:
4457
 
            local_branch.lock_write()
4458
 
            self.add_cleanup(local_branch.unlock)
 
4434
            self.add_cleanup(local_branch.lock_write().unlock)
4459
4435
            # handle race conditions - a parent might be set while we run.
4460
4436
            if local_branch.get_parent() is None:
4461
4437
                local_branch.set_parent(remote_branch.base)
4561
4537
            b = Branch.open_containing(branch)[0]
4562
4538
        else:
4563
4539
            b = Branch.open(branch)
4564
 
        b.lock_read()
4565
 
        self.add_cleanup(b.unlock)
 
4540
        self.add_cleanup(b.lock_read().unlock)
4566
4541
        if revision is None:
4567
4542
            rev_id = b.last_revision()
4568
4543
        else:
4603
4578
        wt, branch, relpath = \
4604
4579
            _open_directory_or_containing_tree_or_branch(filename, directory)
4605
4580
        if wt is not None:
4606
 
            wt.lock_read()
4607
 
            self.add_cleanup(wt.unlock)
 
4581
            self.add_cleanup(wt.lock_read().unlock)
4608
4582
        else:
4609
 
            branch.lock_read()
4610
 
            self.add_cleanup(branch.unlock)
 
4583
            self.add_cleanup(branch.lock_read().unlock)
4611
4584
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4612
 
        tree.lock_read()
4613
 
        self.add_cleanup(tree.unlock)
 
4585
        self.add_cleanup(tree.lock_read().unlock)
4614
4586
        if wt is not None:
4615
4587
            file_id = wt.path2id(relpath)
4616
4588
        else:
4642
4614
        if revision_id_list is None and revision is None:
4643
4615
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4644
4616
        b = WorkingTree.open_containing(directory)[0].branch
4645
 
        b.lock_write()
4646
 
        self.add_cleanup(b.unlock)
 
4617
        self.add_cleanup(b.lock_write().unlock)
4647
4618
        return self._run(b, revision_id_list, revision)
4648
4619
 
4649
4620
    def _run(self, b, revision_id_list, revision):
4799
4770
            b = control.open_branch()
4800
4771
 
4801
4772
        if tree is not None:
4802
 
            tree.lock_write()
4803
 
            self.add_cleanup(tree.unlock)
 
4773
            self.add_cleanup(tree.lock_write().unlock)
4804
4774
        else:
4805
 
            b.lock_write()
4806
 
            self.add_cleanup(b.unlock)
 
4775
            self.add_cleanup(b.lock_write().unlock)
4807
4776
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4808
4777
 
4809
4778
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
5060
5029
    _see_also = ['send']
5061
5030
 
5062
5031
    takes_options = [
 
5032
        'directory',
5063
5033
        RegistryOption.from_kwargs('patch-type',
5064
5034
            'The type of patch to include in the directive.',
5065
5035
            title='Patch type',
5078
5048
    encoding_type = 'exact'
5079
5049
 
5080
5050
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5081
 
            sign=False, revision=None, mail_to=None, message=None):
 
5051
            sign=False, revision=None, mail_to=None, message=None,
 
5052
            directory=u'.'):
5082
5053
        from bzrlib.revision import ensure_null, NULL_REVISION
5083
5054
        include_patch, include_bundle = {
5084
5055
            'plain': (False, False),
5085
5056
            'diff': (True, False),
5086
5057
            'bundle': (True, True),
5087
5058
            }[patch_type]
5088
 
        branch = Branch.open('.')
 
5059
        branch = Branch.open(directory)
5089
5060
        stored_submit_branch = branch.get_submit_branch()
5090
5061
        if submit_branch is None:
5091
5062
            submit_branch = stored_submit_branch
5176
5147
    given, in which case it is sent to a file.
5177
5148
 
5178
5149
    Mail is sent using your preferred mail program.  This should be transparent
5179
 
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
 
5150
    on Windows (it uses MAPI).  On Unix, it requires the xdg-email utility.
5180
5151
    If the preferred client can't be found (or used), your editor will be used.
5181
5152
 
5182
5153
    To use a specific mail program, set the mail_client configuration option.
5368
5339
            revision=None,
5369
5340
            ):
5370
5341
        branch, relpath = Branch.open_containing(directory)
5371
 
        branch.lock_write()
5372
 
        self.add_cleanup(branch.unlock)
 
5342
        self.add_cleanup(branch.lock_write().unlock)
5373
5343
        if delete:
5374
5344
            if tag_name is None:
5375
5345
                raise errors.BzrCommandError("No tag specified to delete.")
5427
5397
        if not tags:
5428
5398
            return
5429
5399
 
5430
 
        branch.lock_read()
5431
 
        self.add_cleanup(branch.unlock)
 
5400
        self.add_cleanup(branch.lock_read().unlock)
5432
5401
        if revision:
5433
5402
            graph = branch.repository.get_graph()
5434
5403
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5581
5550
    """
5582
5551
 
5583
5552
    takes_args = ['to_location?']
5584
 
    takes_options = [Option('force',
 
5553
    takes_options = ['directory',
 
5554
                     Option('force',
5585
5555
                        help='Switch even if local commits will be lost.'),
5586
5556
                     'revision',
5587
5557
                     Option('create-branch', short_name='b',
5590
5560
                    ]
5591
5561
 
5592
5562
    def run(self, to_location=None, force=False, create_branch=False,
5593
 
            revision=None):
 
5563
            revision=None, directory=u'.'):
5594
5564
        from bzrlib import switch
5595
 
        tree_location = '.'
 
5565
        tree_location = directory
5596
5566
        revision = _get_one_revision('switch', revision)
5597
5567
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5598
5568
        if to_location is None:
5599
5569
            if revision is None:
5600
5570
                raise errors.BzrCommandError('You must supply either a'
5601
5571
                                             ' revision or a location')
5602
 
            to_location = '.'
 
5572
            to_location = tree_location
5603
5573
        try:
5604
5574
            branch = control_dir.open_branch()
5605
5575
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5880
5850
    takes_args = ['file*']
5881
5851
 
5882
5852
    takes_options = [
 
5853
        'directory',
5883
5854
        'revision',
5884
5855
        Option('all', help='Shelve all changes.'),
5885
5856
        'message',
5894
5865
    _see_also = ['unshelve']
5895
5866
 
5896
5867
    def run(self, revision=None, all=False, file_list=None, message=None,
5897
 
            writer=None, list=False, destroy=False):
 
5868
            writer=None, list=False, destroy=False, directory=u'.'):
5898
5869
        if list:
5899
5870
            return self.run_for_list()
5900
5871
        from bzrlib.shelf_ui import Shelver
5902
5873
            writer = bzrlib.option.diff_writer_registry.get()
5903
5874
        try:
5904
5875
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5905
 
                file_list, message, destroy=destroy)
 
5876
                file_list, message, destroy=destroy, directory=directory)
5906
5877
            try:
5907
5878
                shelver.run()
5908
5879
            finally:
5912
5883
 
5913
5884
    def run_for_list(self):
5914
5885
        tree = WorkingTree.open_containing('.')[0]
5915
 
        tree.lock_read()
5916
 
        self.add_cleanup(tree.unlock)
 
5886
        self.add_cleanup(tree.lock_read().unlock)
5917
5887
        manager = tree.get_shelf_manager()
5918
5888
        shelves = manager.active_shelves()
5919
5889
        if len(shelves) == 0:
5937
5907
 
5938
5908
    takes_args = ['shelf_id?']
5939
5909
    takes_options = [
 
5910
        'directory',
5940
5911
        RegistryOption.from_kwargs(
5941
5912
            'action', help="The action to perform.",
5942
5913
            enum_switch=False, value_switches=True,
5950
5921
    ]
5951
5922
    _see_also = ['shelve']
5952
5923
 
5953
 
    def run(self, shelf_id=None, action='apply'):
 
5924
    def run(self, shelf_id=None, action='apply', directory=u'.'):
5954
5925
        from bzrlib.shelf_ui import Unshelver
5955
 
        unshelver = Unshelver.from_args(shelf_id, action)
 
5926
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5956
5927
        try:
5957
5928
            unshelver.run()
5958
5929
        finally: