/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
32
33
    bzrdir,
33
34
    directory_service,
34
35
    delta,
35
 
    config as _mod_config,
 
36
    config,
36
37
    errors,
37
38
    globbing,
38
39
    hooks,
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 = _mod_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:
3333
3355
 
3334
3356
        # display a warning if an email address isn't included in the given name.
3335
3357
        try:
3336
 
            _mod_config.extract_email_address(name)
 
3358
            config.extract_email_address(name)
3337
3359
        except errors.NoEmailInUsername, e:
3338
3360
            warning('"%s" does not seem to contain an email address.  '
3339
3361
                    'This is allowed, but not recommended.', name)
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
 
            c = _mod_config.GlobalConfig()
 
3367
            c = config.GlobalConfig()
3349
3368
        c.set_user_option('email', name)
3350
3369
 
3351
3370
 
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:
3418
3436
                'bzr alias --remove expects an alias to remove.')
3419
3437
        # If alias is not found, print something like:
3420
3438
        # unalias: foo: not found
3421
 
        c = _mod_config.GlobalConfig()
 
3439
        c = config.GlobalConfig()
3422
3440
        c.unset_alias(alias_name)
3423
3441
 
3424
3442
    @display_command
3425
3443
    def print_aliases(self):
3426
3444
        """Print out the defined aliases in a similar format to bash."""
3427
 
        aliases = _mod_config.GlobalConfig().get_aliases()
 
3445
        aliases = config.GlobalConfig().get_aliases()
3428
3446
        for key, value in sorted(aliases.iteritems()):
3429
3447
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3430
3448
 
3440
3458
 
3441
3459
    def set_alias(self, alias_name, alias_command):
3442
3460
        """Save the alias in the global config."""
3443
 
        c = _mod_config.GlobalConfig()
 
3461
        c = config.GlobalConfig()
3444
3462
        c.set_alias(alias_name, alias_command)
3445
3463
 
3446
3464
 
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
 
        from bzrlib import tests
3574
 
 
 
3593
        from bzrlib.tests import selftest
 
3594
        import bzrlib.benchmarks as benchmarks
 
3595
        from bzrlib.benchmarks import tree_creator
 
3596
 
 
3597
        # Make deprecation warnings visible, unless -Werror is set
 
3598
        symbol_versioning.activate_deprecation_warnings(override=False)
 
3599
 
 
3600
        if cache_dir is not None:
 
3601
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3575
3602
        if testspecs_list is not None:
3576
3603
            pattern = '|'.join(testspecs_list)
3577
3604
        else:
3585
3612
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3586
3613
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3587
3614
            # stdout, which would corrupt the subunit stream. 
3588
 
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3589
 
            # following code can be deleted when it's sufficiently deployed
3590
 
            # -- vila/mgz 20100514
3591
 
            if (sys.platform == "win32"
3592
 
                and getattr(sys.stdout, 'fileno', None) is not None):
 
3615
            if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3593
3616
                import msvcrt
3594
3617
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3595
3618
        if parallel:
3596
3619
            self.additional_selftest_args.setdefault(
3597
3620
                'suite_decorators', []).append(parallel)
3598
3621
        if benchmark:
3599
 
            raise errors.BzrCommandError(
3600
 
                "--benchmark is no longer supported from bzr 2.2; "
3601
 
                "use bzr-usertest instead")
3602
 
        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
3603
3631
        selftest_kwargs = {"verbose": verbose,
3604
3632
                          "pattern": pattern,
3605
3633
                          "stop_on_failure": one,
3607
3635
                          "test_suite_factory": test_suite_factory,
3608
3636
                          "lsprof_timed": lsprof_timed,
3609
3637
                          "lsprof_tests": lsprof_tests,
 
3638
                          "bench_history": benchfile,
3610
3639
                          "matching_tests_first": first,
3611
3640
                          "list_only": list_only,
3612
3641
                          "random_seed": randomize,
3617
3646
                          "starting_with": starting_with
3618
3647
                          }
3619
3648
        selftest_kwargs.update(self.additional_selftest_args)
3620
 
 
3621
 
        # Make deprecation warnings visible, unless -Werror is set
3622
 
        cleanup = symbol_versioning.activate_deprecation_warnings(
3623
 
            override=False)
3624
 
        try:
3625
 
            result = tests.selftest(**selftest_kwargs)
3626
 
        finally:
3627
 
            cleanup()
 
3649
        result = selftest(**selftest_kwargs)
3628
3650
        return int(not result)
3629
3651
 
3630
3652
 
3668
3690
 
3669
3691
        branch1 = Branch.open_containing(branch)[0]
3670
3692
        branch2 = Branch.open_containing(other)[0]
3671
 
        self.add_cleanup(branch1.lock_read().unlock)
3672
 
        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)
3673
3697
        last1 = ensure_null(branch1.last_revision())
3674
3698
        last2 = ensure_null(branch2.last_revision())
3675
3699
 
3769
3793
                ' completely merged into the source, pull from the'
3770
3794
                ' source rather than merging.  When this happens,'
3771
3795
                ' you do not need to commit the result.'),
3772
 
        custom_help('directory',
 
3796
        Option('directory',
3773
3797
               help='Branch to merge into, '
3774
 
                    '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
               ),
3775
3802
        Option('preview', help='Instead of merging, show a diff of the'
3776
3803
               ' merge.'),
3777
3804
        Option('interactive', help='Select changes interactively.',
3810
3837
            unversioned_filter=tree.is_ignored, view_info=view_info)
3811
3838
        pb = ui.ui_factory.nested_progress_bar()
3812
3839
        self.add_cleanup(pb.finished)
3813
 
        self.add_cleanup(tree.lock_write().unlock)
 
3840
        tree.lock_write()
 
3841
        self.add_cleanup(tree.unlock)
3814
3842
        if location is not None:
3815
3843
            try:
3816
3844
                mergeable = bundle.read_mergeable_from_url(location,
3877
3905
    def _do_preview(self, merger):
3878
3906
        from bzrlib.diff import show_diff_trees
3879
3907
        result_tree = self._get_preview(merger)
3880
 
        path_encoding = osutils.get_diff_header_encoding()
3881
3908
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3882
 
                        old_label='', new_label='',
3883
 
                        path_encoding=path_encoding)
 
3909
                        old_label='', new_label='')
3884
3910
 
3885
3911
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3886
3912
        merger.change_reporter = change_reporter
4073
4099
        from bzrlib.conflicts import restore
4074
4100
        if merge_type is None:
4075
4101
            merge_type = _mod_merge.Merge3Merger
4076
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4077
 
        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)
4078
4105
        parents = tree.get_parent_ids()
4079
4106
        if len(parents) != 2:
4080
4107
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4189
4216
 
4190
4217
    def run(self, revision=None, no_backup=False, file_list=None,
4191
4218
            forget_merges=None):
4192
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4193
 
        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)
4194
4222
        if forget_merges:
4195
4223
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4196
4224
        else:
4285
4313
    _see_also = ['merge', 'pull']
4286
4314
    takes_args = ['other_branch?']
4287
4315
    takes_options = [
4288
 
        'directory',
4289
4316
        Option('reverse', 'Reverse the order of revisions.'),
4290
4317
        Option('mine-only',
4291
4318
               'Display changes in the local branch only.'),
4313
4340
            theirs_only=False,
4314
4341
            log_format=None, long=False, short=False, line=False,
4315
4342
            show_ids=False, verbose=False, this=False, other=False,
4316
 
            include_merges=False, revision=None, my_revision=None,
4317
 
            directory=u'.'):
 
4343
            include_merges=False, revision=None, my_revision=None):
4318
4344
        from bzrlib.missing import find_unmerged, iter_log_revisions
4319
4345
        def message(s):
4320
4346
            if not is_quiet():
4333
4359
        elif theirs_only:
4334
4360
            restrict = 'remote'
4335
4361
 
4336
 
        local_branch = Branch.open_containing(directory)[0]
4337
 
        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)
4338
4365
 
4339
4366
        parent = local_branch.get_parent()
4340
4367
        if other_branch is None:
4351
4378
        if remote_branch.base == local_branch.base:
4352
4379
            remote_branch = local_branch
4353
4380
        else:
4354
 
            self.add_cleanup(remote_branch.lock_read().unlock)
 
4381
            remote_branch.lock_read()
 
4382
            self.add_cleanup(remote_branch.unlock)
4355
4383
 
4356
4384
        local_revid_range = _revision_range_to_revid_range(
4357
4385
            _get_revision_range(my_revision, local_branch,
4412
4440
            message("Branches are up to date.\n")
4413
4441
        self.cleanup_now()
4414
4442
        if not status_code and parent is None and other_branch is not None:
4415
 
            self.add_cleanup(local_branch.lock_write().unlock)
 
4443
            local_branch.lock_write()
 
4444
            self.add_cleanup(local_branch.unlock)
4416
4445
            # handle race conditions - a parent might be set while we run.
4417
4446
            if local_branch.get_parent() is None:
4418
4447
                local_branch.set_parent(remote_branch.base)
4518
4547
            b = Branch.open_containing(branch)[0]
4519
4548
        else:
4520
4549
            b = Branch.open(branch)
4521
 
        self.add_cleanup(b.lock_read().unlock)
 
4550
        b.lock_read()
 
4551
        self.add_cleanup(b.unlock)
4522
4552
        if revision is None:
4523
4553
            rev_id = b.last_revision()
4524
4554
        else:
4548
4578
                     Option('long', help='Show commit date in annotations.'),
4549
4579
                     'revision',
4550
4580
                     'show-ids',
4551
 
                     'directory',
4552
4581
                     ]
4553
4582
    encoding_type = 'exact'
4554
4583
 
4555
4584
    @display_command
4556
4585
    def run(self, filename, all=False, long=False, revision=None,
4557
 
            show_ids=False, directory=None):
 
4586
            show_ids=False):
4558
4587
        from bzrlib.annotate import annotate_file, annotate_file_tree
4559
4588
        wt, branch, relpath = \
4560
 
            _open_directory_or_containing_tree_or_branch(filename, directory)
 
4589
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4561
4590
        if wt is not None:
4562
 
            self.add_cleanup(wt.lock_read().unlock)
 
4591
            wt.lock_read()
 
4592
            self.add_cleanup(wt.unlock)
4563
4593
        else:
4564
 
            self.add_cleanup(branch.lock_read().unlock)
 
4594
            branch.lock_read()
 
4595
            self.add_cleanup(branch.unlock)
4565
4596
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4566
 
        self.add_cleanup(tree.lock_read().unlock)
 
4597
        tree.lock_read()
 
4598
        self.add_cleanup(tree.unlock)
4567
4599
        if wt is not None:
4568
4600
            file_id = wt.path2id(relpath)
4569
4601
        else:
4587
4619
 
4588
4620
    hidden = True # is this right ?
4589
4621
    takes_args = ['revision_id*']
4590
 
    takes_options = ['directory', 'revision']
 
4622
    takes_options = ['revision']
4591
4623
 
4592
 
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
 
4624
    def run(self, revision_id_list=None, revision=None):
4593
4625
        if revision_id_list is not None and revision is not None:
4594
4626
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4595
4627
        if revision_id_list is None and revision is None:
4596
4628
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4597
 
        b = WorkingTree.open_containing(directory)[0].branch
4598
 
        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)
4599
4632
        return self._run(b, revision_id_list, revision)
4600
4633
 
4601
4634
    def _run(self, b, revision_id_list, revision):
4660
4693
 
4661
4694
    _see_also = ['checkouts', 'unbind']
4662
4695
    takes_args = ['location?']
4663
 
    takes_options = ['directory']
 
4696
    takes_options = []
4664
4697
 
4665
 
    def run(self, location=None, directory=u'.'):
4666
 
        b, relpath = Branch.open_containing(directory)
 
4698
    def run(self, location=None):
 
4699
        b, relpath = Branch.open_containing(u'.')
4667
4700
        if location is None:
4668
4701
            try:
4669
4702
                location = b.get_old_bound_location()
4696
4729
 
4697
4730
    _see_also = ['checkouts', 'bind']
4698
4731
    takes_args = []
4699
 
    takes_options = ['directory']
 
4732
    takes_options = []
4700
4733
 
4701
 
    def run(self, directory=u'.'):
4702
 
        b, relpath = Branch.open_containing(directory)
 
4734
    def run(self):
 
4735
        b, relpath = Branch.open_containing(u'.')
4703
4736
        if not b.unbind():
4704
4737
            raise errors.BzrCommandError('Local branch is not bound')
4705
4738
 
4751
4784
            b = control.open_branch()
4752
4785
 
4753
4786
        if tree is not None:
4754
 
            self.add_cleanup(tree.lock_write().unlock)
 
4787
            tree.lock_write()
 
4788
            self.add_cleanup(tree.unlock)
4755
4789
        else:
4756
 
            self.add_cleanup(b.lock_write().unlock)
 
4790
            b.lock_write()
 
4791
            self.add_cleanup(b.unlock)
4757
4792
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4758
4793
 
4759
4794
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4811
4846
 
4812
4847
 
4813
4848
class cmd_break_lock(Command):
4814
 
    __doc__ = """Break a dead lock.
4815
 
 
4816
 
    This command breaks a lock on a repository, branch, working directory or
4817
 
    config file.
 
4849
    __doc__ = """Break a dead lock on a repository, branch or working directory.
4818
4850
 
4819
4851
    CAUTION: Locks should only be broken when you are sure that the process
4820
4852
    holding the lock has been stopped.
4825
4857
    :Examples:
4826
4858
        bzr break-lock
4827
4859
        bzr break-lock bzr+ssh://example.com/bzr/foo
4828
 
        bzr break-lock --conf ~/.bazaar
4829
4860
    """
4830
 
 
4831
4861
    takes_args = ['location?']
4832
 
    takes_options = [
4833
 
        Option('config',
4834
 
               help='LOCATION is the directory where the config lock is.'),
4835
 
        ]
4836
4862
 
4837
 
    def run(self, location=None, config=False):
 
4863
    def run(self, location=None, show=False):
4838
4864
        if location is None:
4839
4865
            location = u'.'
4840
 
        if config:
4841
 
            conf = _mod_config.LockableConfig(file_name=location)
4842
 
            conf.break_lock()
4843
 
        else:
4844
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
4845
 
            try:
4846
 
                control.break_lock()
4847
 
            except NotImplementedError:
4848
 
                pass
 
4866
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
4867
        try:
 
4868
            control.break_lock()
 
4869
        except NotImplementedError:
 
4870
            pass
4849
4871
 
4850
4872
 
4851
4873
class cmd_wait_until_signalled(Command):
4880
4902
                    'result in a dynamically allocated port.  The default port '
4881
4903
                    'depends on the protocol.',
4882
4904
               type=str),
4883
 
        custom_help('directory',
4884
 
               help='Serve contents of this directory.'),
 
4905
        Option('directory',
 
4906
               help='Serve contents of this directory.',
 
4907
               type=unicode),
4885
4908
        Option('allow-writes',
4886
4909
               help='By default the server is a readonly server.  Supplying '
4887
4910
                    '--allow-writes enables write access to the contents of '
4914
4937
 
4915
4938
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
4916
4939
            protocol=None):
4917
 
        from bzrlib import transport
 
4940
        from bzrlib.transport import get_transport, transport_server_registry
4918
4941
        if directory is None:
4919
4942
            directory = os.getcwd()
4920
4943
        if protocol is None:
4921
 
            protocol = transport.transport_server_registry.get()
 
4944
            protocol = transport_server_registry.get()
4922
4945
        host, port = self.get_host_and_port(port)
4923
4946
        url = urlutils.local_path_to_url(directory)
4924
4947
        if not allow_writes:
4925
4948
            url = 'readonly+' + url
4926
 
        t = transport.get_transport(url)
4927
 
        protocol(t, host, port, inet)
 
4949
        transport = get_transport(url)
 
4950
        protocol(transport, host, port, inet)
4928
4951
 
4929
4952
 
4930
4953
class cmd_join(Command):
5023
5046
    _see_also = ['send']
5024
5047
 
5025
5048
    takes_options = [
5026
 
        'directory',
5027
5049
        RegistryOption.from_kwargs('patch-type',
5028
5050
            'The type of patch to include in the directive.',
5029
5051
            title='Patch type',
5042
5064
    encoding_type = 'exact'
5043
5065
 
5044
5066
    def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5045
 
            sign=False, revision=None, mail_to=None, message=None,
5046
 
            directory=u'.'):
 
5067
            sign=False, revision=None, mail_to=None, message=None):
5047
5068
        from bzrlib.revision import ensure_null, NULL_REVISION
5048
5069
        include_patch, include_bundle = {
5049
5070
            'plain': (False, False),
5050
5071
            'diff': (True, False),
5051
5072
            'bundle': (True, True),
5052
5073
            }[patch_type]
5053
 
        branch = Branch.open(directory)
 
5074
        branch = Branch.open('.')
5054
5075
        stored_submit_branch = branch.get_submit_branch()
5055
5076
        if submit_branch is None:
5056
5077
            submit_branch = stored_submit_branch
5141
5162
    given, in which case it is sent to a file.
5142
5163
 
5143
5164
    Mail is sent using your preferred mail program.  This should be transparent
5144
 
    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.
5145
5166
    If the preferred client can't be found (or used), your editor will be used.
5146
5167
 
5147
5168
    To use a specific mail program, set the mail_client configuration option.
5318
5339
        Option('delete',
5319
5340
            help='Delete this tag rather than placing it.',
5320
5341
            ),
5321
 
        custom_help('directory',
5322
 
            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
            ),
5323
5347
        Option('force',
5324
5348
            help='Replace existing tags.',
5325
5349
            ),
5333
5357
            revision=None,
5334
5358
            ):
5335
5359
        branch, relpath = Branch.open_containing(directory)
5336
 
        self.add_cleanup(branch.lock_write().unlock)
 
5360
        branch.lock_write()
 
5361
        self.add_cleanup(branch.unlock)
5337
5362
        if delete:
5338
5363
            if tag_name is None:
5339
5364
                raise errors.BzrCommandError("No tag specified to delete.")
5367
5392
 
5368
5393
    _see_also = ['tag']
5369
5394
    takes_options = [
5370
 
        custom_help('directory',
5371
 
            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
            ),
5372
5400
        RegistryOption.from_kwargs('sort',
5373
5401
            'Sort tags by different criteria.', title='Sorting',
5374
5402
            alpha='Sort tags lexicographically (default).',
5391
5419
        if not tags:
5392
5420
            return
5393
5421
 
5394
 
        self.add_cleanup(branch.lock_read().unlock)
 
5422
        branch.lock_read()
 
5423
        self.add_cleanup(branch.unlock)
5395
5424
        if revision:
5396
5425
            graph = branch.repository.get_graph()
5397
5426
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5544
5573
    """
5545
5574
 
5546
5575
    takes_args = ['to_location?']
5547
 
    takes_options = ['directory',
5548
 
                     Option('force',
 
5576
    takes_options = [Option('force',
5549
5577
                        help='Switch even if local commits will be lost.'),
5550
5578
                     'revision',
5551
5579
                     Option('create-branch', short_name='b',
5554
5582
                    ]
5555
5583
 
5556
5584
    def run(self, to_location=None, force=False, create_branch=False,
5557
 
            revision=None, directory=u'.'):
 
5585
            revision=None):
5558
5586
        from bzrlib import switch
5559
 
        tree_location = directory
 
5587
        tree_location = '.'
5560
5588
        revision = _get_one_revision('switch', revision)
5561
5589
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5562
5590
        if to_location is None:
5563
5591
            if revision is None:
5564
5592
                raise errors.BzrCommandError('You must supply either a'
5565
5593
                                             ' revision or a location')
5566
 
            to_location = tree_location
 
5594
            to_location = '.'
5567
5595
        try:
5568
5596
            branch = control_dir.open_branch()
5569
5597
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5704
5732
            name=None,
5705
5733
            switch=None,
5706
5734
            ):
5707
 
        tree, file_list = WorkingTree.open_containing_paths(file_list,
5708
 
            apply_view=False)
 
5735
        tree, file_list = tree_files(file_list, apply_view=False)
5709
5736
        current_view, view_dict = tree.views.get_view_info()
5710
5737
        if name is None:
5711
5738
            name = current_view
5845
5872
    takes_args = ['file*']
5846
5873
 
5847
5874
    takes_options = [
5848
 
        'directory',
5849
5875
        'revision',
5850
5876
        Option('all', help='Shelve all changes.'),
5851
5877
        'message',
5860
5886
    _see_also = ['unshelve']
5861
5887
 
5862
5888
    def run(self, revision=None, all=False, file_list=None, message=None,
5863
 
            writer=None, list=False, destroy=False, directory=u'.'):
 
5889
            writer=None, list=False, destroy=False):
5864
5890
        if list:
5865
5891
            return self.run_for_list()
5866
5892
        from bzrlib.shelf_ui import Shelver
5868
5894
            writer = bzrlib.option.diff_writer_registry.get()
5869
5895
        try:
5870
5896
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5871
 
                file_list, message, destroy=destroy, directory=directory)
 
5897
                file_list, message, destroy=destroy)
5872
5898
            try:
5873
5899
                shelver.run()
5874
5900
            finally:
5878
5904
 
5879
5905
    def run_for_list(self):
5880
5906
        tree = WorkingTree.open_containing('.')[0]
5881
 
        self.add_cleanup(tree.lock_read().unlock)
 
5907
        tree.lock_read()
 
5908
        self.add_cleanup(tree.unlock)
5882
5909
        manager = tree.get_shelf_manager()
5883
5910
        shelves = manager.active_shelves()
5884
5911
        if len(shelves) == 0:
5902
5929
 
5903
5930
    takes_args = ['shelf_id?']
5904
5931
    takes_options = [
5905
 
        'directory',
5906
5932
        RegistryOption.from_kwargs(
5907
5933
            'action', help="The action to perform.",
5908
5934
            enum_switch=False, value_switches=True,
5916
5942
    ]
5917
5943
    _see_also = ['shelve']
5918
5944
 
5919
 
    def run(self, shelf_id=None, action='apply', directory=u'.'):
 
5945
    def run(self, shelf_id=None, action='apply'):
5920
5946
        from bzrlib.shelf_ui import Unshelver
5921
 
        unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
 
5947
        unshelver = Unshelver.from_args(shelf_id, action)
5922
5948
        try:
5923
5949
            unshelver.run()
5924
5950
        finally:
5940
5966
 
5941
5967
    To check what clean-tree will do, use --dry-run.
5942
5968
    """
5943
 
    takes_options = ['directory',
5944
 
                     Option('ignored', help='Delete all ignored files.'),
 
5969
    takes_options = [Option('ignored', help='Delete all ignored files.'),
5945
5970
                     Option('detritus', help='Delete conflict files, merge'
5946
5971
                            ' backups, and failed selftest dirs.'),
5947
5972
                     Option('unknown',
5950
5975
                            ' deleting them.'),
5951
5976
                     Option('force', help='Do not prompt before deleting.')]
5952
5977
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5953
 
            force=False, directory=u'.'):
 
5978
            force=False):
5954
5979
        from bzrlib.clean_tree import clean_tree
5955
5980
        if not (unknown or ignored or detritus):
5956
5981
            unknown = True
5957
5982
        if dry_run:
5958
5983
            force = True
5959
 
        clean_tree(directory, unknown=unknown, ignored=ignored,
5960
 
                   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)
5961
5986
 
5962
5987
 
5963
5988
class cmd_reference(Command):