71
76
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
79
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
74
80
def tree_files(file_list, default_branch=u'.', canonicalize=True,
77
return internal_tree_files(file_list, default_branch, canonicalize,
79
except errors.FileInWrongBranch, e:
80
raise errors.BzrCommandError("%s is not in the same branch as %s" %
81
(e.path, file_list[0]))
82
return internal_tree_files(file_list, default_branch, canonicalize,
84
86
def tree_files_for_add(file_list):
149
151
# XXX: Bad function name; should possibly also be a class method of
150
152
# WorkingTree rather than a function.
153
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
151
154
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
152
155
apply_view=True):
153
156
"""Convert command-line paths to a WorkingTree and relative paths.
158
Deprecated: use WorkingTree.open_containing_paths instead.
155
160
This is typically used for command-line processors that take one or
156
161
more filenames, and infer the workingtree that contains them.
168
173
:return: workingtree, [relative_paths]
170
if file_list is None or len(file_list) == 0:
171
tree = WorkingTree.open_containing(default_branch)[0]
172
if tree.supports_views() and apply_view:
173
view_files = tree.views.lookup_view()
175
file_list = view_files
176
view_str = views.view_display_str(view_files)
177
note("Ignoring files outside view. View is %s" % view_str)
178
return tree, file_list
179
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
180
return tree, safe_relpath_files(tree, file_list, canonicalize,
181
apply_view=apply_view)
184
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
185
"""Convert file_list into a list of relpaths in tree.
187
:param tree: A tree to operate on.
188
:param file_list: A list of user provided paths or None.
189
:param apply_view: if True and a view is set, apply it or check that
190
specified files are within it
191
:return: A list of relative paths.
192
:raises errors.PathNotChild: When a provided path is in a different tree
195
if file_list is None:
197
if tree.supports_views() and apply_view:
198
view_files = tree.views.lookup_view()
202
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
203
# doesn't - fix that up here before we enter the loop.
205
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
208
for filename in file_list:
210
relpath = fixer(osutils.dereference_path(filename))
211
if view_files and not osutils.is_inside_any(view_files, relpath):
212
raise errors.FileOutsideView(filename, view_files)
213
new_list.append(relpath)
214
except errors.PathNotChild:
215
raise errors.FileInWrongBranch(tree.branch, filename)
175
return WorkingTree.open_containing_paths(
176
file_list, default_directory='.',
219
181
def _get_view_info_for_change_reporter(tree):
193
def _open_directory_or_containing_tree_or_branch(filename, directory):
194
"""Open the tree or branch containing the specified file, unless
195
the --directory option is used to specify a different branch."""
196
if directory is not None:
197
return (None, Branch.open(directory), filename)
198
return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
231
201
# TODO: Make sure no commands unconditionally use the working directory as a
232
202
# branch. If a filename argument is used, the first of them should be used to
233
203
# specify the branch. (Perhaps this can be factored out into some kind of
338
308
takes_args = ['revision_id?']
339
takes_options = ['revision']
309
takes_options = ['directory', 'revision']
340
310
# cat-revision is more for frontends so should be exact
341
311
encoding = 'strict'
313
def print_revision(self, revisions, revid):
314
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
315
record = stream.next()
316
if record.storage_kind == 'absent':
317
raise errors.NoSuchRevision(revisions, revid)
318
revtext = record.get_bytes_as('fulltext')
319
self.outf.write(revtext.decode('utf-8'))
344
def run(self, revision_id=None, revision=None):
322
def run(self, revision_id=None, revision=None, directory=u'.'):
345
323
if revision_id is not None and revision is not None:
346
324
raise errors.BzrCommandError('You can only supply one of'
347
325
' revision_id or --revision')
348
326
if revision_id is None and revision is None:
349
327
raise errors.BzrCommandError('You must supply either'
350
328
' --revision or a revision_id')
351
b = WorkingTree.open_containing(u'.')[0].branch
353
# TODO: jam 20060112 should cat-revision always output utf-8?
354
if revision_id is not None:
355
revision_id = osutils.safe_revision_id(revision_id, warn=False)
357
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
358
except errors.NoSuchRevision:
359
msg = "The repository %s contains no revision %s." % (b.repository.base,
361
raise errors.BzrCommandError(msg)
362
elif revision is not None:
365
raise errors.BzrCommandError('You cannot specify a NULL'
367
rev_id = rev.as_revision_id(b)
368
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
329
b = WorkingTree.open_containing(directory)[0].branch
331
revisions = b.repository.revisions
332
if revisions is None:
333
raise errors.BzrCommandError('Repository %r does not support '
334
'access to raw revision texts')
336
b.repository.lock_read()
338
# TODO: jam 20060112 should cat-revision always output utf-8?
339
if revision_id is not None:
340
revision_id = osutils.safe_revision_id(revision_id, warn=False)
342
self.print_revision(revisions, revision_id)
343
except errors.NoSuchRevision:
344
msg = "The repository %s contains no revision %s." % (
345
b.repository.base, revision_id)
346
raise errors.BzrCommandError(msg)
347
elif revision is not None:
350
raise errors.BzrCommandError(
351
'You cannot specify a NULL revision.')
352
rev_id = rev.as_revision_id(b)
353
self.print_revision(revisions, rev_id)
355
b.repository.unlock()
371
358
class cmd_dump_btree(Command):
372
"""Dump the contents of a btree index file to stdout.
359
__doc__ = """Dump the contents of a btree index file to stdout.
374
361
PATH is a btree index file, it can be any URL. This includes things like
375
362
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
439
426
for node in bt.iter_all_entries():
440
427
# Node is made up of:
441
428
# (index, key, value, [references])
442
refs_as_tuples = static_tuple.as_tuples(node[3])
432
refs_as_tuples = None
434
refs_as_tuples = static_tuple.as_tuples(refs)
443
435
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
444
436
self.outf.write('%s\n' % (as_tuple,))
447
439
class cmd_remove_tree(Command):
448
"""Remove the working tree from a given branch/checkout.
440
__doc__ = """Remove the working tree from a given branch/checkout.
450
442
Since a lightweight checkout is little more than a working tree
451
443
this will refuse to run against one.
478
470
if (working.has_changes()):
479
471
raise errors.UncommittedChanges(working)
472
if working.get_shelf_manager().last_shelf() is not None:
473
raise errors.ShelvedChanges(working)
481
working_path = working.bzrdir.root_transport.base
482
branch_path = working.branch.bzrdir.root_transport.base
483
if working_path != branch_path:
475
if working.user_url != working.branch.user_url:
484
476
raise errors.BzrCommandError("You cannot remove the working tree"
485
477
" from a lightweight checkout")
516
507
revno = ".".join(str(n) for n in revno_t)
518
509
b = Branch.open_containing(location)[0]
520
self.add_cleanup(b.unlock)
510
self.add_cleanup(b.lock_read().unlock)
521
511
revno = b.revno()
522
512
self.cleanup_now()
523
513
self.outf.write(str(revno) + '\n')
526
516
class cmd_revision_info(Command):
527
"""Show revision number and revision id for a given revision identifier.
517
__doc__ = """Show revision number and revision id for a given revision identifier.
530
520
takes_args = ['revision_info*']
531
521
takes_options = [
523
custom_help('directory',
534
524
help='Branch to examine, '
535
'rather than the one containing the working directory.',
525
'rather than the one containing the working directory.'),
539
526
Option('tree', help='Show revno of working tree'),
683
667
def run(self, dir_list):
684
668
for d in dir_list:
686
669
wt, dd = WorkingTree.open_containing(d)
688
self.outf.write('added %s\n' % d)
670
base = os.path.dirname(dd)
671
id = wt.path2id(base)
675
self.outf.write('added %s\n' % d)
677
raise errors.NotVersionedError(path=base)
691
680
class cmd_relpath(Command):
692
"""Show path of a file relative to root"""
681
__doc__ = """Show path of a file relative to root"""
694
683
takes_args = ['filename']
730
719
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
732
721
revision = _get_one_revision('inventory', revision)
733
work_tree, file_list = tree_files(file_list)
734
work_tree.lock_read()
735
self.add_cleanup(work_tree.unlock)
722
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
723
self.add_cleanup(work_tree.lock_read().unlock)
736
724
if revision is not None:
737
725
tree = revision.as_tree(work_tree.branch)
739
727
extra_trees = [work_tree]
741
self.add_cleanup(tree.unlock)
728
self.add_cleanup(tree.lock_read().unlock)
804
791
if len(names_list) < 2:
805
792
raise errors.BzrCommandError("missing file argument")
806
tree, rel_names = tree_files(names_list, canonicalize=False)
807
tree.lock_tree_write()
808
self.add_cleanup(tree.unlock)
793
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
794
self.add_cleanup(tree.lock_tree_write().unlock)
809
795
self._run(tree, names_list, rel_names, after)
811
797
def run_auto(self, names_list, after, dry_run):
816
802
raise errors.BzrCommandError('--after cannot be specified with'
818
work_tree, file_list = tree_files(names_list, default_branch='.')
819
work_tree.lock_tree_write()
820
self.add_cleanup(work_tree.unlock)
804
work_tree, file_list = WorkingTree.open_containing_paths(
805
names_list, default_directory='.')
806
self.add_cleanup(work_tree.lock_tree_write().unlock)
821
807
rename_map.RenameMap.guess_renames(work_tree, dry_run)
823
809
def _run(self, tree, names_list, rel_names, after):
931
917
takes_options = ['remember', 'overwrite', 'revision',
932
918
custom_help('verbose',
933
919
help='Show logs of pulled revisions.'),
920
custom_help('directory',
935
921
help='Branch to pull into, '
936
'rather than the one containing the working directory.',
922
'rather than the one containing the working directory.'),
941
924
help="Perform a local pull in a bound "
942
925
"branch. Local pulls are not applied to "
943
926
"the master branch."
929
help="Show base revision text in conflicts.")
946
931
takes_args = ['location?']
947
932
encoding_type = 'replace'
949
934
def run(self, location=None, remember=False, overwrite=False,
950
935
revision=None, verbose=False,
951
directory=None, local=False):
936
directory=None, local=False,
952
938
# FIXME: too much stuff is in the command class
953
939
revision_id = None
958
944
tree_to = WorkingTree.open_containing(directory)[0]
959
945
branch_to = tree_to.branch
946
self.add_cleanup(tree_to.lock_write().unlock)
960
947
except errors.NoWorkingTree:
962
949
branch_to = Branch.open_containing(directory)[0]
950
self.add_cleanup(branch_to.lock_write().unlock)
952
if tree_to is None and show_base:
953
raise errors.BzrCommandError("Need working tree for --show-base.")
964
955
if local and not branch_to.get_bound_location():
965
956
raise errors.LocalRequiresBoundBranch()
997
988
branch_from = Branch.open(location,
998
989
possible_transports=possible_transports)
990
self.add_cleanup(branch_from.lock_read().unlock)
1000
992
if branch_to.get_parent() is None or remember:
1001
993
branch_to.set_parent(branch_from.base)
1003
if branch_from is not branch_to:
1004
branch_from.lock_read()
1005
self.add_cleanup(branch_from.unlock)
1006
995
if revision is not None:
1007
996
revision_id = revision.as_revision_id(branch_from)
1009
branch_to.lock_write()
1010
self.add_cleanup(branch_to.unlock)
1011
998
if tree_to is not None:
1012
999
view_info = _get_view_info_for_change_reporter(tree_to)
1013
1000
change_reporter = delta._ChangeReporter(
1058
1046
Option('create-prefix',
1059
1047
help='Create the path leading up to the branch '
1060
1048
'if it does not already exist.'),
1049
custom_help('directory',
1062
1050
help='Branch to push from, '
1063
'rather than the one containing the working directory.',
1051
'rather than the one containing the working directory.'),
1067
1052
Option('use-existing-dir',
1068
1053
help='By default push will fail if the target'
1069
1054
' directory exists, but does not already'
1095
1080
# Get the source branch
1096
1081
(tree, br_from,
1097
1082
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1099
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1100
if strict is None: strict = True # default value
1101
1083
# Get the tip's revision_id
1102
1084
revision = _get_one_revision('push', revision)
1103
1085
if revision is not None:
1104
1086
revision_id = revision.in_history(br_from).rev_id
1106
1088
revision_id = None
1107
if strict and tree is not None and revision_id is None:
1108
if (tree.has_changes()):
1109
raise errors.UncommittedChanges(
1110
tree, more='Use --no-strict to force the push.')
1111
if tree.last_revision() != tree.branch.last_revision():
1112
# The tree has lost sync with its branch, there is little
1113
# chance that the user is aware of it but he can still force
1114
# the push with --no-strict
1115
raise errors.OutOfDateTree(
1116
tree, more='Use --no-strict to force the push.')
1089
if tree is not None and revision_id is None:
1090
tree.check_changed_or_out_of_date(
1091
strict, 'push_strict',
1092
more_error='Use --no-strict to force the push.',
1093
more_warning='Uncommitted changes will not be pushed.')
1118
1094
# Get the stacked_on branch, if any
1119
1095
if stacked_on is not None:
1120
1096
stacked_on = urlutils.normalize_url(stacked_on)
1168
1144
_see_also = ['checkout']
1169
1145
takes_args = ['from_location', 'to_location?']
1170
takes_options = ['revision', Option('hardlink',
1171
help='Hard-link working tree files where possible.'),
1146
takes_options = ['revision',
1147
Option('hardlink', help='Hard-link working tree files where possible.'),
1148
Option('files-from', type=str,
1149
help="Get file contents from this tree."),
1172
1150
Option('no-tree',
1173
1151
help="Create a branch without a working-tree."),
1174
1152
Option('switch',
1193
1171
def run(self, from_location, to_location=None, revision=None,
1194
1172
hardlink=False, stacked=False, standalone=False, no_tree=False,
1195
use_existing_dir=False, switch=False, bind=False):
1173
use_existing_dir=False, switch=False, bind=False,
1196
1175
from bzrlib import switch as _mod_switch
1197
1176
from bzrlib.tag import _merge_tags_if_possible
1198
1177
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1179
if not (hardlink or files_from):
1180
# accelerator_tree is usually slower because you have to read N
1181
# files (no readahead, lots of seeks, etc), but allow the user to
1182
# explicitly request it
1183
accelerator_tree = None
1184
if files_from is not None and files_from != from_location:
1185
accelerator_tree = WorkingTree.open(files_from)
1200
1186
revision = _get_one_revision('branch', revision)
1202
self.add_cleanup(br_from.unlock)
1187
self.add_cleanup(br_from.lock_read().unlock)
1203
1188
if revision is not None:
1204
1189
revision_id = revision.as_revision_id(br_from)
1310
1295
to_location = branch_location
1311
1296
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1312
1297
branch_location)
1298
if not (hardlink or files_from):
1299
# accelerator_tree is usually slower because you have to read N
1300
# files (no readahead, lots of seeks, etc), but allow the user to
1301
# explicitly request it
1302
accelerator_tree = None
1313
1303
revision = _get_one_revision('checkout', revision)
1314
if files_from is not None:
1304
if files_from is not None and files_from != branch_location:
1315
1305
accelerator_tree = WorkingTree.open(files_from)
1316
1306
if revision is not None:
1317
1307
revision_id = revision.as_revision_id(source)
1375
1363
If you want to discard your local changes, you can just do a
1376
1364
'bzr revert' instead of 'bzr commit' after the update.
1366
If you want to restore a file that has been removed locally, use
1367
'bzr revert' instead of 'bzr update'.
1378
1369
If the tree's branch is bound to a master branch, it will also update
1379
1370
the branch from the master.
1382
1373
_see_also = ['pull', 'working-trees', 'status-flags']
1383
1374
takes_args = ['dir?']
1384
takes_options = ['revision']
1375
takes_options = ['revision',
1377
help="Show base revision text in conflicts."),
1385
1379
aliases = ['up']
1387
def run(self, dir='.', revision=None):
1381
def run(self, dir='.', revision=None, show_base=None):
1388
1382
if revision is not None and len(revision) != 1:
1389
1383
raise errors.BzrCommandError(
1390
1384
"bzr update --revision takes exactly one revision")
1394
1388
master = branch.get_master_branch(
1395
1389
possible_transports=possible_transports)
1396
1390
if master is not None:
1398
1391
branch_location = master.base
1394
branch_location = tree.branch.base
1400
1395
tree.lock_tree_write()
1401
branch_location = tree.branch.base
1402
1396
self.add_cleanup(tree.unlock)
1403
1397
# get rid of the final '/' and be ready for display
1404
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1398
branch_location = urlutils.unescape_for_display(
1399
branch_location.rstrip('/'),
1406
1401
existing_pending_merges = tree.get_parent_ids()[1:]
1407
1402
if master is None:
1417
1412
revision_id = branch.last_revision()
1418
1413
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1419
revno = branch.revision_id_to_revno(revision_id)
1420
note("Tree is up to date at revision %d of branch %s" %
1421
(revno, branch_location))
1414
revno = branch.revision_id_to_dotted_revno(revision_id)
1415
note("Tree is up to date at revision %s of branch %s" %
1416
('.'.join(map(str, revno)), branch_location))
1423
1418
view_info = _get_view_info_for_change_reporter(tree)
1424
1419
change_reporter = delta._ChangeReporter(
1429
1424
change_reporter,
1430
1425
possible_transports=possible_transports,
1431
1426
revision=revision_id,
1428
show_base=show_base)
1433
1429
except errors.NoSuchRevision, e:
1434
1430
raise errors.BzrCommandError(
1435
1431
"branch has no revision %s\n"
1436
1432
"bzr update --revision only works"
1437
1433
" for a revision in the branch history"
1438
1434
% (e.revision))
1439
revno = tree.branch.revision_id_to_revno(
1435
revno = tree.branch.revision_id_to_dotted_revno(
1440
1436
_mod_revision.ensure_null(tree.last_revision()))
1441
note('Updated to revision %d of branch %s' %
1442
(revno, branch_location))
1443
if tree.get_parent_ids()[1:] != existing_pending_merges:
1437
note('Updated to revision %s of branch %s' %
1438
('.'.join(map(str, revno)), branch_location))
1439
parent_ids = tree.get_parent_ids()
1440
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1444
1441
note('Your local commits will now show as pending merges with '
1445
1442
"'bzr status', and can be committed with 'bzr commit'.")
1446
1443
if conflicts != 0:
1496
1493
class cmd_remove(Command):
1497
"""Remove files or directories.
1494
__doc__ = """Remove files or directories.
1499
This makes bzr stop tracking changes to the specified files. bzr will delete
1500
them if they can easily be recovered using revert. If no options or
1501
parameters are given bzr will scan for files that are being tracked by bzr
1502
but missing in your tree and stop tracking them for you.
1496
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1497
delete them if they can easily be recovered using revert otherwise they
1498
will be backed up (adding an extention of the form .~#~). If no options or
1499
parameters are given Bazaar will scan for files that are being tracked by
1500
Bazaar but missing in your tree and stop tracking them for you.
1504
1502
takes_args = ['file*']
1505
1503
takes_options = ['verbose',
1507
1505
RegistryOption.from_kwargs('file-deletion-strategy',
1508
1506
'The file deletion mode to be used.',
1509
1507
title='Deletion Strategy', value_switches=True, enum_switch=False,
1510
safe='Only delete files if they can be'
1511
' safely recovered (default).',
1508
safe='Backup changed files (default).',
1512
1509
keep='Delete from bzr but leave the working copy.',
1510
no_backup='Don\'t backup changed files.',
1513
1511
force='Delete all the specified files, even if they can not be '
1514
'recovered and even if they are non-empty directories.')]
1512
'recovered and even if they are non-empty directories. '
1513
'(deprecated, use no-backup)')]
1515
1514
aliases = ['rm', 'del']
1516
1515
encoding_type = 'replace'
1518
1517
def run(self, file_list, verbose=False, new=False,
1519
1518
file_deletion_strategy='safe'):
1520
tree, file_list = tree_files(file_list)
1519
if file_deletion_strategy == 'force':
1520
note("(The --force option is deprecated, rather use --no-backup "
1522
file_deletion_strategy = 'no-backup'
1524
tree, file_list = WorkingTree.open_containing_paths(file_list)
1522
1526
if file_list is not None:
1523
1527
file_list = [f for f in file_list]
1526
self.add_cleanup(tree.unlock)
1529
self.add_cleanup(tree.lock_write().unlock)
1527
1530
# Heuristics should probably all move into tree.remove_smart or
1544
1547
file_deletion_strategy = 'keep'
1545
1548
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1546
1549
keep_files=file_deletion_strategy=='keep',
1547
force=file_deletion_strategy=='force')
1550
force=(file_deletion_strategy=='no-backup'))
1550
1553
class cmd_file_id(Command):
1551
"""Print file_id of a particular file or directory.
1554
__doc__ = """Print file_id of a particular file or directory.
1553
1556
The file_id is assigned when the file is first added and remains the
1554
1557
same through all revisions where the file exists, even when it is
1613
1616
_see_also = ['check']
1614
1617
takes_args = ['branch?']
1619
Option('canonicalize-chks',
1620
help='Make sure CHKs are in canonical form (repairs '
1616
def run(self, branch="."):
1625
def run(self, branch=".", canonicalize_chks=False):
1617
1626
from bzrlib.reconcile import reconcile
1618
1627
dir = bzrdir.BzrDir.open(branch)
1628
reconcile(dir, canonicalize_chks=canonicalize_chks)
1622
1631
class cmd_revision_history(Command):
1623
"""Display the list of revision ids on a branch."""
1632
__doc__ = """Display the list of revision ids on a branch."""
1625
1634
_see_also = ['log']
1626
1635
takes_args = ['location?']
1922
1935
help='Use this command to compare files.',
1938
RegistryOption('format',
1939
help='Diff format to use.',
1940
lazy_registry=('bzrlib.diff', 'format_registry'),
1941
value_switches=False, title='Diff format'),
1926
1943
aliases = ['di', 'dif']
1927
1944
encoding_type = 'exact'
1929
1946
@display_command
1930
1947
def run(self, revision=None, file_list=None, diff_options=None,
1931
prefix=None, old=None, new=None, using=None):
1932
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1948
prefix=None, old=None, new=None, using=None, format=None):
1949
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1934
1952
if (prefix is None) or (prefix == '0'):
1935
1953
# diff -p0 format
1949
1967
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1950
1968
' one or two revision specifiers')
1970
if using is not None and format is not None:
1971
raise errors.BzrCommandError('--using and --format are mutually '
1952
1974
(old_tree, new_tree,
1953
1975
old_branch, new_branch,
1954
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1955
file_list, revision, old, new, apply_view=True)
1976
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1977
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1978
# GNU diff on Windows uses ANSI encoding for filenames
1979
path_encoding = osutils.get_diff_header_encoding()
1956
1980
return show_diff_trees(old_tree, new_tree, sys.stdout,
1957
1981
specific_files=specific_files,
1958
1982
external_diff_options=diff_options,
1959
1983
old_label=old_label, new_label=new_label,
1960
extra_trees=extra_trees, using=using)
1984
extra_trees=extra_trees,
1985
path_encoding=path_encoding,
1963
1990
class cmd_deleted(Command):
1964
"""List files deleted in the working tree.
1991
__doc__ = """List files deleted in the working tree.
1966
1993
# TODO: Show files deleted since a previous revision, or
1967
1994
# between two revisions.
1970
1997
# level of effort but possibly much less IO. (Or possibly not,
1971
1998
# if the directories are very large...)
1972
1999
_see_also = ['status', 'ls']
1973
takes_options = ['show-ids']
2000
takes_options = ['directory', 'show-ids']
1975
2002
@display_command
1976
def run(self, show_ids=False):
1977
tree = WorkingTree.open_containing(u'.')[0]
1979
self.add_cleanup(tree.unlock)
2003
def run(self, show_ids=False, directory=u'.'):
2004
tree = WorkingTree.open_containing(directory)[0]
2005
self.add_cleanup(tree.lock_read().unlock)
1980
2006
old = tree.basis_tree()
1982
self.add_cleanup(old.unlock)
2007
self.add_cleanup(old.lock_read().unlock)
1983
2008
for path, ie in old.inventory.iter_entries():
1984
2009
if not tree.has_id(ie.file_id):
1985
2010
self.outf.write(path)
1992
2017
class cmd_modified(Command):
1993
"""List files modified in working tree.
2018
__doc__ = """List files modified in working tree.
1997
2022
_see_also = ['status', 'ls']
2000
help='Write an ascii NUL (\\0) separator '
2001
'between files rather than a newline.')
2023
takes_options = ['directory', 'null']
2004
2025
@display_command
2005
def run(self, null=False):
2006
tree = WorkingTree.open_containing(u'.')[0]
2026
def run(self, null=False, directory=u'.'):
2027
tree = WorkingTree.open_containing(directory)[0]
2007
2028
td = tree.changes_from(tree.basis_tree())
2008
2029
for path, id, kind, text_modified, meta_modified in td.modified:
2015
2036
class cmd_added(Command):
2016
"""List files added in working tree.
2037
__doc__ = """List files added in working tree.
2020
2041
_see_also = ['status', 'ls']
2023
help='Write an ascii NUL (\\0) separator '
2024
'between files rather than a newline.')
2042
takes_options = ['directory', 'null']
2027
2044
@display_command
2028
def run(self, null=False):
2029
wt = WorkingTree.open_containing(u'.')[0]
2031
self.add_cleanup(wt.unlock)
2045
def run(self, null=False, directory=u'.'):
2046
wt = WorkingTree.open_containing(directory)[0]
2047
self.add_cleanup(wt.lock_read().unlock)
2032
2048
basis = wt.basis_tree()
2034
self.add_cleanup(basis.unlock)
2049
self.add_cleanup(basis.lock_read().unlock)
2035
2050
basis_inv = basis.inventory
2036
2051
inv = wt.inventory
2037
2052
for file_id in inv:
2246
2261
help='Show just the specified revision.'
2247
2262
' See also "help revisionspec".'),
2264
RegistryOption('authors',
2265
'What names to list as authors - first, all or committer.',
2267
lazy_registry=('bzrlib.log', 'author_list_registry'),
2249
2269
Option('levels',
2250
2270
short_name='n',
2251
2271
help='Number of levels to display - 0 for all, 1 for flat.',
2310
2341
# find the file ids to log and check for directory filtering
2311
2342
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2312
revision, file_list)
2313
self.add_cleanup(b.unlock)
2343
revision, file_list, self.add_cleanup)
2314
2344
for relpath, file_id, kind in file_info_list:
2315
2345
if file_id is None:
2316
2346
raise errors.BzrCommandError(
2386
2416
direction=direction, specific_fileids=file_ids,
2387
2417
start_revision=rev1, end_revision=rev2, limit=limit,
2388
2418
message_search=message, delta_type=delta_type,
2389
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2419
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2420
exclude_common_ancestry=exclude_common_ancestry,
2390
2422
Logger(b, rqst).show(lf)
2411
2443
raise errors.BzrCommandError(
2412
2444
"bzr %s doesn't accept two revisions in different"
2413
2445
" branches." % command_name)
2414
rev1 = start_spec.in_history(branch)
2446
if start_spec.spec is None:
2447
# Avoid loading all the history.
2448
rev1 = RevisionInfo(branch, None, None)
2450
rev1 = start_spec.in_history(branch)
2415
2451
# Avoid loading all of history when we know a missing
2416
2452
# end of range means the last revision ...
2417
2453
if end_spec.spec is None:
2459
2495
tree, relpath = WorkingTree.open_containing(filename)
2460
2496
file_id = tree.path2id(relpath)
2461
2497
b = tree.branch
2463
self.add_cleanup(b.unlock)
2498
self.add_cleanup(b.lock_read().unlock)
2464
2499
touching_revs = log.find_touching_revisions(b, file_id)
2465
2500
for revno, revision_id, what in touching_revs:
2466
2501
self.outf.write("%6d %s\n" % (revno, what))
2469
2504
class cmd_ls(Command):
2470
"""List files in a tree.
2505
__doc__ = """List files in a tree.
2473
2508
_see_also = ['status', 'cat']
2479
2514
help='Recurse into subdirectories.'),
2480
2515
Option('from-root',
2481
2516
help='Print paths relative to the root of the branch.'),
2482
Option('unknown', help='Print unknown files.'),
2517
Option('unknown', short_name='u',
2518
help='Print unknown files.'),
2483
2519
Option('versioned', help='Print versioned files.',
2484
2520
short_name='V'),
2485
Option('ignored', help='Print ignored files.'),
2487
help='Write an ascii NUL (\\0) separator '
2488
'between files rather than a newline.'),
2521
Option('ignored', short_name='i',
2522
help='Print ignored files.'),
2523
Option('kind', short_name='k',
2490
2524
help='List entries of a particular kind: file, directory, symlink.',
2494
2530
@display_command
2495
2531
def run(self, revision=None, verbose=False,
2496
2532
recursive=False, from_root=False,
2497
2533
unknown=False, versioned=False, ignored=False,
2498
null=False, kind=None, show_ids=False, path=None):
2534
null=False, kind=None, show_ids=False, path=None, directory=None):
2500
2536
if kind and kind not in ('file', 'directory', 'symlink'):
2501
2537
raise errors.BzrCommandError('invalid kind specified')
2535
2571
view_str = views.view_display_str(view_files)
2536
2572
note("Ignoring files outside view. View is %s" % view_str)
2539
self.add_cleanup(tree.unlock)
2574
self.add_cleanup(tree.lock_read().unlock)
2540
2575
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2541
2576
from_dir=relpath, recursive=recursive):
2542
2577
# Apply additional masking
2586
2621
class cmd_unknowns(Command):
2587
"""List unknown files.
2622
__doc__ = """List unknown files.
2591
2626
_see_also = ['ls']
2627
takes_options = ['directory']
2593
2629
@display_command
2595
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2630
def run(self, directory=u'.'):
2631
for f in WorkingTree.open_containing(directory)[0].unknowns():
2596
2632
self.outf.write(osutils.quotefn(f) + '\n')
2599
2635
class cmd_ignore(Command):
2600
"""Ignore specified files or patterns.
2636
__doc__ = """Ignore specified files or patterns.
2602
2638
See ``bzr help patterns`` for details on the syntax of patterns.
2612
2648
using this command or directly by using an editor, be sure to commit
2651
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2652
the global ignore file can be found in the application data directory as
2653
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2654
Global ignores are not touched by this command. The global ignore file
2655
can be edited directly using an editor.
2615
2657
Patterns prefixed with '!' are exceptions to ignore patterns and take
2616
2658
precedence over regular ignores. Such exceptions are used to specify
2617
2659
files that should be versioned which would otherwise be ignored.
2658
2700
_see_also = ['status', 'ignored', 'patterns']
2659
2701
takes_args = ['name_pattern*']
2661
Option('old-default-rules',
2662
help='Write out the ignore rules bzr < 0.9 always used.')
2702
takes_options = ['directory',
2703
Option('default-rules',
2704
help='Display the default ignore rules that bzr uses.')
2665
def run(self, name_pattern_list=None, old_default_rules=None):
2707
def run(self, name_pattern_list=None, default_rules=None,
2666
2709
from bzrlib import ignores
2667
if old_default_rules is not None:
2668
# dump the rules and exit
2669
for pattern in ignores.OLD_DEFAULTS:
2710
if default_rules is not None:
2711
# dump the default rules and exit
2712
for pattern in ignores.USER_DEFAULTS:
2713
self.outf.write("%s\n" % pattern)
2672
2715
if not name_pattern_list:
2673
2716
raise errors.BzrCommandError("ignore requires at least one "
2674
"NAME_PATTERN or --old-default-rules")
2717
"NAME_PATTERN or --default-rules.")
2675
2718
name_pattern_list = [globbing.normalize_pattern(p)
2676
2719
for p in name_pattern_list]
2721
for p in name_pattern_list:
2722
if not globbing.Globster.is_pattern_valid(p):
2723
bad_patterns += ('\n %s' % p)
2725
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2726
ui.ui_factory.show_error(msg)
2727
raise errors.InvalidPattern('')
2677
2728
for name_pattern in name_pattern_list:
2678
2729
if (name_pattern[0] == '/' or
2679
2730
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2680
2731
raise errors.BzrCommandError(
2681
2732
"NAME_PATTERN should not be an absolute path")
2682
tree, relpath = WorkingTree.open_containing(u'.')
2733
tree, relpath = WorkingTree.open_containing(directory)
2683
2734
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2684
2735
ignored = globbing.Globster(name_pattern_list)
2737
self.add_cleanup(tree.lock_read().unlock)
2687
2738
for entry in tree.list_files():
2689
2740
if id is not None:
2690
2741
filename = entry[0]
2691
2742
if ignored.match(filename):
2692
matches.append(filename.encode('utf-8'))
2743
matches.append(filename)
2694
2744
if len(matches) > 0:
2695
print "Warning: the following files are version controlled and" \
2696
" match your ignore pattern:\n%s" \
2697
"\nThese files will continue to be version controlled" \
2698
" unless you 'bzr remove' them." % ("\n".join(matches),)
2745
self.outf.write("Warning: the following files are version controlled and"
2746
" match your ignore pattern:\n%s"
2747
"\nThese files will continue to be version controlled"
2748
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2701
2751
class cmd_ignored(Command):
2702
"""List ignored files and the patterns that matched them.
2752
__doc__ = """List ignored files and the patterns that matched them.
2704
2754
List all the ignored files and the ignore pattern that caused the file to
2712
2762
encoding_type = 'replace'
2713
2763
_see_also = ['ignore', 'ls']
2764
takes_options = ['directory']
2715
2766
@display_command
2717
tree = WorkingTree.open_containing(u'.')[0]
2719
self.add_cleanup(tree.unlock)
2767
def run(self, directory=u'.'):
2768
tree = WorkingTree.open_containing(directory)[0]
2769
self.add_cleanup(tree.lock_read().unlock)
2720
2770
for path, file_class, kind, file_id, entry in tree.list_files():
2721
2771
if file_class != 'I':
2728
2778
class cmd_lookup_revision(Command):
2729
"""Lookup the revision-id from a revision-number
2779
__doc__ = """Lookup the revision-id from a revision-number
2732
2782
bzr lookup-revision 33
2735
2785
takes_args = ['revno']
2786
takes_options = ['directory']
2737
2788
@display_command
2738
def run(self, revno):
2789
def run(self, revno, directory=u'.'):
2740
2791
revno = int(revno)
2741
2792
except ValueError:
2742
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2744
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2793
raise errors.BzrCommandError("not a valid revision-number: %r"
2795
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2796
self.outf.write("%s\n" % revid)
2747
2799
class cmd_export(Command):
2748
"""Export current or past revision to a destination directory or archive.
2800
__doc__ = """Export current or past revision to a destination directory or archive.
2750
2802
If no revision is specified this exports the last committed revision.
2785
2837
help="Name of the root directory inside the exported file."),
2838
Option('per-file-timestamps',
2839
help='Set modification time of files to that of the last '
2840
'revision in which it was changed.'),
2787
2842
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2788
root=None, filters=False):
2843
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2789
2844
from bzrlib.export import export
2791
2846
if branch_or_subdir is None:
2792
tree = WorkingTree.open_containing(u'.')[0]
2847
tree = WorkingTree.open_containing(directory)[0]
2793
2848
b = tree.branch
2799
2854
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2801
export(rev_tree, dest, format, root, subdir, filtered=filters)
2856
export(rev_tree, dest, format, root, subdir, filtered=filters,
2857
per_file_timestamps=per_file_timestamps)
2802
2858
except errors.NoSuchExportFormat, e:
2803
2859
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2806
2862
class cmd_cat(Command):
2807
"""Write the contents of a file as of a given revision to standard output.
2863
__doc__ = """Write the contents of a file as of a given revision to standard output.
2809
2865
If no revision is nominated, the last revision is used.
2825
2881
@display_command
2826
2882
def run(self, filename, revision=None, name_from_revision=False,
2883
filters=False, directory=None):
2828
2884
if revision is not None and len(revision) != 1:
2829
2885
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2830
2886
" one revision specifier")
2831
2887
tree, branch, relpath = \
2832
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2834
self.add_cleanup(branch.unlock)
2888
_open_directory_or_containing_tree_or_branch(filename, directory)
2889
self.add_cleanup(branch.lock_read().unlock)
2835
2890
return self._run(tree, branch, relpath, filename, revision,
2836
2891
name_from_revision, filters)
2892
2946
class cmd_local_time_offset(Command):
2893
"""Show the offset in seconds from GMT to local time."""
2947
__doc__ = """Show the offset in seconds from GMT to local time."""
2895
2949
@display_command
2897
print osutils.local_time_offset()
2951
self.outf.write("%s\n" % osutils.local_time_offset())
2901
2955
class cmd_commit(Command):
2902
"""Commit changes into a new revision.
2956
__doc__ = """Commit changes into a new revision.
2904
2958
An explanatory message needs to be given for each commit. This is
2905
2959
often done by using the --message option (getting the message from the
3099
3153
'(use --file "%(f)s" to take commit message from that file)'
3100
3154
% { 'f': message })
3101
3155
ui.ui_factory.show_warning(warning_msg)
3157
message = message.replace('\r\n', '\n')
3158
message = message.replace('\r', '\n')
3160
raise errors.BzrCommandError(
3161
"please specify either --message or --file")
3103
3163
def get_message(commit_obj):
3104
3164
"""Callback to get commit message"""
3105
my_message = message
3106
if my_message is not None and '\r' in my_message:
3107
my_message = my_message.replace('\r\n', '\n')
3108
my_message = my_message.replace('\r', '\n')
3109
if my_message is None and not file:
3110
t = make_commit_message_template_encoded(tree,
3168
my_message = f.read().decode(osutils.get_user_encoding())
3171
elif message is not None:
3172
my_message = message
3174
# No message supplied: make one up.
3175
# text is the status of the tree
3176
text = make_commit_message_template_encoded(tree,
3111
3177
selected_list, diff=show_diff,
3112
3178
output_encoding=osutils.get_user_encoding())
3179
# start_message is the template generated from hooks
3180
# XXX: Warning - looks like hooks return unicode,
3181
# make_commit_message_template_encoded returns user encoding.
3182
# We probably want to be using edit_commit_message instead to
3113
3184
start_message = generate_commit_message_template(commit_obj)
3114
my_message = edit_commit_message_encoded(t,
3185
my_message = edit_commit_message_encoded(text,
3115
3186
start_message=start_message)
3116
3187
if my_message is None:
3117
3188
raise errors.BzrCommandError("please specify a commit"
3118
3189
" message with either --message or --file")
3119
elif my_message and file:
3120
raise errors.BzrCommandError(
3121
"please specify either --message or --file")
3123
my_message = codecs.open(file, 'rt',
3124
osutils.get_user_encoding()).read()
3125
3190
if my_message == "":
3126
3191
raise errors.BzrCommandError("empty commit message specified")
3127
3192
return my_message
3137
3202
reporter=None, verbose=verbose, revprops=properties,
3138
3203
authors=author, timestamp=commit_stamp,
3139
3204
timezone=offset,
3140
exclude=safe_relpath_files(tree, exclude))
3205
exclude=tree.safe_relpath_files(exclude))
3141
3206
except PointlessCommit:
3142
# FIXME: This should really happen before the file is read in;
3143
# perhaps prepare the commit; get the message; then actually commit
3144
3207
raise errors.BzrCommandError("No changes to commit."
3145
3208
" Use --unchanged to commit anyhow.")
3146
3209
except ConflictsInTree:
3151
3214
raise errors.BzrCommandError("Commit refused because there are"
3152
3215
" unknown files in the working tree.")
3153
3216
except errors.BoundBranchOutOfDate, e:
3154
raise errors.BzrCommandError(str(e) + "\n"
3155
'To commit to master branch, run update and then commit.\n'
3156
'You can also pass --local to commit to continue working '
3217
e.extra_help = ("\n"
3218
'To commit to master branch, run update and then commit.\n'
3219
'You can also pass --local to commit to continue working '
3160
3224
class cmd_check(Command):
3161
"""Validate working tree structure, branch consistency and repository history.
3225
__doc__ = """Validate working tree structure, branch consistency and repository history.
3163
3227
This command checks various invariants about branch and repository storage
3164
3228
to detect data corruption or bzr bugs.
3273
3338
encoding_type = 'replace'
3275
3340
@display_command
3276
def run(self, email=False, branch=False, name=None):
3341
def run(self, email=False, branch=False, name=None, directory=None):
3277
3342
if name is None:
3278
# use branch if we're inside one; otherwise global config
3280
c = Branch.open_containing('.')[0].get_config()
3281
except errors.NotBranchError:
3282
c = config.GlobalConfig()
3343
if directory is None:
3344
# use branch if we're inside one; otherwise global config
3346
c = Branch.open_containing(u'.')[0].get_config()
3347
except errors.NotBranchError:
3348
c = _mod_config.GlobalConfig()
3350
c = Branch.open(directory).get_config()
3284
3352
self.outf.write(c.user_email() + '\n')
3289
3357
# display a warning if an email address isn't included in the given name.
3291
config.extract_email_address(name)
3359
_mod_config.extract_email_address(name)
3292
3360
except errors.NoEmailInUsername, e:
3293
3361
warning('"%s" does not seem to contain an email address. '
3294
3362
'This is allowed, but not recommended.', name)
3296
3364
# use global config unless --branch given
3298
c = Branch.open_containing('.')[0].get_config()
3366
if directory is None:
3367
c = Branch.open_containing(u'.')[0].get_config()
3369
c = Branch.open(directory).get_config()
3300
c = config.GlobalConfig()
3371
c = _mod_config.GlobalConfig()
3301
3372
c.set_user_option('email', name)
3304
3375
class cmd_nick(Command):
3305
"""Print or set the branch nickname.
3376
__doc__ = """Print or set the branch nickname.
3307
3378
If unset, the tree root directory name is used as the nickname.
3308
3379
To print the current nickname, execute with no argument.
3369
3441
'bzr alias --remove expects an alias to remove.')
3370
3442
# If alias is not found, print something like:
3371
3443
# unalias: foo: not found
3372
c = config.GlobalConfig()
3444
c = _mod_config.GlobalConfig()
3373
3445
c.unset_alias(alias_name)
3375
3447
@display_command
3376
3448
def print_aliases(self):
3377
3449
"""Print out the defined aliases in a similar format to bash."""
3378
aliases = config.GlobalConfig().get_aliases()
3450
aliases = _mod_config.GlobalConfig().get_aliases()
3379
3451
for key, value in sorted(aliases.iteritems()):
3380
3452
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3392
3464
def set_alias(self, alias_name, alias_command):
3393
3465
"""Save the alias in the global config."""
3394
c = config.GlobalConfig()
3466
c = _mod_config.GlobalConfig()
3395
3467
c.set_alias(alias_name, alias_command)
3398
3470
class cmd_selftest(Command):
3399
"""Run internal test suite.
3471
__doc__ = """Run internal test suite.
3401
3473
If arguments are given, they are regular expressions that say which tests
3402
3474
should run. Tests matching any expression are run, and other tests are
3470
3545
'throughout the test suite.',
3471
3546
type=get_transport_type),
3472
3547
Option('benchmark',
3473
help='Run the benchmarks rather than selftests.'),
3548
help='Run the benchmarks rather than selftests.',
3474
3550
Option('lsprof-timed',
3475
3551
help='Generate lsprof output for benchmarked'
3476
3552
' sections of code.'),
3477
3553
Option('lsprof-tests',
3478
3554
help='Generate lsprof output for each test.'),
3479
Option('cache-dir', type=str,
3480
help='Cache intermediate benchmark output in this '
3482
3555
Option('first',
3483
3556
help='Run all tests, but run specified tests first.',
3484
3557
short_name='f',
3519
3592
def run(self, testspecs_list=None, verbose=False, one=False,
3520
3593
transport=None, benchmark=None,
3521
lsprof_timed=None, cache_dir=None,
3522
3595
first=False, list_only=False,
3523
3596
randomize=None, exclude=None, strict=False,
3524
3597
load_list=None, debugflag=None, starting_with=None, subunit=False,
3525
3598
parallel=None, lsprof_tests=False):
3526
from bzrlib.tests import selftest
3527
import bzrlib.benchmarks as benchmarks
3528
from bzrlib.benchmarks import tree_creator
3530
# Make deprecation warnings visible, unless -Werror is set
3531
symbol_versioning.activate_deprecation_warnings(override=False)
3533
if cache_dir is not None:
3534
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3599
from bzrlib import tests
3535
3601
if testspecs_list is not None:
3536
3602
pattern = '|'.join(testspecs_list)
3543
3609
raise errors.BzrCommandError("subunit not available. subunit "
3544
3610
"needs to be installed to use --subunit.")
3545
3611
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3612
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3613
# stdout, which would corrupt the subunit stream.
3614
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3615
# following code can be deleted when it's sufficiently deployed
3616
# -- vila/mgz 20100514
3617
if (sys.platform == "win32"
3618
and getattr(sys.stdout, 'fileno', None) is not None):
3620
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3547
3622
self.additional_selftest_args.setdefault(
3548
3623
'suite_decorators', []).append(parallel)
3550
test_suite_factory = benchmarks.test_suite
3551
# Unless user explicitly asks for quiet, be verbose in benchmarks
3552
verbose = not is_quiet()
3553
# TODO: should possibly lock the history file...
3554
benchfile = open(".perf_history", "at", buffering=1)
3555
self.add_cleanup(benchfile.close)
3557
test_suite_factory = None
3625
raise errors.BzrCommandError(
3626
"--benchmark is no longer supported from bzr 2.2; "
3627
"use bzr-usertest instead")
3628
test_suite_factory = None
3559
3629
selftest_kwargs = {"verbose": verbose,
3560
3630
"pattern": pattern,
3561
3631
"stop_on_failure": one,
3574
3643
"starting_with": starting_with
3576
3645
selftest_kwargs.update(self.additional_selftest_args)
3577
result = selftest(**selftest_kwargs)
3647
# Make deprecation warnings visible, unless -Werror is set
3648
cleanup = symbol_versioning.activate_deprecation_warnings(
3651
result = tests.selftest(**selftest_kwargs)
3578
3654
return int(not result)
3581
3657
class cmd_version(Command):
3582
"""Show version of bzr."""
3658
__doc__ = """Show version of bzr."""
3584
3660
encoding_type = 'replace'
3585
3661
takes_options = [
3598
3674
class cmd_rocks(Command):
3599
"""Statement of optimism."""
3675
__doc__ = """Statement of optimism."""
3603
3679
@display_command
3605
print "It sure does!"
3681
self.outf.write("It sure does!\n")
3608
3684
class cmd_find_merge_base(Command):
3609
"""Find and print a base revision for merging two branches."""
3685
__doc__ = """Find and print a base revision for merging two branches."""
3610
3686
# TODO: Options to specify revisions on either side, as if
3611
3687
# merging only part of the history.
3612
3688
takes_args = ['branch', 'other']
3619
3695
branch1 = Branch.open_containing(branch)[0]
3620
3696
branch2 = Branch.open_containing(other)[0]
3622
self.add_cleanup(branch1.unlock)
3624
self.add_cleanup(branch2.unlock)
3697
self.add_cleanup(branch1.lock_read().unlock)
3698
self.add_cleanup(branch2.lock_read().unlock)
3625
3699
last1 = ensure_null(branch1.last_revision())
3626
3700
last2 = ensure_null(branch2.last_revision())
3628
3702
graph = branch1.repository.get_graph(branch2.repository)
3629
3703
base_rev_id = graph.find_unique_lca(last1, last2)
3631
print 'merge base is revision %s' % base_rev_id
3705
self.outf.write('merge base is revision %s\n' % base_rev_id)
3634
3708
class cmd_merge(Command):
3635
"""Perform a three-way merge.
3709
__doc__ = """Perform a three-way merge.
3637
3711
The source of the merge can be specified either in the form of a branch,
3638
3712
or in the form of a path to a file containing a merge directive generated
3721
3795
' completely merged into the source, pull from the'
3722
3796
' source rather than merging. When this happens,'
3723
3797
' you do not need to commit the result.'),
3798
custom_help('directory',
3725
3799
help='Branch to merge into, '
3726
'rather than the one containing the working directory.',
3800
'rather than the one containing the working directory.'),
3730
3801
Option('preview', help='Instead of merging, show a diff of the'
3732
3803
Option('interactive', help='Select changes interactively.',
3833
3903
def _do_preview(self, merger):
3834
3904
from bzrlib.diff import show_diff_trees
3835
3905
result_tree = self._get_preview(merger)
3906
path_encoding = osutils.get_diff_header_encoding()
3836
3907
show_diff_trees(merger.this_tree, result_tree, self.outf,
3837
old_label='', new_label='')
3908
old_label='', new_label='',
3909
path_encoding=path_encoding)
3839
3911
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3840
3912
merger.change_reporter = change_reporter
4025
4097
def run(self, file_list=None, merge_type=None, show_base=False,
4026
4098
reprocess=False):
4099
from bzrlib.conflicts import restore
4027
4100
if merge_type is None:
4028
4101
merge_type = _mod_merge.Merge3Merger
4029
tree, file_list = tree_files(file_list)
4031
self.add_cleanup(tree.unlock)
4102
tree, file_list = WorkingTree.open_containing_paths(file_list)
4103
self.add_cleanup(tree.lock_write().unlock)
4032
4104
parents = tree.get_parent_ids()
4033
4105
if len(parents) != 2:
4034
4106
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4267
4339
theirs_only=False,
4268
4340
log_format=None, long=False, short=False, line=False,
4269
4341
show_ids=False, verbose=False, this=False, other=False,
4270
include_merges=False, revision=None, my_revision=None):
4342
include_merges=False, revision=None, my_revision=None,
4271
4344
from bzrlib.missing import find_unmerged, iter_log_revisions
4272
4345
def message(s):
4273
4346
if not is_quiet():
4301
4376
remote_branch = Branch.open(other_branch)
4302
4377
if remote_branch.base == local_branch.base:
4303
4378
remote_branch = local_branch
4380
self.add_cleanup(remote_branch.lock_read().unlock)
4305
local_branch.lock_read()
4306
self.add_cleanup(local_branch.unlock)
4307
4382
local_revid_range = _revision_range_to_revid_range(
4308
4383
_get_revision_range(my_revision, local_branch,
4311
remote_branch.lock_read()
4312
self.add_cleanup(remote_branch.unlock)
4313
4386
remote_revid_range = _revision_range_to_revid_range(
4314
4387
_get_revision_range(revision,
4315
4388
remote_branch, self.name()))
4376
4448
class cmd_pack(Command):
4377
"""Compress the data within a repository."""
4449
__doc__ = """Compress the data within a repository.
4451
This operation compresses the data within a bazaar repository. As
4452
bazaar supports automatic packing of repository, this operation is
4453
normally not required to be done manually.
4455
During the pack operation, bazaar takes a backup of existing repository
4456
data, i.e. pack files. This backup is eventually removed by bazaar
4457
automatically when it is safe to do so. To save disk space by removing
4458
the backed up pack files, the --clean-obsolete-packs option may be
4461
Warning: If you use --clean-obsolete-packs and your machine crashes
4462
during or immediately after repacking, you may be left with a state
4463
where the deletion has been written to disk but the new packs have not
4464
been. In this case the repository may be unusable.
4379
4467
_see_also = ['repositories']
4380
4468
takes_args = ['branch_or_repo?']
4470
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4382
def run(self, branch_or_repo='.'):
4473
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4383
4474
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4385
4476
branch = dir.open_branch()
4386
4477
repository = branch.repository
4387
4478
except errors.NotBranchError:
4388
4479
repository = dir.open_repository()
4480
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4392
4483
class cmd_plugins(Command):
4393
"""List the installed plugins.
4484
__doc__ = """List the installed plugins.
4395
4486
This command displays the list of installed plugins including
4396
4487
version of plugin and a short description of each.
4427
4518
doc = '(no description)'
4428
4519
result.append((name_ver, doc, plugin.path()))
4429
4520
for name_ver, doc, path in sorted(result):
4521
self.outf.write("%s\n" % name_ver)
4522
self.outf.write(" %s\n" % doc)
4524
self.outf.write(" %s\n" % path)
4525
self.outf.write("\n")
4437
4528
class cmd_testament(Command):
4438
"""Show testament (signing-form) of a revision."""
4529
__doc__ = """Show testament (signing-form) of a revision."""
4439
4530
takes_options = [
4441
4532
Option('long', help='Produce long-format testament.'),
4484
4574
Option('long', help='Show commit date in annotations.'),
4488
4579
encoding_type = 'exact'
4490
4581
@display_command
4491
4582
def run(self, filename, all=False, long=False, revision=None,
4583
show_ids=False, directory=None):
4493
4584
from bzrlib.annotate import annotate_file, annotate_file_tree
4494
4585
wt, branch, relpath = \
4495
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4586
_open_directory_or_containing_tree_or_branch(filename, directory)
4496
4587
if wt is not None:
4498
self.add_cleanup(wt.unlock)
4588
self.add_cleanup(wt.lock_read().unlock)
4501
self.add_cleanup(branch.unlock)
4590
self.add_cleanup(branch.lock_read().unlock)
4502
4591
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4504
self.add_cleanup(tree.unlock)
4592
self.add_cleanup(tree.lock_read().unlock)
4505
4593
if wt is not None:
4506
4594
file_id = wt.path2id(relpath)
4522
4610
class cmd_re_sign(Command):
4523
"""Create a digital signature for an existing revision."""
4611
__doc__ = """Create a digital signature for an existing revision."""
4524
4612
# TODO be able to replace existing ones.
4526
4614
hidden = True # is this right ?
4527
4615
takes_args = ['revision_id*']
4528
takes_options = ['revision']
4616
takes_options = ['directory', 'revision']
4530
def run(self, revision_id_list=None, revision=None):
4618
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4531
4619
if revision_id_list is not None and revision is not None:
4532
4620
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4533
4621
if revision_id_list is None and revision is None:
4534
4622
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4535
b = WorkingTree.open_containing(u'.')[0].branch
4537
self.add_cleanup(b.unlock)
4623
b = WorkingTree.open_containing(directory)[0].branch
4624
self.add_cleanup(b.lock_write().unlock)
4538
4625
return self._run(b, revision_id_list, revision)
4540
4627
def _run(self, b, revision_id_list, revision):
4599
4687
_see_also = ['checkouts', 'unbind']
4600
4688
takes_args = ['location?']
4689
takes_options = ['directory']
4603
def run(self, location=None):
4604
b, relpath = Branch.open_containing(u'.')
4691
def run(self, location=None, directory=u'.'):
4692
b, relpath = Branch.open_containing(directory)
4605
4693
if location is None:
4607
4695
location = b.get_old_bound_location()
4635
4723
_see_also = ['checkouts', 'bind']
4636
4724
takes_args = []
4725
takes_options = ['directory']
4640
b, relpath = Branch.open_containing(u'.')
4727
def run(self, directory=u'.'):
4728
b, relpath = Branch.open_containing(directory)
4641
4729
if not b.unbind():
4642
4730
raise errors.BzrCommandError('Local branch is not bound')
4645
4733
class cmd_uncommit(Command):
4646
"""Remove the last committed revision.
4734
__doc__ = """Remove the last committed revision.
4648
4736
--verbose will print out what is being removed.
4649
4737
--dry-run will go through all the motions, but not actually
4689
4777
b = control.open_branch()
4691
4779
if tree is not None:
4693
self.add_cleanup(tree.unlock)
4780
self.add_cleanup(tree.lock_write().unlock)
4696
self.add_cleanup(b.unlock)
4782
self.add_cleanup(b.lock_write().unlock)
4697
4783
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4699
4785
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4733
4818
end_revision=last_revno)
4736
ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
4821
self.outf.write('Dry-run, pretending to remove'
4822
' the above revisions.\n')
4738
ui.ui_factory.note('The above revision(s) will be removed.')
4824
self.outf.write('The above revision(s) will be removed.\n')
4741
if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4742
ui.ui_factory.note('Canceled')
4827
if not ui.ui_factory.confirm_action(
4828
'Uncommit these revisions',
4829
'bzrlib.builtins.uncommit',
4831
self.outf.write('Canceled\n')
4745
4834
mutter('Uncommitting from {%s} to {%s}',
4746
4835
last_rev_id, rev_id)
4747
4836
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4748
4837
revno=revno, local=local)
4749
ui.ui_factory.note('You can restore the old tip by running:\n'
4750
' bzr pull . -r revid:%s' % last_rev_id)
4838
self.outf.write('You can restore the old tip by running:\n'
4839
' bzr pull . -r revid:%s\n' % last_rev_id)
4753
4842
class cmd_break_lock(Command):
4754
"""Break a dead lock on a repository, branch or working directory.
4843
__doc__ = """Break a dead lock.
4845
This command breaks a lock on a repository, branch, working directory or
4756
4848
CAUTION: Locks should only be broken when you are sure that the process
4757
4849
holding the lock has been stopped.
4764
4856
bzr break-lock bzr+ssh://example.com/bzr/foo
4857
bzr break-lock --conf ~/.bazaar
4766
4860
takes_args = ['location?']
4863
help='LOCATION is the directory where the config lock is.'),
4865
help='Do not ask for confirmation before breaking the lock.'),
4768
def run(self, location=None, show=False):
4868
def run(self, location=None, config=False, force=False):
4769
4869
if location is None:
4770
4870
location = u'.'
4771
control, relpath = bzrdir.BzrDir.open_containing(location)
4773
control.break_lock()
4774
except NotImplementedError:
4872
ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
4874
{'bzrlib.lockdir.break': True})
4876
conf = _mod_config.LockableConfig(file_name=location)
4879
control, relpath = bzrdir.BzrDir.open_containing(location)
4881
control.break_lock()
4882
except NotImplementedError:
4778
4886
class cmd_wait_until_signalled(Command):
4779
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4887
__doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4781
4889
This just prints a line to signal when it is ready, then blocks on stdin.
4843
4950
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4844
4951
protocol=None):
4845
from bzrlib.transport import get_transport, transport_server_registry
4952
from bzrlib import transport
4846
4953
if directory is None:
4847
4954
directory = os.getcwd()
4848
4955
if protocol is None:
4849
protocol = transport_server_registry.get()
4956
protocol = transport.transport_server_registry.get()
4850
4957
host, port = self.get_host_and_port(port)
4851
4958
url = urlutils.local_path_to_url(directory)
4852
4959
if not allow_writes:
4853
4960
url = 'readonly+' + url
4854
transport = get_transport(url)
4855
protocol(transport, host, port, inet)
4961
t = transport.get_transport(url)
4962
protocol(t, host, port, inet)
4858
4965
class cmd_join(Command):
4859
"""Combine a tree into its containing tree.
4966
__doc__ = """Combine a tree into its containing tree.
4861
4968
This command requires the target tree to be in a rich-root format.
4969
5077
encoding_type = 'exact'
4971
5079
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4972
sign=False, revision=None, mail_to=None, message=None):
5080
sign=False, revision=None, mail_to=None, message=None,
4973
5082
from bzrlib.revision import ensure_null, NULL_REVISION
4974
5083
include_patch, include_bundle = {
4975
5084
'plain': (False, False),
4976
5085
'diff': (True, False),
4977
5086
'bundle': (True, True),
4979
branch = Branch.open('.')
5088
branch = Branch.open(directory)
4980
5089
stored_submit_branch = branch.get_submit_branch()
4981
5090
if submit_branch is None:
4982
5091
submit_branch = stored_submit_branch
5232
5341
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5233
5342
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5344
If no tag name is specified it will be determined through the
5345
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5346
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5236
5350
_see_also = ['commit', 'tags']
5237
takes_args = ['tag_name']
5351
takes_args = ['tag_name?']
5238
5352
takes_options = [
5239
5353
Option('delete',
5240
5354
help='Delete this tag rather than placing it.',
5243
help='Branch in which to place the tag.',
5356
custom_help('directory',
5357
help='Branch in which to place the tag.'),
5247
5358
Option('force',
5248
5359
help='Replace existing tags.',
5253
def run(self, tag_name,
5364
def run(self, tag_name=None,
5259
5370
branch, relpath = Branch.open_containing(directory)
5261
self.add_cleanup(branch.unlock)
5371
self.add_cleanup(branch.lock_write().unlock)
5373
if tag_name is None:
5374
raise errors.BzrCommandError("No tag specified to delete.")
5263
5375
branch.tags.delete_tag(tag_name)
5264
5376
self.outf.write('Deleted tag %s.\n' % tag_name)
5280
5397
class cmd_tags(Command):
5398
__doc__ = """List tags.
5283
5400
This command shows a table of tag names and the revisions they reference.
5286
5403
_see_also = ['tag']
5287
5404
takes_options = [
5289
help='Branch whose tags should be displayed.',
5405
custom_help('directory',
5406
help='Branch whose tags should be displayed.'),
5293
5407
RegistryOption.from_kwargs('sort',
5294
5408
'Sort tags by different criteria.', title='Sorting',
5295
alpha='Sort tags lexicographically (default).',
5409
natural='Sort numeric substrings as numbers:'
5410
' suitable for version numbers. (default)',
5411
alpha='Sort tags lexicographically.',
5296
5412
time='Sort tags chronologically.',
5321
5436
# only show revisions between revid1 and revid2 (inclusive)
5322
5437
tags = [(tag, revid) for tag, revid in tags if
5323
5438
graph.is_between(revid, revid1, revid2)]
5439
if sort == 'natural':
5440
def natural_sort_key(tag):
5441
return [f(s) for f,s in
5442
zip(itertools.cycle((unicode.lower,int)),
5443
re.split('([0-9]+)', tag[0]))]
5444
tags.sort(key=natural_sort_key)
5445
elif sort == 'alpha':
5326
5447
elif sort == 'time':
5327
5448
timestamps = {}
5477
5599
def run(self, to_location=None, force=False, create_branch=False,
5600
revision=None, directory=u'.'):
5479
5601
from bzrlib import switch
5602
tree_location = directory
5481
5603
revision = _get_one_revision('switch', revision)
5482
5604
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5483
5605
if to_location is None:
5484
5606
if revision is None:
5485
5607
raise errors.BzrCommandError('You must supply either a'
5486
5608
' revision or a location')
5609
to_location = tree_location
5489
5611
branch = control_dir.open_branch()
5490
5612
had_explicit_nick = branch.get_config().has_explicit_nickname()
5712
5835
self.outf.write(" <no hooks installed>\n")
5838
class cmd_remove_branch(Command):
5839
__doc__ = """Remove a branch.
5841
This will remove the branch from the specified location but
5842
will keep any working tree or repository in place.
5846
Remove the branch at repo/trunk::
5848
bzr remove-branch repo/trunk
5852
takes_args = ["location?"]
5854
aliases = ["rmbranch"]
5856
def run(self, location=None):
5857
if location is None:
5859
branch = Branch.open_containing(location)[0]
5860
branch.bzrdir.destroy_branch()
5715
5863
class cmd_shelve(Command):
5716
"""Temporarily set aside some changes from the current tree.
5864
__doc__ = """Temporarily set aside some changes from the current tree.
5718
5866
Shelve allows you to temporarily put changes you've made "on the shelf",
5719
5867
ie. out of the way, until a later time when you can bring them back from
5754
5903
_see_also = ['unshelve']
5756
5905
def run(self, revision=None, all=False, file_list=None, message=None,
5757
writer=None, list=False, destroy=False):
5906
writer=None, list=False, destroy=False, directory=u'.'):
5759
5908
return self.run_for_list()
5760
5909
from bzrlib.shelf_ui import Shelver
5835
5984
To check what clean-tree will do, use --dry-run.
5837
takes_options = [Option('ignored', help='Delete all ignored files.'),
5986
takes_options = ['directory',
5987
Option('ignored', help='Delete all ignored files.'),
5838
5988
Option('detritus', help='Delete conflict files, merge'
5839
5989
' backups, and failed selftest dirs.'),
5840
5990
Option('unknown',
5843
5993
' deleting them.'),
5844
5994
Option('force', help='Do not prompt before deleting.')]
5845
5995
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5996
force=False, directory=u'.'):
5847
5997
from bzrlib.clean_tree import clean_tree
5848
5998
if not (unknown or ignored or detritus):
5852
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5853
dry_run=dry_run, no_prompt=force)
6002
clean_tree(directory, unknown=unknown, ignored=ignored,
6003
detritus=detritus, dry_run=dry_run, no_prompt=force)
5856
6006
class cmd_reference(Command):
5857
"""list, view and set branch locations for nested trees.
6007
__doc__ = """list, view and set branch locations for nested trees.
5859
6009
If no arguments are provided, lists the branch locations for nested trees.
5860
6010
If one argument is provided, display the branch location for that tree.
5900
6050
self.outf.write('%s %s\n' % (path, location))
5903
# these get imported and then picked up by the scan for cmd_*
5904
# TODO: Some more consistent way to split command definitions across files;
5905
# we do need to load at least some information about them to know of
5906
# aliases. ideally we would avoid loading the implementation until the
5907
# details were needed.
5908
from bzrlib.cmd_version_info import cmd_version_info
5909
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5910
from bzrlib.bundle.commands import (
5913
from bzrlib.foreign import cmd_dpush
5914
from bzrlib.sign_my_commits import cmd_sign_my_commits
6053
def _register_lazy_builtins():
6054
# register lazy builtins from other modules; called at startup and should
6055
# be only called once.
6056
for (name, aliases, module_name) in [
6057
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6058
('cmd_dpush', [], 'bzrlib.foreign'),
6059
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6060
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6061
('cmd_conflicts', [], 'bzrlib.conflicts'),
6062
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6064
builtin_command_registry.register_lazy(name, aliases, module_name)