/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
25
import sys
25
26
import time
74
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
75
76
 
76
77
 
77
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
79
79
    apply_view=True):
80
 
    return internal_tree_files(file_list, default_branch, canonicalize,
81
 
        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]))
82
86
 
83
87
 
84
88
def tree_files_for_add(file_list):
148
152
 
149
153
# XXX: Bad function name; should possibly also be a class method of
150
154
# WorkingTree rather than a function.
151
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
152
155
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
153
156
    apply_view=True):
154
157
    """Convert command-line paths to a WorkingTree and relative paths.
155
158
 
156
 
    Deprecated: use WorkingTree.open_containing_paths instead.
157
 
 
158
159
    This is typically used for command-line processors that take one or
159
160
    more filenames, and infer the workingtree that contains them.
160
161
 
170
171
 
171
172
    :return: workingtree, [relative_paths]
172
173
    """
173
 
    return WorkingTree.open_containing_paths(
174
 
        file_list, default_directory='.',
175
 
        canonicalize=True,
176
 
        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
177
221
 
178
222
 
179
223
def _get_view_info_for_change_reporter(tree):
188
232
    return view_info
189
233
 
190
234
 
191
 
def _open_directory_or_containing_tree_or_branch(filename, directory):
192
 
    """Open the tree or branch containing the specified file, unless
193
 
    the --directory option is used to specify a different branch."""
194
 
    if directory is not None:
195
 
        return (None, Branch.open(directory), filename)
196
 
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
197
 
 
198
 
 
199
235
# TODO: Make sure no commands unconditionally use the working directory as a
200
236
# branch.  If a filename argument is used, the first of them should be used to
201
237
# specify the branch.  (Perhaps this can be factored out into some kind of
279
315
            raise errors.BzrCommandError('bzr status --revision takes exactly'
280
316
                                         ' one or two revision specifiers')
281
317
 
282
 
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
 
318
        tree, relfile_list = tree_files(file_list)
283
319
        # Avoid asking for specific files when that is not needed.
284
320
        if relfile_list == ['']:
285
321
            relfile_list = None
304
340
 
305
341
    hidden = True
306
342
    takes_args = ['revision_id?']
307
 
    takes_options = ['directory', 'revision']
 
343
    takes_options = ['revision']
308
344
    # cat-revision is more for frontends so should be exact
309
345
    encoding = 'strict'
310
346
 
317
353
        self.outf.write(revtext.decode('utf-8'))
318
354
 
319
355
    @display_command
320
 
    def run(self, revision_id=None, revision=None, directory=u'.'):
 
356
    def run(self, revision_id=None, revision=None):
321
357
        if revision_id is not None and revision is not None:
322
358
            raise errors.BzrCommandError('You can only supply one of'
323
359
                                         ' revision_id or --revision')
324
360
        if revision_id is None and revision is None:
325
361
            raise errors.BzrCommandError('You must supply either'
326
362
                                         ' --revision or a revision_id')
327
 
        b = WorkingTree.open_containing(directory)[0].branch
 
363
        b = WorkingTree.open_containing(u'.')[0].branch
328
364
 
329
365
        revisions = b.repository.revisions
330
366
        if revisions is None:
447
483
    takes_options = [
448
484
        Option('force',
449
485
               help='Remove the working tree even if it has '
450
 
                    'uncommitted or shelved changes.'),
 
486
                    'uncommitted changes.'),
451
487
        ]
452
488
 
453
489
    def run(self, location_list, force=False):
467
503
            if not force:
468
504
                if (working.has_changes()):
469
505
                    raise errors.UncommittedChanges(working)
470
 
                if working.get_shelf_manager().last_shelf() is not None:
471
 
                    raise errors.ShelvedChanges(working)
472
506
 
473
507
            if working.user_url != working.branch.user_url:
474
508
                raise errors.BzrCommandError("You cannot remove the working tree"
494
528
        if tree:
495
529
            try:
496
530
                wt = WorkingTree.open_containing(location)[0]
497
 
                self.add_cleanup(wt.lock_read().unlock)
 
531
                wt.lock_read()
498
532
            except (errors.NoWorkingTree, errors.NotLocalUrl):
499
533
                raise errors.NoWorkingTree(location)
 
534
            self.add_cleanup(wt.unlock)
500
535
            revid = wt.last_revision()
501
536
            try:
502
537
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
505
540
            revno = ".".join(str(n) for n in revno_t)
506
541
        else:
507
542
            b = Branch.open_containing(location)[0]
508
 
            self.add_cleanup(b.lock_read().unlock)
 
543
            b.lock_read()
 
544
            self.add_cleanup(b.unlock)
509
545
            revno = b.revno()
510
546
        self.cleanup_now()
511
547
        self.outf.write(str(revno) + '\n')
518
554
    takes_args = ['revision_info*']
519
555
    takes_options = [
520
556
        'revision',
521
 
        custom_help('directory',
 
557
        Option('directory',
522
558
            help='Branch to examine, '
523
 
                 '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
            ),
524
563
        Option('tree', help='Show revno of working tree'),
525
564
        ]
526
565
 
531
570
        try:
532
571
            wt = WorkingTree.open_containing(directory)[0]
533
572
            b = wt.branch
534
 
            self.add_cleanup(wt.lock_read().unlock)
 
573
            wt.lock_read()
 
574
            self.add_cleanup(wt.unlock)
535
575
        except (errors.NoWorkingTree, errors.NotLocalUrl):
536
576
            wt = None
537
577
            b = Branch.open_containing(directory)[0]
538
 
            self.add_cleanup(b.lock_read().unlock)
 
578
            b.lock_read()
 
579
            self.add_cleanup(b.unlock)
539
580
        revision_ids = []
540
581
        if revision is not None:
541
582
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
640
681
                should_print=(not is_quiet()))
641
682
 
642
683
        if base_tree:
643
 
            self.add_cleanup(base_tree.lock_read().unlock)
 
684
            base_tree.lock_read()
 
685
            self.add_cleanup(base_tree.unlock)
644
686
        tree, file_list = tree_files_for_add(file_list)
645
687
        added, ignored = tree.smart_add(file_list, not
646
688
            no_recurse, action=action, save=not dry_run)
717
759
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
718
760
 
719
761
        revision = _get_one_revision('inventory', revision)
720
 
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
721
 
        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)
722
765
        if revision is not None:
723
766
            tree = revision.as_tree(work_tree.branch)
724
767
 
725
768
            extra_trees = [work_tree]
726
 
            self.add_cleanup(tree.lock_read().unlock)
 
769
            tree.lock_read()
 
770
            self.add_cleanup(tree.unlock)
727
771
        else:
728
772
            tree = work_tree
729
773
            extra_trees = []
788
832
            names_list = []
789
833
        if len(names_list) < 2:
790
834
            raise errors.BzrCommandError("missing file argument")
791
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
792
 
        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)
793
838
        self._run(tree, names_list, rel_names, after)
794
839
 
795
840
    def run_auto(self, names_list, after, dry_run):
799
844
        if after:
800
845
            raise errors.BzrCommandError('--after cannot be specified with'
801
846
                                         ' --auto.')
802
 
        work_tree, file_list = WorkingTree.open_containing_paths(
803
 
            names_list, default_directory='.')
804
 
        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)
805
850
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
806
851
 
807
852
    def _run(self, tree, names_list, rel_names, after):
915
960
    takes_options = ['remember', 'overwrite', 'revision',
916
961
        custom_help('verbose',
917
962
            help='Show logs of pulled revisions.'),
918
 
        custom_help('directory',
 
963
        Option('directory',
919
964
            help='Branch to pull into, '
920
 
                 '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
            ),
921
969
        Option('local',
922
970
            help="Perform a local pull in a bound "
923
971
                 "branch.  Local pulls are not applied to "
938
986
        try:
939
987
            tree_to = WorkingTree.open_containing(directory)[0]
940
988
            branch_to = tree_to.branch
941
 
            self.add_cleanup(tree_to.lock_write().unlock)
 
989
            tree_to.lock_write()
 
990
            self.add_cleanup(tree_to.unlock)
942
991
        except errors.NoWorkingTree:
943
992
            tree_to = None
944
993
            branch_to = Branch.open_containing(directory)[0]
945
 
            self.add_cleanup(branch_to.lock_write().unlock)
 
994
            branch_to.lock_write()
 
995
            self.add_cleanup(branch_to.unlock)
946
996
 
947
997
        if local and not branch_to.get_bound_location():
948
998
            raise errors.LocalRequiresBoundBranch()
979
1029
        else:
980
1030
            branch_from = Branch.open(location,
981
1031
                possible_transports=possible_transports)
982
 
            self.add_cleanup(branch_from.lock_read().unlock)
 
1032
            branch_from.lock_read()
 
1033
            self.add_cleanup(branch_from.unlock)
983
1034
 
984
1035
            if branch_to.get_parent() is None or remember:
985
1036
                branch_to.set_parent(branch_from.base)
1037
1088
        Option('create-prefix',
1038
1089
               help='Create the path leading up to the branch '
1039
1090
                    'if it does not already exist.'),
1040
 
        custom_help('directory',
 
1091
        Option('directory',
1041
1092
            help='Branch to push from, '
1042
 
                 '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
            ),
1043
1097
        Option('use-existing-dir',
1044
1098
               help='By default push will fail if the target'
1045
1099
                    ' directory exists, but does not already'
1134
1188
 
1135
1189
    _see_also = ['checkout']
1136
1190
    takes_args = ['from_location', 'to_location?']
1137
 
    takes_options = ['revision',
1138
 
        Option('hardlink', help='Hard-link working tree files where possible.'),
1139
 
        Option('files-from', type=str,
1140
 
               help="Get file contents from this tree."),
 
1191
    takes_options = ['revision', Option('hardlink',
 
1192
        help='Hard-link working tree files where possible.'),
1141
1193
        Option('no-tree',
1142
1194
            help="Create a branch without a working-tree."),
1143
1195
        Option('switch',
1161
1213
 
1162
1214
    def run(self, from_location, to_location=None, revision=None,
1163
1215
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1164
 
            use_existing_dir=False, switch=False, bind=False,
1165
 
            files_from=None):
 
1216
            use_existing_dir=False, switch=False, bind=False):
1166
1217
        from bzrlib import switch as _mod_switch
1167
1218
        from bzrlib.tag import _merge_tags_if_possible
1168
1219
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1169
1220
            from_location)
1170
 
        if not (hardlink or files_from):
1171
 
            # accelerator_tree is usually slower because you have to read N
1172
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1173
 
            # explicitly request it
1174
 
            accelerator_tree = None
1175
 
        if files_from is not None and files_from != from_location:
1176
 
            accelerator_tree = WorkingTree.open(files_from)
1177
1221
        revision = _get_one_revision('branch', revision)
1178
 
        self.add_cleanup(br_from.lock_read().unlock)
 
1222
        br_from.lock_read()
 
1223
        self.add_cleanup(br_from.unlock)
1179
1224
        if revision is not None:
1180
1225
            revision_id = revision.as_revision_id(br_from)
1181
1226
        else:
1286
1331
            to_location = branch_location
1287
1332
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1288
1333
            branch_location)
1289
 
        if not (hardlink or files_from):
1290
 
            # accelerator_tree is usually slower because you have to read N
1291
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1292
 
            # explicitly request it
1293
 
            accelerator_tree = None
1294
1334
        revision = _get_one_revision('checkout', revision)
1295
 
        if files_from is not None and files_from != branch_location:
 
1335
        if files_from is not None:
1296
1336
            accelerator_tree = WorkingTree.open(files_from)
1297
1337
        if revision is not None:
1298
1338
            revision_id = revision.as_revision_id(source)
1326
1366
    @display_command
1327
1367
    def run(self, dir=u'.'):
1328
1368
        tree = WorkingTree.open_containing(dir)[0]
1329
 
        self.add_cleanup(tree.lock_read().unlock)
 
1369
        tree.lock_read()
 
1370
        self.add_cleanup(tree.unlock)
1330
1371
        new_inv = tree.inventory
1331
1372
        old_tree = tree.basis_tree()
1332
 
        self.add_cleanup(old_tree.lock_read().unlock)
 
1373
        old_tree.lock_read()
 
1374
        self.add_cleanup(old_tree.unlock)
1333
1375
        old_inv = old_tree.inventory
1334
1376
        renames = []
1335
1377
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1373
1415
        master = branch.get_master_branch(
1374
1416
            possible_transports=possible_transports)
1375
1417
        if master is not None:
 
1418
            tree.lock_write()
1376
1419
            branch_location = master.base
1377
 
            tree.lock_write()
1378
1420
        else:
 
1421
            tree.lock_tree_write()
1379
1422
            branch_location = tree.branch.base
1380
 
            tree.lock_tree_write()
1381
1423
        self.add_cleanup(tree.unlock)
1382
1424
        # get rid of the final '/' and be ready for display
1383
1425
        branch_location = urlutils.unescape_for_display(
1477
1519
class cmd_remove(Command):
1478
1520
    __doc__ = """Remove files or directories.
1479
1521
 
1480
 
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1481
 
    delete them if they can easily be recovered using revert otherwise they
1482
 
    will be backed up (adding an extention of the form .~#~). If no options or
1483
 
    parameters are given Bazaar will scan for files that are being tracked by
1484
 
    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.
1485
1526
    """
1486
1527
    takes_args = ['file*']
1487
1528
    takes_options = ['verbose',
1489
1530
        RegistryOption.from_kwargs('file-deletion-strategy',
1490
1531
            'The file deletion mode to be used.',
1491
1532
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1492
 
            safe='Backup changed files (default).',
 
1533
            safe='Only delete files if they can be'
 
1534
                 ' safely recovered (default).',
1493
1535
            keep='Delete from bzr but leave the working copy.',
1494
1536
            force='Delete all the specified files, even if they can not be '
1495
1537
                'recovered and even if they are non-empty directories.')]
1498
1540
 
1499
1541
    def run(self, file_list, verbose=False, new=False,
1500
1542
        file_deletion_strategy='safe'):
1501
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
1543
        tree, file_list = tree_files(file_list)
1502
1544
 
1503
1545
        if file_list is not None:
1504
1546
            file_list = [f for f in file_list]
1505
1547
 
1506
 
        self.add_cleanup(tree.lock_write().unlock)
 
1548
        tree.lock_write()
 
1549
        self.add_cleanup(tree.unlock)
1507
1550
        # Heuristics should probably all move into tree.remove_smart or
1508
1551
        # some such?
1509
1552
        if new:
1592
1635
 
1593
1636
    _see_also = ['check']
1594
1637
    takes_args = ['branch?']
1595
 
    takes_options = [
1596
 
        Option('canonicalize-chks',
1597
 
               help='Make sure CHKs are in canonical form (repairs '
1598
 
                    'bug 522637).',
1599
 
               hidden=True),
1600
 
        ]
1601
1638
 
1602
 
    def run(self, branch=".", canonicalize_chks=False):
 
1639
    def run(self, branch="."):
1603
1640
        from bzrlib.reconcile import reconcile
1604
1641
        dir = bzrdir.BzrDir.open(branch)
1605
 
        reconcile(dir, canonicalize_chks=canonicalize_chks)
 
1642
        reconcile(dir)
1606
1643
 
1607
1644
 
1608
1645
class cmd_revision_history(Command):
1884
1921
        Same as 'bzr diff' but prefix paths with old/ and new/::
1885
1922
 
1886
1923
            bzr diff --prefix old/:new/
1887
 
            
1888
 
        Show the differences using a custom diff program with options::
1889
 
        
1890
 
            bzr diff --using /usr/bin/diff --diff-options -wu
1891
1924
    """
1892
1925
    _see_also = ['status']
1893
1926
    takes_args = ['file*']
1952
1985
         old_branch, new_branch,
1953
1986
         specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1954
1987
            file_list, revision, old, new, self.add_cleanup, apply_view=True)
1955
 
        # GNU diff on Windows uses ANSI encoding for filenames
1956
 
        path_encoding = osutils.get_diff_header_encoding()
1957
1988
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1958
1989
                               specific_files=specific_files,
1959
1990
                               external_diff_options=diff_options,
1960
1991
                               old_label=old_label, new_label=new_label,
1961
 
                               extra_trees=extra_trees,
1962
 
                               path_encoding=path_encoding,
1963
 
                               using=using,
 
1992
                               extra_trees=extra_trees, using=using,
1964
1993
                               format_cls=format)
1965
1994
 
1966
1995
 
1974
2003
    # level of effort but possibly much less IO.  (Or possibly not,
1975
2004
    # if the directories are very large...)
1976
2005
    _see_also = ['status', 'ls']
1977
 
    takes_options = ['directory', 'show-ids']
 
2006
    takes_options = ['show-ids']
1978
2007
 
1979
2008
    @display_command
1980
 
    def run(self, show_ids=False, directory=u'.'):
1981
 
        tree = WorkingTree.open_containing(directory)[0]
1982
 
        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)
1983
2013
        old = tree.basis_tree()
1984
 
        self.add_cleanup(old.lock_read().unlock)
 
2014
        old.lock_read()
 
2015
        self.add_cleanup(old.unlock)
1985
2016
        for path, ie in old.inventory.iter_entries():
1986
2017
            if not tree.has_id(ie.file_id):
1987
2018
                self.outf.write(path)
1997
2028
 
1998
2029
    hidden = True
1999
2030
    _see_also = ['status', 'ls']
2000
 
    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
            ]
2001
2036
 
2002
2037
    @display_command
2003
 
    def run(self, null=False, directory=u'.'):
2004
 
        tree = WorkingTree.open_containing(directory)[0]
 
2038
    def run(self, null=False):
 
2039
        tree = WorkingTree.open_containing(u'.')[0]
2005
2040
        td = tree.changes_from(tree.basis_tree())
2006
2041
        for path, id, kind, text_modified, meta_modified in td.modified:
2007
2042
            if null:
2016
2051
 
2017
2052
    hidden = True
2018
2053
    _see_also = ['status', 'ls']
2019
 
    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
            ]
2020
2059
 
2021
2060
    @display_command
2022
 
    def run(self, null=False, directory=u'.'):
2023
 
        wt = WorkingTree.open_containing(directory)[0]
2024
 
        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)
2025
2065
        basis = wt.basis_tree()
2026
 
        self.add_cleanup(basis.lock_read().unlock)
 
2066
        basis.lock_read()
 
2067
        self.add_cleanup(basis.unlock)
2027
2068
        basis_inv = basis.inventory
2028
2069
        inv = wt.inventory
2029
2070
        for file_id in inv:
2032
2073
            if inv.is_root(file_id) and len(basis_inv) == 0:
2033
2074
                continue
2034
2075
            path = inv.id2path(file_id)
2035
 
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
 
2076
            if not os.access(osutils.abspath(path), os.F_OK):
2036
2077
                continue
2037
2078
            if null:
2038
2079
                self.outf.write(path + '\0')
2238
2279
                   help='Show just the specified revision.'
2239
2280
                   ' See also "help revisionspec".'),
2240
2281
            'log-format',
2241
 
            RegistryOption('authors',
2242
 
                'What names to list as authors - first, all or committer.',
2243
 
                title='Authors',
2244
 
                lazy_registry=('bzrlib.log', 'author_list_registry'),
2245
 
            ),
2246
2282
            Option('levels',
2247
2283
                   short_name='n',
2248
2284
                   help='Number of levels to display - 0 for all, 1 for flat.',
2283
2319
            limit=None,
2284
2320
            show_diff=False,
2285
2321
            include_merges=False,
2286
 
            authors=None,
2287
2322
            exclude_common_ancestry=False,
2288
2323
            ):
2289
2324
        from bzrlib.log import (
2317
2352
        if file_list:
2318
2353
            # find the file ids to log and check for directory filtering
2319
2354
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2320
 
                revision, file_list, self.add_cleanup)
 
2355
                revision, file_list)
 
2356
            self.add_cleanup(b.unlock)
2321
2357
            for relpath, file_id, kind in file_info_list:
2322
2358
                if file_id is None:
2323
2359
                    raise errors.BzrCommandError(
2341
2377
                location = '.'
2342
2378
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2343
2379
            b = dir.open_branch()
2344
 
            self.add_cleanup(b.lock_read().unlock)
 
2380
            b.lock_read()
 
2381
            self.add_cleanup(b.unlock)
2345
2382
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2346
2383
 
2347
2384
        # Decide on the type of delta & diff filtering to use
2367
2404
                        show_timezone=timezone,
2368
2405
                        delta_format=get_verbosity_level(),
2369
2406
                        levels=levels,
2370
 
                        show_advice=levels is None,
2371
 
                        author_list_handler=authors)
 
2407
                        show_advice=levels is None)
2372
2408
 
2373
2409
        # Choose the algorithm for doing the logging. It's annoying
2374
2410
        # having multiple code paths like this but necessary until
2472
2508
        tree, relpath = WorkingTree.open_containing(filename)
2473
2509
        file_id = tree.path2id(relpath)
2474
2510
        b = tree.branch
2475
 
        self.add_cleanup(b.lock_read().unlock)
 
2511
        b.lock_read()
 
2512
        self.add_cleanup(b.unlock)
2476
2513
        touching_revs = log.find_touching_revisions(b, file_id)
2477
2514
        for revno, revision_id, what in touching_revs:
2478
2515
            self.outf.write("%6d %s\n" % (revno, what))
2491
2528
                   help='Recurse into subdirectories.'),
2492
2529
            Option('from-root',
2493
2530
                   help='Print paths relative to the root of the branch.'),
2494
 
            Option('unknown', short_name='u',
2495
 
                help='Print unknown files.'),
 
2531
            Option('unknown', help='Print unknown files.'),
2496
2532
            Option('versioned', help='Print versioned files.',
2497
2533
                   short_name='V'),
2498
 
            Option('ignored', short_name='i',
2499
 
                help='Print ignored files.'),
2500
 
            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',
2501
2539
                   help='List entries of a particular kind: file, directory, symlink.',
2502
2540
                   type=unicode),
2503
 
            'null',
2504
2541
            'show-ids',
2505
 
            'directory',
2506
2542
            ]
2507
2543
    @display_command
2508
2544
    def run(self, revision=None, verbose=False,
2509
2545
            recursive=False, from_root=False,
2510
2546
            unknown=False, versioned=False, ignored=False,
2511
 
            null=False, kind=None, show_ids=False, path=None, directory=None):
 
2547
            null=False, kind=None, show_ids=False, path=None):
2512
2548
 
2513
2549
        if kind and kind not in ('file', 'directory', 'symlink'):
2514
2550
            raise errors.BzrCommandError('invalid kind specified')
2526
2562
                raise errors.BzrCommandError('cannot specify both --from-root'
2527
2563
                                             ' and PATH')
2528
2564
            fs_path = path
2529
 
        tree, branch, relpath = \
2530
 
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
 
2565
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2566
            fs_path)
2531
2567
 
2532
2568
        # Calculate the prefix to use
2533
2569
        prefix = None
2548
2584
                view_str = views.view_display_str(view_files)
2549
2585
                note("Ignoring files outside view. View is %s" % view_str)
2550
2586
 
2551
 
        self.add_cleanup(tree.lock_read().unlock)
 
2587
        tree.lock_read()
 
2588
        self.add_cleanup(tree.unlock)
2552
2589
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2553
2590
            from_dir=relpath, recursive=recursive):
2554
2591
            # Apply additional masking
2601
2638
 
2602
2639
    hidden = True
2603
2640
    _see_also = ['ls']
2604
 
    takes_options = ['directory']
2605
2641
 
2606
2642
    @display_command
2607
 
    def run(self, directory=u'.'):
2608
 
        for f in WorkingTree.open_containing(directory)[0].unknowns():
 
2643
    def run(self):
 
2644
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
2609
2645
            self.outf.write(osutils.quotefn(f) + '\n')
2610
2646
 
2611
2647
 
2676
2712
 
2677
2713
    _see_also = ['status', 'ignored', 'patterns']
2678
2714
    takes_args = ['name_pattern*']
2679
 
    takes_options = ['directory',
 
2715
    takes_options = [
2680
2716
        Option('default-rules',
2681
2717
               help='Display the default ignore rules that bzr uses.')
2682
2718
        ]
2683
2719
 
2684
 
    def run(self, name_pattern_list=None, default_rules=None,
2685
 
            directory=u'.'):
 
2720
    def run(self, name_pattern_list=None, default_rules=None):
2686
2721
        from bzrlib import ignores
2687
2722
        if default_rules is not None:
2688
2723
            # dump the default rules and exit
2694
2729
                "NAME_PATTERN or --default-rules.")
2695
2730
        name_pattern_list = [globbing.normalize_pattern(p)
2696
2731
                             for p in name_pattern_list]
2697
 
        bad_patterns = ''
2698
 
        for p in name_pattern_list:
2699
 
            if not globbing.Globster.is_pattern_valid(p):
2700
 
                bad_patterns += ('\n  %s' % p)
2701
 
        if bad_patterns:
2702
 
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2703
 
            ui.ui_factory.show_error(msg)
2704
 
            raise errors.InvalidPattern('')
2705
2732
        for name_pattern in name_pattern_list:
2706
2733
            if (name_pattern[0] == '/' or
2707
2734
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2708
2735
                raise errors.BzrCommandError(
2709
2736
                    "NAME_PATTERN should not be an absolute path")
2710
 
        tree, relpath = WorkingTree.open_containing(directory)
 
2737
        tree, relpath = WorkingTree.open_containing(u'.')
2711
2738
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2712
2739
        ignored = globbing.Globster(name_pattern_list)
2713
2740
        matches = []
2714
 
        self.add_cleanup(tree.lock_read().unlock)
 
2741
        tree.lock_read()
2715
2742
        for entry in tree.list_files():
2716
2743
            id = entry[3]
2717
2744
            if id is not None:
2718
2745
                filename = entry[0]
2719
2746
                if ignored.match(filename):
2720
2747
                    matches.append(filename)
 
2748
        tree.unlock()
2721
2749
        if len(matches) > 0:
2722
2750
            self.outf.write("Warning: the following files are version controlled and"
2723
2751
                  " match your ignore pattern:\n%s"
2738
2766
 
2739
2767
    encoding_type = 'replace'
2740
2768
    _see_also = ['ignore', 'ls']
2741
 
    takes_options = ['directory']
2742
2769
 
2743
2770
    @display_command
2744
 
    def run(self, directory=u'.'):
2745
 
        tree = WorkingTree.open_containing(directory)[0]
2746
 
        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)
2747
2775
        for path, file_class, kind, file_id, entry in tree.list_files():
2748
2776
            if file_class != 'I':
2749
2777
                continue
2760
2788
    """
2761
2789
    hidden = True
2762
2790
    takes_args = ['revno']
2763
 
    takes_options = ['directory']
2764
2791
 
2765
2792
    @display_command
2766
 
    def run(self, revno, directory=u'.'):
 
2793
    def run(self, revno):
2767
2794
        try:
2768
2795
            revno = int(revno)
2769
2796
        except ValueError:
2770
2797
            raise errors.BzrCommandError("not a valid revision-number: %r"
2771
2798
                                         % revno)
2772
 
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
 
2799
        revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2773
2800
        self.outf.write("%s\n" % revid)
2774
2801
 
2775
2802
 
2802
2829
      =================       =========================
2803
2830
    """
2804
2831
    takes_args = ['dest', 'branch_or_subdir?']
2805
 
    takes_options = ['directory',
 
2832
    takes_options = [
2806
2833
        Option('format',
2807
2834
               help="Type of file to export to.",
2808
2835
               type=unicode),
2817
2844
                    'revision in which it was changed.'),
2818
2845
        ]
2819
2846
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2820
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
2847
        root=None, filters=False, per_file_timestamps=False):
2821
2848
        from bzrlib.export import export
2822
2849
 
2823
2850
        if branch_or_subdir is None:
2824
 
            tree = WorkingTree.open_containing(directory)[0]
 
2851
            tree = WorkingTree.open_containing(u'.')[0]
2825
2852
            b = tree.branch
2826
2853
            subdir = None
2827
2854
        else:
2846
2873
    """
2847
2874
 
2848
2875
    _see_also = ['ls']
2849
 
    takes_options = ['directory',
 
2876
    takes_options = [
2850
2877
        Option('name-from-revision', help='The path name in the old tree.'),
2851
2878
        Option('filters', help='Apply content filters to display the '
2852
2879
                'convenience form.'),
2857
2884
 
2858
2885
    @display_command
2859
2886
    def run(self, filename, revision=None, name_from_revision=False,
2860
 
            filters=False, directory=None):
 
2887
            filters=False):
2861
2888
        if revision is not None and len(revision) != 1:
2862
2889
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2863
2890
                                         " one revision specifier")
2864
2891
        tree, branch, relpath = \
2865
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
2866
 
        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)
2867
2895
        return self._run(tree, branch, relpath, filename, revision,
2868
2896
                         name_from_revision, filters)
2869
2897
 
2872
2900
        if tree is None:
2873
2901
            tree = b.basis_tree()
2874
2902
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2875
 
        self.add_cleanup(rev_tree.lock_read().unlock)
 
2903
        rev_tree.lock_read()
 
2904
        self.add_cleanup(rev_tree.unlock)
2876
2905
 
2877
2906
        old_file_id = rev_tree.path2id(relpath)
2878
2907
 
3099
3128
 
3100
3129
        properties = {}
3101
3130
 
3102
 
        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
 
3131
        tree, selected_list = tree_files(selected_list)
3103
3132
        if selected_list == ['']:
3104
3133
            # workaround - commit of root of tree should be exactly the same
3105
3134
            # as just default commit in that tree, and succeed even though
3140
3169
        def get_message(commit_obj):
3141
3170
            """Callback to get commit message"""
3142
3171
            if file:
3143
 
                f = open(file)
3144
 
                try:
3145
 
                    my_message = f.read().decode(osutils.get_user_encoding())
3146
 
                finally:
3147
 
                    f.close()
 
3172
                my_message = codecs.open(
 
3173
                    file, 'rt', osutils.get_user_encoding()).read()
3148
3174
            elif message is not None:
3149
3175
                my_message = message
3150
3176
            else:
3179
3205
                        reporter=None, verbose=verbose, revprops=properties,
3180
3206
                        authors=author, timestamp=commit_stamp,
3181
3207
                        timezone=offset,
3182
 
                        exclude=tree.safe_relpath_files(exclude))
 
3208
                        exclude=safe_relpath_files(tree, exclude))
3183
3209
        except PointlessCommit:
3184
3210
            raise errors.BzrCommandError("No changes to commit."
3185
3211
                              " Use --unchanged to commit anyhow.")
3304
3330
 
3305
3331
            bzr whoami "Frank Chu <fchu@example.com>"
3306
3332
    """
3307
 
    takes_options = [ 'directory',
3308
 
                      Option('email',
 
3333
    takes_options = [ Option('email',
3309
3334
                             help='Display email address only.'),
3310
3335
                      Option('branch',
3311
3336
                             help='Set identity for the current branch instead of '
3315
3340
    encoding_type = 'replace'
3316
3341
 
3317
3342
    @display_command
3318
 
    def run(self, email=False, branch=False, name=None, directory=None):
 
3343
    def run(self, email=False, branch=False, name=None):
3319
3344
        if name is None:
3320
 
            if directory is None:
3321
 
                # use branch if we're inside one; otherwise global config
3322
 
                try:
3323
 
                    c = Branch.open_containing(u'.')[0].get_config()
3324
 
                except errors.NotBranchError:
3325
 
                    c = config.GlobalConfig()
3326
 
            else:
3327
 
                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()
3328
3350
            if email:
3329
3351
                self.outf.write(c.user_email() + '\n')
3330
3352
            else:
3340
3362
 
3341
3363
        # use global config unless --branch given
3342
3364
        if branch:
3343
 
            if directory is None:
3344
 
                c = Branch.open_containing(u'.')[0].get_config()
3345
 
            else:
3346
 
                c = Branch.open(directory).get_config()
 
3365
            c = Branch.open_containing('.')[0].get_config()
3347
3366
        else:
3348
3367
            c = config.GlobalConfig()
3349
3368
        c.set_user_option('email', name)
3361
3380
 
3362
3381
    _see_also = ['info']
3363
3382
    takes_args = ['nickname?']
3364
 
    takes_options = ['directory']
3365
 
    def run(self, nickname=None, directory=u'.'):
3366
 
        branch = Branch.open_containing(directory)[0]
 
3383
    def run(self, nickname=None):
 
3384
        branch = Branch.open_containing(u'.')[0]
3367
3385
        if nickname is None:
3368
3386
            self.printme(branch)
3369
3387
        else:
3519
3537
                                 'throughout the test suite.',
3520
3538
                            type=get_transport_type),
3521
3539
                     Option('benchmark',
3522
 
                            help='Run the benchmarks rather than selftests.',
3523
 
                            hidden=True),
 
3540
                            help='Run the benchmarks rather than selftests.'),
3524
3541
                     Option('lsprof-timed',
3525
3542
                            help='Generate lsprof output for benchmarked'
3526
3543
                                 ' sections of code.'),
3527
3544
                     Option('lsprof-tests',
3528
3545
                            help='Generate lsprof output for each test.'),
 
3546
                     Option('cache-dir', type=str,
 
3547
                            help='Cache intermediate benchmark output in this '
 
3548
                                 'directory.'),
3529
3549
                     Option('first',
3530
3550
                            help='Run all tests, but run specified tests first.',
3531
3551
                            short_name='f',
3565
3585
 
3566
3586
    def run(self, testspecs_list=None, verbose=False, one=False,
3567
3587
            transport=None, benchmark=None,
3568
 
            lsprof_timed=None,
 
3588
            lsprof_timed=None, cache_dir=None,
3569
3589
            first=False, list_only=False,
3570
3590
            randomize=None, exclude=None, strict=False,
3571
3591
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3572
3592
            parallel=None, lsprof_tests=False):
3573
3593
        from bzrlib.tests import selftest
 
3594
        import bzrlib.benchmarks as benchmarks
 
3595
        from bzrlib.benchmarks import tree_creator
3574
3596
 
3575
3597
        # Make deprecation warnings visible, unless -Werror is set
3576
3598
        symbol_versioning.activate_deprecation_warnings(override=False)
3577
3599
 
 
3600
        if cache_dir is not None:
 
3601
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3578
3602
        if testspecs_list is not None:
3579
3603
            pattern = '|'.join(testspecs_list)
3580
3604
        else:
3588
3612
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3589
3613
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3590
3614
            # stdout, which would corrupt the subunit stream. 
3591
 
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3592
 
            # following code can be deleted when it's sufficiently deployed
3593
 
            # -- vila/mgz 20100514
3594
 
            if (sys.platform == "win32"
3595
 
                and getattr(sys.stdout, 'fileno', None) is not None):
 
3615
            if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3596
3616
                import msvcrt
3597
3617
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3598
3618
        if parallel:
3599
3619
            self.additional_selftest_args.setdefault(
3600
3620
                'suite_decorators', []).append(parallel)
3601
3621
        if benchmark:
3602
 
            raise errors.BzrCommandError(
3603
 
                "--benchmark is no longer supported from bzr 2.2; "
3604
 
                "use bzr-usertest instead")
3605
 
        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
3606
3631
        selftest_kwargs = {"verbose": verbose,
3607
3632
                          "pattern": pattern,
3608
3633
                          "stop_on_failure": one,
3610
3635
                          "test_suite_factory": test_suite_factory,
3611
3636
                          "lsprof_timed": lsprof_timed,
3612
3637
                          "lsprof_tests": lsprof_tests,
 
3638
                          "bench_history": benchfile,
3613
3639
                          "matching_tests_first": first,
3614
3640
                          "list_only": list_only,
3615
3641
                          "random_seed": randomize,
3664
3690
 
3665
3691
        branch1 = Branch.open_containing(branch)[0]
3666
3692
        branch2 = Branch.open_containing(other)[0]
3667
 
        self.add_cleanup(branch1.lock_read().unlock)
3668
 
        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)
3669
3697
        last1 = ensure_null(branch1.last_revision())
3670
3698
        last2 = ensure_null(branch2.last_revision())
3671
3699
 
3765
3793
                ' completely merged into the source, pull from the'
3766
3794
                ' source rather than merging.  When this happens,'
3767
3795
                ' you do not need to commit the result.'),
3768
 
        custom_help('directory',
 
3796
        Option('directory',
3769
3797
               help='Branch to merge into, '
3770
 
                    '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
               ),
3771
3802
        Option('preview', help='Instead of merging, show a diff of the'
3772
3803
               ' merge.'),
3773
3804
        Option('interactive', help='Select changes interactively.',
3806
3837
            unversioned_filter=tree.is_ignored, view_info=view_info)
3807
3838
        pb = ui.ui_factory.nested_progress_bar()
3808
3839
        self.add_cleanup(pb.finished)
3809
 
        self.add_cleanup(tree.lock_write().unlock)
 
3840
        tree.lock_write()
 
3841
        self.add_cleanup(tree.unlock)
3810
3842
        if location is not None:
3811
3843
            try:
3812
3844
                mergeable = bundle.read_mergeable_from_url(location,
3873
3905
    def _do_preview(self, merger):
3874
3906
        from bzrlib.diff import show_diff_trees
3875
3907
        result_tree = self._get_preview(merger)
3876
 
        path_encoding = osutils.get_diff_header_encoding()
3877
3908
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3878
 
                        old_label='', new_label='',
3879
 
                        path_encoding=path_encoding)
 
3909
                        old_label='', new_label='')
3880
3910
 
3881
3911
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3882
3912
        merger.change_reporter = change_reporter
4069
4099
        from bzrlib.conflicts import restore
4070
4100
        if merge_type is None:
4071
4101
            merge_type = _mod_merge.Merge3Merger
4072
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4073
 
        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)
4074
4105
        parents = tree.get_parent_ids()
4075
4106
        if len(parents) != 2:
4076
4107
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4185
4216
 
4186
4217
    def run(self, revision=None, no_backup=False, file_list=None,
4187
4218
            forget_merges=None):
4188
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4189
 
        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)
4190
4222
        if forget_merges:
4191
4223
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4192
4224
        else:
4281
4313
    _see_also = ['merge', 'pull']
4282
4314
    takes_args = ['other_branch?']
4283
4315
    takes_options = [
4284
 
        'directory',
4285
4316
        Option('reverse', 'Reverse the order of revisions.'),
4286
4317
        Option('mine-only',
4287
4318
               'Display changes in the local branch only.'),
4309
4340
            theirs_only=False,
4310
4341
            log_format=None, long=False, short=False, line=False,
4311
4342
            show_ids=False, verbose=False, this=False, other=False,
4312
 
            include_merges=False, revision=None, my_revision=None,
4313
 
            directory=u'.'):
 
4343
            include_merges=False, revision=None, my_revision=None):
4314
4344
        from bzrlib.missing import find_unmerged, iter_log_revisions
4315
4345
        def message(s):
4316
4346
            if not is_quiet():
4329
4359
        elif theirs_only:
4330
4360
            restrict = 'remote'
4331
4361
 
4332
 
        local_branch = Branch.open_containing(directory)[0]
4333
 
        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)
4334
4365
 
4335
4366
        parent = local_branch.get_parent()
4336
4367
        if other_branch is None:
4347
4378
        if remote_branch.base == local_branch.base:
4348
4379
            remote_branch = local_branch
4349
4380
        else:
4350
 
            self.add_cleanup(remote_branch.lock_read().unlock)
 
4381
            remote_branch.lock_read()
 
4382
            self.add_cleanup(remote_branch.unlock)
4351
4383
 
4352
4384
        local_revid_range = _revision_range_to_revid_range(
4353
4385
            _get_revision_range(my_revision, local_branch,
4408
4440
            message("Branches are up to date.\n")
4409
4441
        self.cleanup_now()
4410
4442
        if not status_code and parent is None and other_branch is not None:
4411
 
            self.add_cleanup(local_branch.lock_write().unlock)
 
4443
            local_branch.lock_write()
 
4444
            self.add_cleanup(local_branch.unlock)
4412
4445
            # handle race conditions - a parent might be set while we run.
4413
4446
            if local_branch.get_parent() is None:
4414
4447
                local_branch.set_parent(remote_branch.base)
4514
4547
            b = Branch.open_containing(branch)[0]
4515
4548
        else:
4516
4549
            b = Branch.open(branch)
4517
 
        self.add_cleanup(b.lock_read().unlock)
 
4550
        b.lock_read()
 
4551
        self.add_cleanup(b.unlock)
4518
4552
        if revision is None:
4519
4553
            rev_id = b.last_revision()
4520
4554
        else:
4544
4578
                     Option('long', help='Show commit date in annotations.'),
4545
4579
                     'revision',
4546
4580
                     'show-ids',
4547
 
                     'directory',
4548
4581
                     ]
4549
4582
    encoding_type = 'exact'
4550
4583
 
4551
4584
    @display_command
4552
4585
    def run(self, filename, all=False, long=False, revision=None,
4553
 
            show_ids=False, directory=None):
 
4586
            show_ids=False):
4554
4587
        from bzrlib.annotate import annotate_file, annotate_file_tree
4555
4588
        wt, branch, relpath = \
4556
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
 
4589
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4557
4590
        if wt is not None:
4558
 
            self.add_cleanup(wt.lock_read().unlock)
 
4591
            wt.lock_read()
 
4592
            self.add_cleanup(wt.unlock)
4559
4593
        else:
4560
 
            self.add_cleanup(branch.lock_read().unlock)
 
4594
            branch.lock_read()
 
4595
            self.add_cleanup(branch.unlock)
4561
4596
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4562
 
        self.add_cleanup(tree.lock_read().unlock)
 
4597
        tree.lock_read()
 
4598
        self.add_cleanup(tree.unlock)
4563
4599
        if wt is not None:
4564
4600
            file_id = wt.path2id(relpath)
4565
4601
        else:
4583
4619
 
4584
4620
    hidden = True # is this right ?
4585
4621
    takes_args = ['revision_id*']
4586
 
    takes_options = ['directory', 'revision']
 
4622
    takes_options = ['revision']
4587
4623
 
4588
 
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
 
4624
    def run(self, revision_id_list=None, revision=None):
4589
4625
        if revision_id_list is not None and revision is not None:
4590
4626
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4591
4627
        if revision_id_list is None and revision is None:
4592
4628
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4593
 
        b = WorkingTree.open_containing(directory)[0].branch
4594
 
        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)
4595
4632
        return self._run(b, revision_id_list, revision)
4596
4633
 
4597
4634
    def _run(self, b, revision_id_list, revision):
4656
4693
 
4657
4694
    _see_also = ['checkouts', 'unbind']
4658
4695
    takes_args = ['location?']
4659
 
    takes_options = ['directory']
 
4696
    takes_options = []
4660
4697
 
4661
 
    def run(self, location=None, directory=u'.'):
4662
 
        b, relpath = Branch.open_containing(directory)
 
4698
    def run(self, location=None):
 
4699
        b, relpath = Branch.open_containing(u'.')
4663
4700
        if location is None:
4664
4701
            try:
4665
4702
                location = b.get_old_bound_location()
4692
4729
 
4693
4730
    _see_also = ['checkouts', 'bind']
4694
4731
    takes_args = []
4695
 
    takes_options = ['directory']
 
4732
    takes_options = []
4696
4733
 
4697
 
    def run(self, directory=u'.'):
4698
 
        b, relpath = Branch.open_containing(directory)
 
4734
    def run(self):
 
4735
        b, relpath = Branch.open_containing(u'.')
4699
4736
        if not b.unbind():
4700
4737
            raise errors.BzrCommandError('Local branch is not bound')
4701
4738
 
4747
4784
            b = control.open_branch()
4748
4785
 
4749
4786
        if tree is not None:
4750
 
            self.add_cleanup(tree.lock_write().unlock)
 
4787
            tree.lock_write()
 
4788
            self.add_cleanup(tree.unlock)
4751
4789
        else:
4752
 
            self.add_cleanup(b.lock_write().unlock)
 
4790
            b.lock_write()
 
4791
            self.add_cleanup(b.unlock)
4753
4792
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4754
4793
 
4755
4794
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4863
4902
                    'result in a dynamically allocated port.  The default port '
4864
4903
                    'depends on the protocol.',
4865
4904
               type=str),
4866
 
        custom_help('directory',
4867
 
               help='Serve contents of this directory.'),
 
4905
        Option('directory',
 
4906
               help='Serve contents of this directory.',
 
4907
               type=unicode),
4868
4908
        Option('allow-writes',
4869
4909
               help='By default the server is a readonly server.  Supplying '
4870
4910
                    '--allow-writes enables write access to the contents of '
4897
4937
 
4898
4938
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
4899
4939
            protocol=None):
4900
 
        from bzrlib import transport
 
4940
        from bzrlib.transport import get_transport, transport_server_registry
4901
4941
        if directory is None:
4902
4942
            directory = os.getcwd()
4903
4943
        if protocol is None:
4904
 
            protocol = transport.transport_server_registry.get()
 
4944
            protocol = transport_server_registry.get()
4905
4945
        host, port = self.get_host_and_port(port)
4906
4946
        url = urlutils.local_path_to_url(directory)
4907
4947
        if not allow_writes:
4908
4948
            url = 'readonly+' + url
4909
 
        t = transport.get_transport(url)
4910
 
        protocol(t, host, port, inet)
 
4949
        transport = get_transport(url)
 
4950
        protocol(transport, host, port, inet)
4911
4951
 
4912
4952
 
4913
4953
class cmd_join(Command):
5006
5046
    _see_also = ['send']
5007
5047
 
5008
5048
    takes_options = [
5009
 
        'directory',
5010
5049
        RegistryOption.from_kwargs('patch-type',
5011
5050
            'The type of patch to include in the directive.',
5012
5051
            title='Patch type',
5025
5064
    encoding_type = 'exact'
5026
5065
 
5027
5066
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5028
 
            sign=False, revision=None, mail_to=None, message=None,
5029
 
            directory=u'.'):
 
5067
            sign=False, revision=None, mail_to=None, message=None):
5030
5068
        from bzrlib.revision import ensure_null, NULL_REVISION
5031
5069
        include_patch, include_bundle = {
5032
5070
            'plain': (False, False),
5033
5071
            'diff': (True, False),
5034
5072
            'bundle': (True, True),
5035
5073
            }[patch_type]
5036
 
        branch = Branch.open(directory)
 
5074
        branch = Branch.open('.')
5037
5075
        stored_submit_branch = branch.get_submit_branch()
5038
5076
        if submit_branch is None:
5039
5077
            submit_branch = stored_submit_branch
5124
5162
    given, in which case it is sent to a file.
5125
5163
 
5126
5164
    Mail is sent using your preferred mail program.  This should be transparent
5127
 
    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.
5128
5166
    If the preferred client can't be found (or used), your editor will be used.
5129
5167
 
5130
5168
    To use a specific mail program, set the mail_client configuration option.
5301
5339
        Option('delete',
5302
5340
            help='Delete this tag rather than placing it.',
5303
5341
            ),
5304
 
        custom_help('directory',
5305
 
            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
            ),
5306
5347
        Option('force',
5307
5348
            help='Replace existing tags.',
5308
5349
            ),
5316
5357
            revision=None,
5317
5358
            ):
5318
5359
        branch, relpath = Branch.open_containing(directory)
5319
 
        self.add_cleanup(branch.lock_write().unlock)
 
5360
        branch.lock_write()
 
5361
        self.add_cleanup(branch.unlock)
5320
5362
        if delete:
5321
5363
            if tag_name is None:
5322
5364
                raise errors.BzrCommandError("No tag specified to delete.")
5350
5392
 
5351
5393
    _see_also = ['tag']
5352
5394
    takes_options = [
5353
 
        custom_help('directory',
5354
 
            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
            ),
5355
5400
        RegistryOption.from_kwargs('sort',
5356
5401
            'Sort tags by different criteria.', title='Sorting',
5357
5402
            alpha='Sort tags lexicographically (default).',
5374
5419
        if not tags:
5375
5420
            return
5376
5421
 
5377
 
        self.add_cleanup(branch.lock_read().unlock)
 
5422
        branch.lock_read()
 
5423
        self.add_cleanup(branch.unlock)
5378
5424
        if revision:
5379
5425
            graph = branch.repository.get_graph()
5380
5426
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5527
5573
    """
5528
5574
 
5529
5575
    takes_args = ['to_location?']
5530
 
    takes_options = ['directory',
5531
 
                     Option('force',
 
5576
    takes_options = [Option('force',
5532
5577
                        help='Switch even if local commits will be lost.'),
5533
5578
                     'revision',
5534
5579
                     Option('create-branch', short_name='b',
5537
5582
                    ]
5538
5583
 
5539
5584
    def run(self, to_location=None, force=False, create_branch=False,
5540
 
            revision=None, directory=u'.'):
 
5585
            revision=None):
5541
5586
        from bzrlib import switch
5542
 
        tree_location = directory
 
5587
        tree_location = '.'
5543
5588
        revision = _get_one_revision('switch', revision)
5544
5589
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5545
5590
        if to_location is None:
5546
5591
            if revision is None:
5547
5592
                raise errors.BzrCommandError('You must supply either a'
5548
5593
                                             ' revision or a location')
5549
 
            to_location = tree_location
 
5594
            to_location = '.'
5550
5595
        try:
5551
5596
            branch = control_dir.open_branch()
5552
5597
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5687
5732
            name=None,
5688
5733
            switch=None,
5689
5734
            ):
5690
 
        tree, file_list = WorkingTree.open_containing_paths(file_list,
5691
 
            apply_view=False)
 
5735
        tree, file_list = tree_files(file_list, apply_view=False)
5692
5736
        current_view, view_dict = tree.views.get_view_info()
5693
5737
        if name is None:
5694
5738
            name = current_view
5828
5872
    takes_args = ['file*']
5829
5873
 
5830
5874
    takes_options = [
5831
 
        'directory',
5832
5875
        'revision',
5833
5876
        Option('all', help='Shelve all changes.'),
5834
5877
        'message',
5843
5886
    _see_also = ['unshelve']
5844
5887
 
5845
5888
    def run(self, revision=None, all=False, file_list=None, message=None,
5846
 
            writer=None, list=False, destroy=False, directory=u'.'):
 
5889
            writer=None, list=False, destroy=False):
5847
5890
        if list:
5848
5891
            return self.run_for_list()
5849
5892
        from bzrlib.shelf_ui import Shelver
5851
5894
            writer = bzrlib.option.diff_writer_registry.get()
5852
5895
        try:
5853
5896
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5854
 
                file_list, message, destroy=destroy, directory=directory)
 
5897
                file_list, message, destroy=destroy)
5855
5898
            try:
5856
5899
                shelver.run()
5857
5900
            finally:
5861
5904
 
5862
5905
    def run_for_list(self):
5863
5906
        tree = WorkingTree.open_containing('.')[0]
5864
 
        self.add_cleanup(tree.lock_read().unlock)
 
5907
        tree.lock_read()
 
5908
        self.add_cleanup(tree.unlock)
5865
5909
        manager = tree.get_shelf_manager()
5866
5910
        shelves = manager.active_shelves()
5867
5911
        if len(shelves) == 0:
5885
5929
 
5886
5930
    takes_args = ['shelf_id?']
5887
5931
    takes_options = [
5888
 
        'directory',
5889
5932
        RegistryOption.from_kwargs(
5890
5933
            'action', help="The action to perform.",
5891
5934
            enum_switch=False, value_switches=True,
5899
5942
    ]
5900
5943
    _see_also = ['shelve']
5901
5944
 
5902
 
    def run(self, shelf_id=None, action='apply', directory=u'.'):
 
5945
    def run(self, shelf_id=None, action='apply'):
5903
5946
        from bzrlib.shelf_ui import Unshelver
5904
 
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
 
5947
        unshelver = Unshelver.from_args(shelf_id, action)
5905
5948
        try:
5906
5949
            unshelver.run()
5907
5950
        finally:
5923
5966
 
5924
5967
    To check what clean-tree will do, use --dry-run.
5925
5968
    """
5926
 
    takes_options = ['directory',
5927
 
                     Option('ignored', help='Delete all ignored files.'),
 
5969
    takes_options = [Option('ignored', help='Delete all ignored files.'),
5928
5970
                     Option('detritus', help='Delete conflict files, merge'
5929
5971
                            ' backups, and failed selftest dirs.'),
5930
5972
                     Option('unknown',
5933
5975
                            ' deleting them.'),
5934
5976
                     Option('force', help='Do not prompt before deleting.')]
5935
5977
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5936
 
            force=False, directory=u'.'):
 
5978
            force=False):
5937
5979
        from bzrlib.clean_tree import clean_tree
5938
5980
        if not (unknown or ignored or detritus):
5939
5981
            unknown = True
5940
5982
        if dry_run:
5941
5983
            force = True
5942
 
        clean_tree(directory, unknown=unknown, ignored=ignored,
5943
 
                   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)
5944
5986
 
5945
5987
 
5946
5988
class cmd_reference(Command):