55
55
from bzrlib.branch import Branch
56
56
from bzrlib.conflicts import ConflictList
57
from bzrlib.transport import memory
58
57
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
59
58
from bzrlib.smtp_connection import SMTPConnection
60
59
from bzrlib.workingtree import WorkingTree
63
from bzrlib.commands import (
65
builtin_command_registry,
62
from bzrlib.commands import Command, display_command
68
63
from bzrlib.option import (
235
def _open_directory_or_containing_tree_or_branch(filename, directory):
236
"""Open the tree or branch containing the specified file, unless
237
the --directory option is used to specify a different branch."""
238
if directory is not None:
239
return (None, Branch.open(directory), filename)
240
return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
243
230
# TODO: Make sure no commands unconditionally use the working directory as a
244
231
# branch. If a filename argument is used, the first of them should be used to
245
232
# specify the branch. (Perhaps this can be factored out into some kind of
350
337
takes_args = ['revision_id?']
351
takes_options = ['directory', 'revision']
338
takes_options = ['revision']
352
339
# cat-revision is more for frontends so should be exact
353
340
encoding = 'strict'
355
def print_revision(self, revisions, revid):
356
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
357
record = stream.next()
358
if record.storage_kind == 'absent':
359
raise errors.NoSuchRevision(revisions, revid)
360
revtext = record.get_bytes_as('fulltext')
361
self.outf.write(revtext.decode('utf-8'))
364
def run(self, revision_id=None, revision=None, directory=u'.'):
343
def run(self, revision_id=None, revision=None):
365
344
if revision_id is not None and revision is not None:
366
345
raise errors.BzrCommandError('You can only supply one of'
367
346
' revision_id or --revision')
368
347
if revision_id is None and revision is None:
369
348
raise errors.BzrCommandError('You must supply either'
370
349
' --revision or a revision_id')
371
b = WorkingTree.open_containing(directory)[0].branch
373
revisions = b.repository.revisions
374
if revisions is None:
375
raise errors.BzrCommandError('Repository %r does not support '
376
'access to raw revision texts')
378
b.repository.lock_read()
380
# TODO: jam 20060112 should cat-revision always output utf-8?
381
if revision_id is not None:
382
revision_id = osutils.safe_revision_id(revision_id, warn=False)
384
self.print_revision(revisions, revision_id)
385
except errors.NoSuchRevision:
386
msg = "The repository %s contains no revision %s." % (
387
b.repository.base, revision_id)
388
raise errors.BzrCommandError(msg)
389
elif revision is not None:
392
raise errors.BzrCommandError(
393
'You cannot specify a NULL revision.')
394
rev_id = rev.as_revision_id(b)
395
self.print_revision(revisions, rev_id)
397
b.repository.unlock()
350
b = WorkingTree.open_containing(u'.')[0].branch
352
# TODO: jam 20060112 should cat-revision always output utf-8?
353
if revision_id is not None:
354
revision_id = osutils.safe_revision_id(revision_id, warn=False)
356
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
357
except errors.NoSuchRevision:
358
msg = "The repository %s contains no revision %s." % (b.repository.base,
360
raise errors.BzrCommandError(msg)
361
elif revision is not None:
364
raise errors.BzrCommandError('You cannot specify a NULL'
366
rev_id = rev.as_revision_id(b)
367
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
400
370
class cmd_dump_btree(Command):
401
__doc__ = """Dump the contents of a btree index file to stdout.
371
"""Dump the contents of a btree index file to stdout.
403
373
PATH is a btree index file, it can be any URL. This includes things like
404
374
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
468
438
for node in bt.iter_all_entries():
469
439
# Node is made up of:
470
440
# (index, key, value, [references])
474
refs_as_tuples = None
476
refs_as_tuples = static_tuple.as_tuples(refs)
441
refs_as_tuples = static_tuple.as_tuples(node[3])
477
442
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
478
443
self.outf.write('%s\n' % (as_tuple,))
481
446
class cmd_remove_tree(Command):
482
__doc__ = """Remove the working tree from a given branch/checkout.
447
"""Remove the working tree from a given branch/checkout.
484
449
Since a lightweight checkout is little more than a working tree
485
450
this will refuse to run against one.
487
452
To re-create the working tree, use "bzr checkout".
489
454
_see_also = ['checkout', 'working-trees']
490
takes_args = ['location*']
455
takes_args = ['location?']
491
456
takes_options = [
493
458
help='Remove the working tree even if it has '
494
'uncommitted or shelved changes.'),
459
'uncommitted changes.'),
497
def run(self, location_list, force=False):
498
if not location_list:
501
for location in location_list:
502
d = bzrdir.BzrDir.open(location)
505
working = d.open_workingtree()
506
except errors.NoWorkingTree:
507
raise errors.BzrCommandError("No working tree to remove")
508
except errors.NotLocalUrl:
509
raise errors.BzrCommandError("You cannot remove the working tree"
512
if (working.has_changes()):
513
raise errors.UncommittedChanges(working)
514
if working.get_shelf_manager().last_shelf() is not None:
515
raise errors.ShelvedChanges(working)
517
if working.user_url != working.branch.user_url:
518
raise errors.BzrCommandError("You cannot remove the working tree"
519
" from a lightweight checkout")
521
d.destroy_workingtree()
462
def run(self, location='.', force=False):
463
d = bzrdir.BzrDir.open(location)
466
working = d.open_workingtree()
467
except errors.NoWorkingTree:
468
raise errors.BzrCommandError("No working tree to remove")
469
except errors.NotLocalUrl:
470
raise errors.BzrCommandError("You cannot remove the working tree"
473
if (working.has_changes()):
474
raise errors.UncommittedChanges(working)
476
working_path = working.bzrdir.root_transport.base
477
branch_path = working.branch.bzrdir.root_transport.base
478
if working_path != branch_path:
479
raise errors.BzrCommandError("You cannot remove the working tree"
480
" from a lightweight checkout")
482
d.destroy_workingtree()
524
485
class cmd_revno(Command):
525
__doc__ = """Show current revision number.
486
"""Show current revision number.
527
488
This is equal to the number of revisions on this branch.
549
511
revno = ".".join(str(n) for n in revno_t)
551
513
b = Branch.open_containing(location)[0]
552
self.add_cleanup(b.lock_read().unlock)
515
self.add_cleanup(b.unlock)
553
516
revno = b.revno()
554
517
self.cleanup_now()
555
518
self.outf.write(str(revno) + '\n')
558
521
class cmd_revision_info(Command):
559
__doc__ = """Show revision number and revision id for a given revision identifier.
522
"""Show revision number and revision id for a given revision identifier.
562
525
takes_args = ['revision_info*']
563
526
takes_options = [
565
custom_help('directory',
566
529
help='Branch to examine, '
567
'rather than the one containing the working directory.'),
530
'rather than the one containing the working directory.',
568
534
Option('tree', help='Show revno of working tree'),
709
678
def run(self, dir_list):
710
679
for d in dir_list:
711
681
wt, dd = WorkingTree.open_containing(d)
712
base = os.path.dirname(dd)
713
id = wt.path2id(base)
717
self.outf.write('added %s\n' % d)
719
raise errors.NotVersionedError(path=base)
683
self.outf.write('added %s\n' % d)
722
686
class cmd_relpath(Command):
723
__doc__ = """Show path of a file relative to root"""
687
"""Show path of a file relative to root"""
725
689
takes_args = ['filename']
833
799
if len(names_list) < 2:
834
800
raise errors.BzrCommandError("missing file argument")
835
801
tree, rel_names = tree_files(names_list, canonicalize=False)
836
self.add_cleanup(tree.lock_tree_write().unlock)
802
tree.lock_tree_write()
803
self.add_cleanup(tree.unlock)
837
804
self._run(tree, names_list, rel_names, after)
839
806
def run_auto(self, names_list, after, dry_run):
844
811
raise errors.BzrCommandError('--after cannot be specified with'
846
813
work_tree, file_list = tree_files(names_list, default_branch='.')
847
self.add_cleanup(work_tree.lock_tree_write().unlock)
814
work_tree.lock_tree_write()
815
self.add_cleanup(work_tree.unlock)
848
816
rename_map.RenameMap.guess_renames(work_tree, dry_run)
850
818
def _run(self, tree, names_list, rel_names, after):
958
926
takes_options = ['remember', 'overwrite', 'revision',
959
927
custom_help('verbose',
960
928
help='Show logs of pulled revisions.'),
961
custom_help('directory',
962
930
help='Branch to pull into, '
963
'rather than the one containing the working directory.'),
931
'rather than the one containing the working directory.',
965
936
help="Perform a local pull in a bound "
966
937
"branch. Local pulls are not applied to "
1023
992
branch_from = Branch.open(location,
1024
993
possible_transports=possible_transports)
1025
self.add_cleanup(branch_from.lock_read().unlock)
1027
995
if branch_to.get_parent() is None or remember:
1028
996
branch_to.set_parent(branch_from.base)
998
if branch_from is not branch_to:
999
branch_from.lock_read()
1000
self.add_cleanup(branch_from.unlock)
1030
1001
if revision is not None:
1031
1002
revision_id = revision.as_revision_id(branch_from)
1004
branch_to.lock_write()
1005
self.add_cleanup(branch_to.unlock)
1033
1006
if tree_to is not None:
1034
1007
view_info = _get_view_info_for_change_reporter(tree_to)
1035
1008
change_reporter = delta._ChangeReporter(
1080
1053
Option('create-prefix',
1081
1054
help='Create the path leading up to the branch '
1082
1055
'if it does not already exist.'),
1083
custom_help('directory',
1084
1057
help='Branch to push from, '
1085
'rather than the one containing the working directory.'),
1058
'rather than the one containing the working directory.',
1086
1062
Option('use-existing-dir',
1087
1063
help='By default push will fail if the target'
1088
1064
' directory exists, but does not already'
1114
1090
# Get the source branch
1115
1091
(tree, br_from,
1116
1092
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1094
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1095
if strict is None: strict = True # default value
1117
1096
# Get the tip's revision_id
1118
1097
revision = _get_one_revision('push', revision)
1119
1098
if revision is not None:
1120
1099
revision_id = revision.in_history(br_from).rev_id
1122
1101
revision_id = None
1123
if tree is not None and revision_id is None:
1124
tree.check_changed_or_out_of_date(
1125
strict, 'push_strict',
1126
more_error='Use --no-strict to force the push.',
1127
more_warning='Uncommitted changes will not be pushed.')
1102
if strict and tree is not None and revision_id is None:
1103
if (tree.has_changes()):
1104
raise errors.UncommittedChanges(
1105
tree, more='Use --no-strict to force the push.')
1106
if tree.last_revision() != tree.branch.last_revision():
1107
# The tree has lost sync with its branch, there is little
1108
# chance that the user is aware of it but he can still force
1109
# the push with --no-strict
1110
raise errors.OutOfDateTree(
1111
tree, more='Use --no-strict to force the push.')
1128
1113
# Get the stacked_on branch, if any
1129
1114
if stacked_on is not None:
1130
1115
stacked_on = urlutils.normalize_url(stacked_on)
1401
1389
master = branch.get_master_branch(
1402
1390
possible_transports=possible_transports)
1403
1391
if master is not None:
1404
1393
branch_location = master.base
1395
tree.lock_tree_write()
1407
1396
branch_location = tree.branch.base
1408
tree.lock_tree_write()
1409
1397
self.add_cleanup(tree.unlock)
1410
1398
# get rid of the final '/' and be ready for display
1411
branch_location = urlutils.unescape_for_display(
1412
branch_location.rstrip('/'),
1399
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1414
1401
existing_pending_merges = tree.get_parent_ids()[1:]
1415
1402
if master is None:
1425
1412
revision_id = branch.last_revision()
1426
1413
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1427
revno = branch.revision_id_to_dotted_revno(revision_id)
1428
note("Tree is up to date at revision %s of branch %s" %
1429
('.'.join(map(str, revno)), branch_location))
1414
revno = branch.revision_id_to_revno(revision_id)
1415
note("Tree is up to date at revision %d of branch %s" %
1416
(revno, branch_location))
1431
1418
view_info = _get_view_info_for_change_reporter(tree)
1432
1419
change_reporter = delta._ChangeReporter(
1444
1431
"bzr update --revision only works"
1445
1432
" for a revision in the branch history"
1446
1433
% (e.revision))
1447
revno = tree.branch.revision_id_to_dotted_revno(
1434
revno = tree.branch.revision_id_to_revno(
1448
1435
_mod_revision.ensure_null(tree.last_revision()))
1449
note('Updated to revision %s of branch %s' %
1450
('.'.join(map(str, revno)), branch_location))
1451
parent_ids = tree.get_parent_ids()
1452
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1436
note('Updated to revision %d of branch %s' %
1437
(revno, branch_location))
1438
if tree.get_parent_ids()[1:] != existing_pending_merges:
1453
1439
note('Your local commits will now show as pending merges with '
1454
1440
"'bzr status', and can be committed with 'bzr commit'.")
1455
1441
if conflicts != 0:
1930
1917
help='Use this command to compare files.',
1933
RegistryOption('format',
1934
help='Diff format to use.',
1935
lazy_registry=('bzrlib.diff', 'format_registry'),
1936
value_switches=False, title='Diff format'),
1938
1921
aliases = ['di', 'dif']
1939
1922
encoding_type = 'exact'
1941
1924
@display_command
1942
1925
def run(self, revision=None, file_list=None, diff_options=None,
1943
prefix=None, old=None, new=None, using=None, format=None):
1944
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1926
prefix=None, old=None, new=None, using=None):
1927
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1947
1929
if (prefix is None) or (prefix == '0'):
1948
1930
# diff -p0 format
1962
1944
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1963
1945
' one or two revision specifiers')
1965
if using is not None and format is not None:
1966
raise errors.BzrCommandError('--using and --format are mutually '
1969
1947
(old_tree, new_tree,
1970
1948
old_branch, new_branch,
1971
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1972
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1973
# GNU diff on Windows uses ANSI encoding for filenames
1974
path_encoding = osutils.get_diff_header_encoding()
1949
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1950
file_list, revision, old, new, apply_view=True)
1975
1951
return show_diff_trees(old_tree, new_tree, sys.stdout,
1976
1952
specific_files=specific_files,
1977
1953
external_diff_options=diff_options,
1978
1954
old_label=old_label, new_label=new_label,
1979
extra_trees=extra_trees,
1980
path_encoding=path_encoding,
1955
extra_trees=extra_trees, using=using)
1985
1958
class cmd_deleted(Command):
1986
__doc__ = """List files deleted in the working tree.
1959
"""List files deleted in the working tree.
1988
1961
# TODO: Show files deleted since a previous revision, or
1989
1962
# between two revisions.
1992
1965
# level of effort but possibly much less IO. (Or possibly not,
1993
1966
# if the directories are very large...)
1994
1967
_see_also = ['status', 'ls']
1995
takes_options = ['directory', 'show-ids']
1968
takes_options = ['show-ids']
1997
1970
@display_command
1998
def run(self, show_ids=False, directory=u'.'):
1999
tree = WorkingTree.open_containing(directory)[0]
2000
self.add_cleanup(tree.lock_read().unlock)
1971
def run(self, show_ids=False):
1972
tree = WorkingTree.open_containing(u'.')[0]
1974
self.add_cleanup(tree.unlock)
2001
1975
old = tree.basis_tree()
2002
self.add_cleanup(old.lock_read().unlock)
1977
self.add_cleanup(old.unlock)
2003
1978
for path, ie in old.inventory.iter_entries():
2004
1979
if not tree.has_id(ie.file_id):
2005
1980
self.outf.write(path)
2012
1987
class cmd_modified(Command):
2013
__doc__ = """List files modified in working tree.
1988
"""List files modified in working tree.
2017
1992
_see_also = ['status', 'ls']
2018
takes_options = ['directory', 'null']
1995
help='Write an ascii NUL (\\0) separator '
1996
'between files rather than a newline.')
2020
1999
@display_command
2021
def run(self, null=False, directory=u'.'):
2022
tree = WorkingTree.open_containing(directory)[0]
2000
def run(self, null=False):
2001
tree = WorkingTree.open_containing(u'.')[0]
2023
2002
td = tree.changes_from(tree.basis_tree())
2024
2003
for path, id, kind, text_modified, meta_modified in td.modified:
2031
2010
class cmd_added(Command):
2032
__doc__ = """List files added in working tree.
2011
"""List files added in working tree.
2036
2015
_see_also = ['status', 'ls']
2037
takes_options = ['directory', 'null']
2018
help='Write an ascii NUL (\\0) separator '
2019
'between files rather than a newline.')
2039
2022
@display_command
2040
def run(self, null=False, directory=u'.'):
2041
wt = WorkingTree.open_containing(directory)[0]
2042
self.add_cleanup(wt.lock_read().unlock)
2023
def run(self, null=False):
2024
wt = WorkingTree.open_containing(u'.')[0]
2026
self.add_cleanup(wt.unlock)
2043
2027
basis = wt.basis_tree()
2044
self.add_cleanup(basis.lock_read().unlock)
2029
self.add_cleanup(basis.unlock)
2045
2030
basis_inv = basis.inventory
2046
2031
inv = wt.inventory
2047
2032
for file_id in inv:
2206
2191
:Tips & tricks:
2208
2193
GUI tools and IDEs are often better at exploring history than command
2209
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2210
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2211
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2212
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2194
line tools. You may prefer qlog or viz from the QBzr and Bzr-Gtk packages
2195
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2196
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2198
Web interfaces are often better at exploring history than command line
2199
tools, particularly for branches on servers. You may prefer Loggerhead
2200
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2214
2202
You may find it useful to add the aliases below to ``bazaar.conf``::
2256
2244
help='Show just the specified revision.'
2257
2245
' See also "help revisionspec".'),
2259
RegistryOption('authors',
2260
'What names to list as authors - first, all or committer.',
2262
lazy_registry=('bzrlib.log', 'author_list_registry'),
2264
2247
Option('levels',
2265
2248
short_name='n',
2266
2249
help='Number of levels to display - 0 for all, 1 for flat.',
2336
2308
# find the file ids to log and check for directory filtering
2337
2309
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2338
revision, file_list, self.add_cleanup)
2310
revision, file_list)
2311
self.add_cleanup(b.unlock)
2339
2312
for relpath, file_id, kind in file_info_list:
2340
2313
if file_id is None:
2341
2314
raise errors.BzrCommandError(
2411
2384
direction=direction, specific_fileids=file_ids,
2412
2385
start_revision=rev1, end_revision=rev2, limit=limit,
2413
2386
message_search=message, delta_type=delta_type,
2414
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2415
exclude_common_ancestry=exclude_common_ancestry,
2387
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2417
2388
Logger(b, rqst).show(lf)
2438
2409
raise errors.BzrCommandError(
2439
2410
"bzr %s doesn't accept two revisions in different"
2440
2411
" branches." % command_name)
2441
if start_spec.spec is None:
2442
# Avoid loading all the history.
2443
rev1 = RevisionInfo(branch, None, None)
2445
rev1 = start_spec.in_history(branch)
2412
rev1 = start_spec.in_history(branch)
2446
2413
# Avoid loading all of history when we know a missing
2447
2414
# end of range means the last revision ...
2448
2415
if end_spec.spec is None:
2490
2457
tree, relpath = WorkingTree.open_containing(filename)
2491
2458
file_id = tree.path2id(relpath)
2492
2459
b = tree.branch
2493
self.add_cleanup(b.lock_read().unlock)
2461
self.add_cleanup(b.unlock)
2494
2462
touching_revs = log.find_touching_revisions(b, file_id)
2495
2463
for revno, revision_id, what in touching_revs:
2496
2464
self.outf.write("%6d %s\n" % (revno, what))
2499
2467
class cmd_ls(Command):
2500
__doc__ = """List files in a tree.
2468
"""List files in a tree.
2503
2471
_see_also = ['status', 'cat']
2509
2477
help='Recurse into subdirectories.'),
2510
2478
Option('from-root',
2511
2479
help='Print paths relative to the root of the branch.'),
2512
Option('unknown', short_name='u',
2513
help='Print unknown files.'),
2480
Option('unknown', help='Print unknown files.'),
2514
2481
Option('versioned', help='Print versioned files.',
2515
2482
short_name='V'),
2516
Option('ignored', short_name='i',
2517
help='Print ignored files.'),
2518
Option('kind', short_name='k',
2483
Option('ignored', help='Print ignored files.'),
2485
help='Write an ascii NUL (\\0) separator '
2486
'between files rather than a newline.'),
2519
2488
help='List entries of a particular kind: file, directory, symlink.',
2525
2492
@display_command
2526
2493
def run(self, revision=None, verbose=False,
2527
2494
recursive=False, from_root=False,
2528
2495
unknown=False, versioned=False, ignored=False,
2529
null=False, kind=None, show_ids=False, path=None, directory=None):
2496
null=False, kind=None, show_ids=False, path=None):
2531
2498
if kind and kind not in ('file', 'directory', 'symlink'):
2532
2499
raise errors.BzrCommandError('invalid kind specified')
2566
2533
view_str = views.view_display_str(view_files)
2567
2534
note("Ignoring files outside view. View is %s" % view_str)
2569
self.add_cleanup(tree.lock_read().unlock)
2537
self.add_cleanup(tree.unlock)
2570
2538
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2571
2539
from_dir=relpath, recursive=recursive):
2572
2540
# Apply additional masking
2616
2584
class cmd_unknowns(Command):
2617
__doc__ = """List unknown files.
2585
"""List unknown files.
2621
2589
_see_also = ['ls']
2622
takes_options = ['directory']
2624
2591
@display_command
2625
def run(self, directory=u'.'):
2626
for f in WorkingTree.open_containing(directory)[0].unknowns():
2593
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2627
2594
self.outf.write(osutils.quotefn(f) + '\n')
2630
2597
class cmd_ignore(Command):
2631
__doc__ = """Ignore specified files or patterns.
2598
"""Ignore specified files or patterns.
2633
2600
See ``bzr help patterns`` for details on the syntax of patterns.
2643
2610
using this command or directly by using an editor, be sure to commit
2646
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2647
the global ignore file can be found in the application data directory as
2648
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2649
Global ignores are not touched by this command. The global ignore file
2650
can be edited directly using an editor.
2652
2613
Patterns prefixed with '!' are exceptions to ignore patterns and take
2653
2614
precedence over regular ignores. Such exceptions are used to specify
2654
2615
files that should be versioned which would otherwise be ignored.
2695
2656
_see_also = ['status', 'ignored', 'patterns']
2696
2657
takes_args = ['name_pattern*']
2697
takes_options = ['directory',
2698
Option('default-rules',
2699
help='Display the default ignore rules that bzr uses.')
2659
Option('old-default-rules',
2660
help='Write out the ignore rules bzr < 0.9 always used.')
2702
def run(self, name_pattern_list=None, default_rules=None,
2663
def run(self, name_pattern_list=None, old_default_rules=None):
2704
2664
from bzrlib import ignores
2705
if default_rules is not None:
2706
# dump the default rules and exit
2707
for pattern in ignores.USER_DEFAULTS:
2708
self.outf.write("%s\n" % pattern)
2665
if old_default_rules is not None:
2666
# dump the rules and exit
2667
for pattern in ignores.OLD_DEFAULTS:
2710
2670
if not name_pattern_list:
2711
2671
raise errors.BzrCommandError("ignore requires at least one "
2712
"NAME_PATTERN or --default-rules.")
2672
"NAME_PATTERN or --old-default-rules")
2713
2673
name_pattern_list = [globbing.normalize_pattern(p)
2714
2674
for p in name_pattern_list]
2716
for p in name_pattern_list:
2717
if not globbing.Globster.is_pattern_valid(p):
2718
bad_patterns += ('\n %s' % p)
2720
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2721
ui.ui_factory.show_error(msg)
2722
raise errors.InvalidPattern('')
2723
2675
for name_pattern in name_pattern_list:
2724
2676
if (name_pattern[0] == '/' or
2725
2677
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2726
2678
raise errors.BzrCommandError(
2727
2679
"NAME_PATTERN should not be an absolute path")
2728
tree, relpath = WorkingTree.open_containing(directory)
2680
tree, relpath = WorkingTree.open_containing(u'.')
2729
2681
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2730
2682
ignored = globbing.Globster(name_pattern_list)
2732
self.add_cleanup(tree.lock_read().unlock)
2733
2685
for entry in tree.list_files():
2735
2687
if id is not None:
2736
2688
filename = entry[0]
2737
2689
if ignored.match(filename):
2738
matches.append(filename)
2690
matches.append(filename.encode('utf-8'))
2739
2692
if len(matches) > 0:
2740
self.outf.write("Warning: the following files are version controlled and"
2741
" match your ignore pattern:\n%s"
2742
"\nThese files will continue to be version controlled"
2743
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2693
print "Warning: the following files are version controlled and" \
2694
" match your ignore pattern:\n%s" \
2695
"\nThese files will continue to be version controlled" \
2696
" unless you 'bzr remove' them." % ("\n".join(matches),)
2746
2699
class cmd_ignored(Command):
2747
__doc__ = """List ignored files and the patterns that matched them.
2700
"""List ignored files and the patterns that matched them.
2749
2702
List all the ignored files and the ignore pattern that caused the file to
2757
2710
encoding_type = 'replace'
2758
2711
_see_also = ['ignore', 'ls']
2759
takes_options = ['directory']
2761
2713
@display_command
2762
def run(self, directory=u'.'):
2763
tree = WorkingTree.open_containing(directory)[0]
2764
self.add_cleanup(tree.lock_read().unlock)
2715
tree = WorkingTree.open_containing(u'.')[0]
2717
self.add_cleanup(tree.unlock)
2765
2718
for path, file_class, kind, file_id, entry in tree.list_files():
2766
2719
if file_class != 'I':
2773
2726
class cmd_lookup_revision(Command):
2774
__doc__ = """Lookup the revision-id from a revision-number
2727
"""Lookup the revision-id from a revision-number
2777
2730
bzr lookup-revision 33
2780
2733
takes_args = ['revno']
2781
takes_options = ['directory']
2783
2735
@display_command
2784
def run(self, revno, directory=u'.'):
2736
def run(self, revno):
2786
2738
revno = int(revno)
2787
2739
except ValueError:
2788
raise errors.BzrCommandError("not a valid revision-number: %r"
2790
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2791
self.outf.write("%s\n" % revid)
2740
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2742
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2794
2745
class cmd_export(Command):
2795
__doc__ = """Export current or past revision to a destination directory or archive.
2746
"""Export current or past revision to a destination directory or archive.
2797
2748
If no revision is specified this exports the last committed revision.
2832
2783
help="Name of the root directory inside the exported file."),
2833
Option('per-file-timestamps',
2834
help='Set modification time of files to that of the last '
2835
'revision in which it was changed.'),
2837
2785
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2838
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2786
root=None, filters=False):
2839
2787
from bzrlib.export import export
2841
2789
if branch_or_subdir is None:
2842
tree = WorkingTree.open_containing(directory)[0]
2790
tree = WorkingTree.open_containing(u'.')[0]
2843
2791
b = tree.branch
2849
2797
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2851
export(rev_tree, dest, format, root, subdir, filtered=filters,
2852
per_file_timestamps=per_file_timestamps)
2799
export(rev_tree, dest, format, root, subdir, filtered=filters)
2853
2800
except errors.NoSuchExportFormat, e:
2854
2801
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2857
2804
class cmd_cat(Command):
2858
__doc__ = """Write the contents of a file as of a given revision to standard output.
2805
"""Write the contents of a file as of a given revision to standard output.
2860
2807
If no revision is nominated, the last revision is used.
2876
2823
@display_command
2877
2824
def run(self, filename, revision=None, name_from_revision=False,
2878
filters=False, directory=None):
2879
2826
if revision is not None and len(revision) != 1:
2880
2827
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2881
2828
" one revision specifier")
2882
2829
tree, branch, relpath = \
2883
_open_directory_or_containing_tree_or_branch(filename, directory)
2884
self.add_cleanup(branch.lock_read().unlock)
2830
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2832
self.add_cleanup(branch.unlock)
2885
2833
return self._run(tree, branch, relpath, filename, revision,
2886
2834
name_from_revision, filters)
2941
2890
class cmd_local_time_offset(Command):
2942
__doc__ = """Show the offset in seconds from GMT to local time."""
2891
"""Show the offset in seconds from GMT to local time."""
2944
2893
@display_command
2946
self.outf.write("%s\n" % osutils.local_time_offset())
2895
print osutils.local_time_offset()
2950
2899
class cmd_commit(Command):
2951
__doc__ = """Commit changes into a new revision.
2900
"""Commit changes into a new revision.
2953
2902
An explanatory message needs to be given for each commit. This is
2954
2903
often done by using the --message option (getting the message from the
3148
3097
'(use --file "%(f)s" to take commit message from that file)'
3149
3098
% { 'f': message })
3150
3099
ui.ui_factory.show_warning(warning_msg)
3152
message = message.replace('\r\n', '\n')
3153
message = message.replace('\r', '\n')
3155
raise errors.BzrCommandError(
3156
"please specify either --message or --file")
3158
3101
def get_message(commit_obj):
3159
3102
"""Callback to get commit message"""
3161
f = codecs.open(file, 'rt', osutils.get_user_encoding())
3163
my_message = f.read()
3166
elif message is not None:
3167
my_message = message
3169
# No message supplied: make one up.
3170
# text is the status of the tree
3171
text = make_commit_message_template_encoded(tree,
3103
my_message = message
3104
if my_message is not None and '\r' in my_message:
3105
my_message = my_message.replace('\r\n', '\n')
3106
my_message = my_message.replace('\r', '\n')
3107
if my_message is None and not file:
3108
t = make_commit_message_template_encoded(tree,
3172
3109
selected_list, diff=show_diff,
3173
3110
output_encoding=osutils.get_user_encoding())
3174
# start_message is the template generated from hooks
3175
# XXX: Warning - looks like hooks return unicode,
3176
# make_commit_message_template_encoded returns user encoding.
3177
# We probably want to be using edit_commit_message instead to
3179
3111
start_message = generate_commit_message_template(commit_obj)
3180
my_message = edit_commit_message_encoded(text,
3112
my_message = edit_commit_message_encoded(t,
3181
3113
start_message=start_message)
3182
3114
if my_message is None:
3183
3115
raise errors.BzrCommandError("please specify a commit"
3184
3116
" message with either --message or --file")
3117
elif my_message and file:
3118
raise errors.BzrCommandError(
3119
"please specify either --message or --file")
3121
my_message = codecs.open(file, 'rt',
3122
osutils.get_user_encoding()).read()
3185
3123
if my_message == "":
3186
3124
raise errors.BzrCommandError("empty commit message specified")
3187
3125
return my_message
3209
3149
raise errors.BzrCommandError("Commit refused because there are"
3210
3150
" unknown files in the working tree.")
3211
3151
except errors.BoundBranchOutOfDate, e:
3212
e.extra_help = ("\n"
3213
'To commit to master branch, run update and then commit.\n'
3214
'You can also pass --local to commit to continue working '
3152
raise errors.BzrCommandError(str(e) + "\n"
3153
'To commit to master branch, run update and then commit.\n'
3154
'You can also pass --local to commit to continue working '
3219
3158
class cmd_check(Command):
3220
__doc__ = """Validate working tree structure, branch consistency and repository history.
3159
"""Validate working tree structure, branch consistency and repository history.
3222
3161
This command checks various invariants about branch and repository storage
3223
3162
to detect data corruption or bzr bugs.
3333
3271
encoding_type = 'replace'
3335
3273
@display_command
3336
def run(self, email=False, branch=False, name=None, directory=None):
3274
def run(self, email=False, branch=False, name=None):
3337
3275
if name is None:
3338
if directory is None:
3339
# use branch if we're inside one; otherwise global config
3341
c = Branch.open_containing(u'.')[0].get_config()
3342
except errors.NotBranchError:
3343
c = config.GlobalConfig()
3345
c = Branch.open(directory).get_config()
3276
# use branch if we're inside one; otherwise global config
3278
c = Branch.open_containing('.')[0].get_config()
3279
except errors.NotBranchError:
3280
c = config.GlobalConfig()
3347
3282
self.outf.write(c.user_email() + '\n')
3359
3294
# use global config unless --branch given
3361
if directory is None:
3362
c = Branch.open_containing(u'.')[0].get_config()
3364
c = Branch.open(directory).get_config()
3296
c = Branch.open_containing('.')[0].get_config()
3366
3298
c = config.GlobalConfig()
3367
3299
c.set_user_option('email', name)
3370
3302
class cmd_nick(Command):
3371
__doc__ = """Print or set the branch nickname.
3303
"""Print or set the branch nickname.
3373
3305
If unset, the tree root directory name is used as the nickname.
3374
3306
To print the current nickname, execute with no argument.
3513
3444
def get_transport_type(typestring):
3514
3445
"""Parse and return a transport specifier."""
3515
3446
if typestring == "sftp":
3516
from bzrlib.tests import stub_sftp
3517
return stub_sftp.SFTPAbsoluteServer
3447
from bzrlib.transport.sftp import SFTPAbsoluteServer
3448
return SFTPAbsoluteServer
3518
3449
if typestring == "memory":
3519
from bzrlib.tests import test_server
3520
return memory.MemoryServer
3450
from bzrlib.transport.memory import MemoryServer
3521
3452
if typestring == "fakenfs":
3522
from bzrlib.tests import test_server
3523
return test_server.FakeNFSServer
3453
from bzrlib.transport.fakenfs import FakeNFSServer
3454
return FakeNFSServer
3524
3455
msg = "No known transport type %s. Supported types are: sftp\n" %\
3526
3457
raise errors.BzrCommandError(msg)
3537
3468
'throughout the test suite.',
3538
3469
type=get_transport_type),
3539
3470
Option('benchmark',
3540
help='Run the benchmarks rather than selftests.',
3471
help='Run the benchmarks rather than selftests.'),
3542
3472
Option('lsprof-timed',
3543
3473
help='Generate lsprof output for benchmarked'
3544
3474
' sections of code.'),
3545
3475
Option('lsprof-tests',
3546
3476
help='Generate lsprof output for each test.'),
3477
Option('cache-dir', type=str,
3478
help='Cache intermediate benchmark output in this '
3547
3480
Option('first',
3548
3481
help='Run all tests, but run specified tests first.',
3549
3482
short_name='f',
3584
3517
def run(self, testspecs_list=None, verbose=False, one=False,
3585
3518
transport=None, benchmark=None,
3519
lsprof_timed=None, cache_dir=None,
3587
3520
first=False, list_only=False,
3588
3521
randomize=None, exclude=None, strict=False,
3589
3522
load_list=None, debugflag=None, starting_with=None, subunit=False,
3590
3523
parallel=None, lsprof_tests=False):
3591
3524
from bzrlib.tests import selftest
3525
import bzrlib.benchmarks as benchmarks
3526
from bzrlib.benchmarks import tree_creator
3593
3528
# Make deprecation warnings visible, unless -Werror is set
3594
3529
symbol_versioning.activate_deprecation_warnings(override=False)
3531
if cache_dir is not None:
3532
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3596
3533
if testspecs_list is not None:
3597
3534
pattern = '|'.join(testspecs_list)
3604
3541
raise errors.BzrCommandError("subunit not available. subunit "
3605
3542
"needs to be installed to use --subunit.")
3606
3543
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3607
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3608
# stdout, which would corrupt the subunit stream.
3609
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3610
# following code can be deleted when it's sufficiently deployed
3611
# -- vila/mgz 20100514
3612
if (sys.platform == "win32"
3613
and getattr(sys.stdout, 'fileno', None) is not None):
3615
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3617
3545
self.additional_selftest_args.setdefault(
3618
3546
'suite_decorators', []).append(parallel)
3620
raise errors.BzrCommandError(
3621
"--benchmark is no longer supported from bzr 2.2; "
3622
"use bzr-usertest instead")
3623
test_suite_factory = None
3548
test_suite_factory = benchmarks.test_suite
3549
# Unless user explicitly asks for quiet, be verbose in benchmarks
3550
verbose = not is_quiet()
3551
# TODO: should possibly lock the history file...
3552
benchfile = open(".perf_history", "at", buffering=1)
3553
self.add_cleanup(benchfile.close)
3555
test_suite_factory = None
3624
3557
selftest_kwargs = {"verbose": verbose,
3625
3558
"pattern": pattern,
3626
3559
"stop_on_failure": one,
3662
3596
class cmd_rocks(Command):
3663
__doc__ = """Statement of optimism."""
3597
"""Statement of optimism."""
3667
3601
@display_command
3669
self.outf.write("It sure does!\n")
3603
print "It sure does!"
3672
3606
class cmd_find_merge_base(Command):
3673
__doc__ = """Find and print a base revision for merging two branches."""
3607
"""Find and print a base revision for merging two branches."""
3674
3608
# TODO: Options to specify revisions on either side, as if
3675
3609
# merging only part of the history.
3676
3610
takes_args = ['branch', 'other']
3683
3617
branch1 = Branch.open_containing(branch)[0]
3684
3618
branch2 = Branch.open_containing(other)[0]
3685
self.add_cleanup(branch1.lock_read().unlock)
3686
self.add_cleanup(branch2.lock_read().unlock)
3620
self.add_cleanup(branch1.unlock)
3622
self.add_cleanup(branch2.unlock)
3687
3623
last1 = ensure_null(branch1.last_revision())
3688
3624
last2 = ensure_null(branch2.last_revision())
3690
3626
graph = branch1.repository.get_graph(branch2.repository)
3691
3627
base_rev_id = graph.find_unique_lca(last1, last2)
3693
self.outf.write('merge base is revision %s\n' % base_rev_id)
3629
print 'merge base is revision %s' % base_rev_id
3696
3632
class cmd_merge(Command):
3697
__doc__ = """Perform a three-way merge.
3633
"""Perform a three-way merge.
3699
3635
The source of the merge can be specified either in the form of a branch,
3700
3636
or in the form of a path to a file containing a merge directive generated
3783
3719
' completely merged into the source, pull from the'
3784
3720
' source rather than merging. When this happens,'
3785
3721
' you do not need to commit the result.'),
3786
custom_help('directory',
3787
3723
help='Branch to merge into, '
3788
'rather than the one containing the working directory.'),
3724
'rather than the one containing the working directory.',
3789
3728
Option('preview', help='Instead of merging, show a diff of the'
3791
3730
Option('interactive', help='Select changes interactively.',
3840
3780
raise errors.BzrCommandError(
3841
3781
'Cannot use -r with merge directives or bundles')
3842
3782
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3845
3785
if merger is None and uncommitted:
3846
3786
if revision is not None and len(revision) > 0:
3847
3787
raise errors.BzrCommandError('Cannot use --uncommitted and'
3848
3788
' --revision at the same time.')
3849
merger = self.get_merger_from_uncommitted(tree, location, None)
3789
merger = self.get_merger_from_uncommitted(tree, location, pb)
3850
3790
allow_pending = False
3852
3792
if merger is None:
3853
3793
merger, allow_pending = self._get_merger_from_branch(tree,
3854
location, revision, remember, possible_transports, None)
3794
location, revision, remember, possible_transports, pb)
3856
3796
merger.merge_type = merge_type
3857
3797
merger.reprocess = reprocess
3891
3831
def _do_preview(self, merger):
3892
3832
from bzrlib.diff import show_diff_trees
3893
3833
result_tree = self._get_preview(merger)
3894
path_encoding = osutils.get_diff_header_encoding()
3895
3834
show_diff_trees(merger.this_tree, result_tree, self.outf,
3896
old_label='', new_label='',
3897
path_encoding=path_encoding)
3835
old_label='', new_label='')
3899
3837
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3900
3838
merger.change_reporter = change_reporter
4085
4023
def run(self, file_list=None, merge_type=None, show_base=False,
4086
4024
reprocess=False):
4087
from bzrlib.conflicts import restore
4088
4025
if merge_type is None:
4089
4026
merge_type = _mod_merge.Merge3Merger
4090
4027
tree, file_list = tree_files(file_list)
4091
self.add_cleanup(tree.lock_write().unlock)
4029
self.add_cleanup(tree.unlock)
4092
4030
parents = tree.get_parent_ids()
4093
4031
if len(parents) != 2:
4094
4032
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4130
4068
# list, we imply that the working tree text has seen and rejected
4131
4069
# all the changes from the other tree, when in fact those changes
4132
4070
# have not yet been seen.
4071
pb = ui.ui_factory.nested_progress_bar()
4133
4072
tree.set_parent_ids(parents[:1])
4135
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4074
merger = _mod_merge.Merger.from_revision_ids(pb,
4136
4076
merger.interesting_ids = interesting_ids
4137
4077
merger.merge_type = merge_type
4138
4078
merger.show_base = show_base
4214
4156
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4215
4157
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4216
tree.revert(file_list, rev_tree, not no_backup, None,
4217
report_changes=True)
4158
pb = ui.ui_factory.nested_progress_bar()
4160
tree.revert(file_list, rev_tree, not no_backup, pb,
4161
report_changes=True)
4220
4166
class cmd_assert_fail(Command):
4221
__doc__ = """Test reporting of assertion failures"""
4167
"""Test reporting of assertion failures"""
4222
4168
# intended just for use in testing
4327
4272
theirs_only=False,
4328
4273
log_format=None, long=False, short=False, line=False,
4329
4274
show_ids=False, verbose=False, this=False, other=False,
4330
include_merges=False, revision=None, my_revision=None,
4275
include_merges=False, revision=None, my_revision=None):
4332
4276
from bzrlib.missing import find_unmerged, iter_log_revisions
4333
4277
def message(s):
4334
4278
if not is_quiet():
4364
4306
remote_branch = Branch.open(other_branch)
4365
4307
if remote_branch.base == local_branch.base:
4366
4308
remote_branch = local_branch
4368
self.add_cleanup(remote_branch.lock_read().unlock)
4310
local_branch.lock_read()
4311
self.add_cleanup(local_branch.unlock)
4370
4312
local_revid_range = _revision_range_to_revid_range(
4371
4313
_get_revision_range(my_revision, local_branch,
4316
remote_branch.lock_read()
4317
self.add_cleanup(remote_branch.unlock)
4374
4318
remote_revid_range = _revision_range_to_revid_range(
4375
4319
_get_revision_range(revision,
4376
4320
remote_branch, self.name()))
4436
4381
class cmd_pack(Command):
4437
__doc__ = """Compress the data within a repository.
4439
This operation compresses the data within a bazaar repository. As
4440
bazaar supports automatic packing of repository, this operation is
4441
normally not required to be done manually.
4443
During the pack operation, bazaar takes a backup of existing repository
4444
data, i.e. pack files. This backup is eventually removed by bazaar
4445
automatically when it is safe to do so. To save disk space by removing
4446
the backed up pack files, the --clean-obsolete-packs option may be
4449
Warning: If you use --clean-obsolete-packs and your machine crashes
4450
during or immediately after repacking, you may be left with a state
4451
where the deletion has been written to disk but the new packs have not
4452
been. In this case the repository may be unusable.
4382
"""Compress the data within a repository."""
4455
4384
_see_also = ['repositories']
4456
4385
takes_args = ['branch_or_repo?']
4458
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4461
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4387
def run(self, branch_or_repo='.'):
4462
4388
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4464
4390
branch = dir.open_branch()
4465
4391
repository = branch.repository
4466
4392
except errors.NotBranchError:
4467
4393
repository = dir.open_repository()
4468
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4471
4397
class cmd_plugins(Command):
4472
__doc__ = """List the installed plugins.
4398
"""List the installed plugins.
4474
4400
This command displays the list of installed plugins including
4475
4401
version of plugin and a short description of each.
4482
4408
adding new commands, providing additional network transports and
4483
4409
customizing log output.
4485
See the Bazaar Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/>
4486
for further information on plugins including where to find them and how to
4487
install them. Instructions are also provided there on how to write new
4488
plugins using the Python programming language.
4411
See the Bazaar web site, http://bazaar-vcs.org, for further
4412
information on plugins including where to find them and how to
4413
install them. Instructions are also provided there on how to
4414
write new plugins using the Python programming language.
4490
4416
takes_options = ['verbose']
4506
4432
doc = '(no description)'
4507
4433
result.append((name_ver, doc, plugin.path()))
4508
4434
for name_ver, doc, path in sorted(result):
4509
self.outf.write("%s\n" % name_ver)
4510
self.outf.write(" %s\n" % doc)
4512
self.outf.write(" %s\n" % path)
4513
self.outf.write("\n")
4516
4442
class cmd_testament(Command):
4517
__doc__ = """Show testament (signing-form) of a revision."""
4443
"""Show testament (signing-form) of a revision."""
4518
4444
takes_options = [
4520
4446
Option('long', help='Produce long-format testament.'),
4562
4489
Option('long', help='Show commit date in annotations.'),
4567
4493
encoding_type = 'exact'
4569
4495
@display_command
4570
4496
def run(self, filename, all=False, long=False, revision=None,
4571
show_ids=False, directory=None):
4572
4498
from bzrlib.annotate import annotate_file, annotate_file_tree
4573
4499
wt, branch, relpath = \
4574
_open_directory_or_containing_tree_or_branch(filename, directory)
4500
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4575
4501
if wt is not None:
4576
self.add_cleanup(wt.lock_read().unlock)
4503
self.add_cleanup(wt.unlock)
4578
self.add_cleanup(branch.lock_read().unlock)
4506
self.add_cleanup(branch.unlock)
4579
4507
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4580
self.add_cleanup(tree.lock_read().unlock)
4509
self.add_cleanup(tree.unlock)
4581
4510
if wt is not None:
4582
4511
file_id = wt.path2id(relpath)
4598
4527
class cmd_re_sign(Command):
4599
__doc__ = """Create a digital signature for an existing revision."""
4528
"""Create a digital signature for an existing revision."""
4600
4529
# TODO be able to replace existing ones.
4602
4531
hidden = True # is this right ?
4603
4532
takes_args = ['revision_id*']
4604
takes_options = ['directory', 'revision']
4533
takes_options = ['revision']
4606
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4535
def run(self, revision_id_list=None, revision=None):
4607
4536
if revision_id_list is not None and revision is not None:
4608
4537
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4609
4538
if revision_id_list is None and revision is None:
4610
4539
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4611
b = WorkingTree.open_containing(directory)[0].branch
4612
self.add_cleanup(b.lock_write().unlock)
4540
b = WorkingTree.open_containing(u'.')[0].branch
4542
self.add_cleanup(b.unlock)
4613
4543
return self._run(b, revision_id_list, revision)
4615
4545
def _run(self, b, revision_id_list, revision):
4675
4604
_see_also = ['checkouts', 'unbind']
4676
4605
takes_args = ['location?']
4677
takes_options = ['directory']
4679
def run(self, location=None, directory=u'.'):
4680
b, relpath = Branch.open_containing(directory)
4608
def run(self, location=None):
4609
b, relpath = Branch.open_containing(u'.')
4681
4610
if location is None:
4683
4612
location = b.get_old_bound_location()
4711
4637
_see_also = ['checkouts', 'bind']
4712
4638
takes_args = []
4713
takes_options = ['directory']
4715
def run(self, directory=u'.'):
4716
b, relpath = Branch.open_containing(directory)
4642
b, relpath = Branch.open_containing(u'.')
4717
4643
if not b.unbind():
4718
4644
raise errors.BzrCommandError('Local branch is not bound')
4721
4647
class cmd_uncommit(Command):
4722
__doc__ = """Remove the last committed revision.
4648
"""Remove the last committed revision.
4724
4650
--verbose will print out what is being removed.
4725
4651
--dry-run will go through all the motions, but not actually
4765
4691
b = control.open_branch()
4767
4693
if tree is not None:
4768
self.add_cleanup(tree.lock_write().unlock)
4695
self.add_cleanup(tree.unlock)
4770
self.add_cleanup(b.lock_write().unlock)
4698
self.add_cleanup(b.unlock)
4771
4699
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4773
4701
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4806
4734
end_revision=last_revno)
4809
self.outf.write('Dry-run, pretending to remove'
4810
' the above revisions.\n')
4737
print 'Dry-run, pretending to remove the above revisions.'
4739
val = raw_input('Press <enter> to continue')
4812
self.outf.write('The above revision(s) will be removed.\n')
4815
if not ui.ui_factory.get_boolean('Are you sure'):
4816
self.outf.write('Canceled')
4741
print 'The above revision(s) will be removed.'
4743
val = raw_input('Are you sure [y/N]? ')
4744
if val.lower() not in ('y', 'yes'):
4819
4748
mutter('Uncommitting from {%s} to {%s}',
4820
4749
last_rev_id, rev_id)
4821
4750
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4822
4751
revno=revno, local=local)
4823
self.outf.write('You can restore the old tip by running:\n'
4824
' bzr pull . -r revid:%s\n' % last_rev_id)
4752
note('You can restore the old tip by running:\n'
4753
' bzr pull . -r revid:%s', last_rev_id)
4827
4756
class cmd_break_lock(Command):
4828
__doc__ = """Break a dead lock on a repository, branch or working directory.
4757
"""Break a dead lock on a repository, branch or working directory.
4830
4759
CAUTION: Locks should only be broken when you are sure that the process
4831
4760
holding the lock has been stopped.
4916
4846
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4917
4847
protocol=None):
4918
from bzrlib import transport
4848
from bzrlib.transport import get_transport, transport_server_registry
4919
4849
if directory is None:
4920
4850
directory = os.getcwd()
4921
4851
if protocol is None:
4922
protocol = transport.transport_server_registry.get()
4852
protocol = transport_server_registry.get()
4923
4853
host, port = self.get_host_and_port(port)
4924
4854
url = urlutils.local_path_to_url(directory)
4925
4855
if not allow_writes:
4926
4856
url = 'readonly+' + url
4927
t = transport.get_transport(url)
4928
protocol(t, host, port, inet)
4857
transport = get_transport(url)
4858
protocol(transport, host, port, inet)
4931
4861
class cmd_join(Command):
4932
__doc__ = """Combine a tree into its containing tree.
4862
"""Combine a tree into its containing tree.
4934
4864
This command requires the target tree to be in a rich-root format.
5043
4972
encoding_type = 'exact'
5045
4974
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5046
sign=False, revision=None, mail_to=None, message=None,
4975
sign=False, revision=None, mail_to=None, message=None):
5048
4976
from bzrlib.revision import ensure_null, NULL_REVISION
5049
4977
include_patch, include_bundle = {
5050
4978
'plain': (False, False),
5051
4979
'diff': (True, False),
5052
4980
'bundle': (True, True),
5054
branch = Branch.open(directory)
4982
branch = Branch.open('.')
5055
4983
stored_submit_branch = branch.get_submit_branch()
5056
4984
if submit_branch is None:
5057
4985
submit_branch = stored_submit_branch
5307
5235
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5308
5236
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5310
If no tag name is specified it will be determined through the
5311
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5312
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5316
5239
_see_also = ['commit', 'tags']
5317
takes_args = ['tag_name?']
5240
takes_args = ['tag_name']
5318
5241
takes_options = [
5319
5242
Option('delete',
5320
5243
help='Delete this tag rather than placing it.',
5322
custom_help('directory',
5323
help='Branch in which to place the tag.'),
5246
help='Branch in which to place the tag.',
5324
5250
Option('force',
5325
5251
help='Replace existing tags.',
5330
def run(self, tag_name=None,
5256
def run(self, tag_name,
5336
5262
branch, relpath = Branch.open_containing(directory)
5337
self.add_cleanup(branch.lock_write().unlock)
5264
self.add_cleanup(branch.unlock)
5339
if tag_name is None:
5340
raise errors.BzrCommandError("No tag specified to delete.")
5341
5266
branch.tags.delete_tag(tag_name)
5342
5267
self.outf.write('Deleted tag %s.\n' % tag_name)
5557
5480
def run(self, to_location=None, force=False, create_branch=False,
5558
revision=None, directory=u'.'):
5559
5482
from bzrlib import switch
5560
tree_location = directory
5561
5484
revision = _get_one_revision('switch', revision)
5562
5485
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5563
5486
if to_location is None:
5564
5487
if revision is None:
5565
5488
raise errors.BzrCommandError('You must supply either a'
5566
5489
' revision or a location')
5567
to_location = tree_location
5569
5492
branch = control_dir.open_branch()
5570
5493
had_explicit_nick = branch.get_config().has_explicit_nickname()
5792
5715
self.outf.write(" <no hooks installed>\n")
5795
class cmd_remove_branch(Command):
5796
__doc__ = """Remove a branch.
5798
This will remove the branch from the specified location but
5799
will keep any working tree or repository in place.
5803
Remove the branch at repo/trunk::
5805
bzr remove-branch repo/trunk
5809
takes_args = ["location?"]
5811
aliases = ["rmbranch"]
5813
def run(self, location=None):
5814
if location is None:
5816
branch = Branch.open_containing(location)[0]
5817
branch.bzrdir.destroy_branch()
5820
5718
class cmd_shelve(Command):
5821
__doc__ = """Temporarily set aside some changes from the current tree.
5719
"""Temporarily set aside some changes from the current tree.
5823
5721
Shelve allows you to temporarily put changes you've made "on the shelf",
5824
5722
ie. out of the way, until a later time when you can bring them back from
5860
5757
_see_also = ['unshelve']
5862
5759
def run(self, revision=None, all=False, file_list=None, message=None,
5863
writer=None, list=False, destroy=False, directory=u'.'):
5760
writer=None, list=False, destroy=False):
5865
5762
return self.run_for_list()
5866
5763
from bzrlib.shelf_ui import Shelver
5941
5838
To check what clean-tree will do, use --dry-run.
5943
takes_options = ['directory',
5944
Option('ignored', help='Delete all ignored files.'),
5840
takes_options = [Option('ignored', help='Delete all ignored files.'),
5945
5841
Option('detritus', help='Delete conflict files, merge'
5946
5842
' backups, and failed selftest dirs.'),
5947
5843
Option('unknown',
5950
5846
' deleting them.'),
5951
5847
Option('force', help='Do not prompt before deleting.')]
5952
5848
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5953
force=False, directory=u'.'):
5954
5850
from bzrlib.clean_tree import clean_tree
5955
5851
if not (unknown or ignored or detritus):
5959
clean_tree(directory, unknown=unknown, ignored=ignored,
5960
detritus=detritus, dry_run=dry_run, no_prompt=force)
5855
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5856
dry_run=dry_run, no_prompt=force)
5963
5859
class cmd_reference(Command):
5964
__doc__ = """list, view and set branch locations for nested trees.
5860
"""list, view and set branch locations for nested trees.
5966
5862
If no arguments are provided, lists the branch locations for nested trees.
5967
5863
If one argument is provided, display the branch location for that tree.
6007
5903
self.outf.write('%s %s\n' % (path, location))
6010
def _register_lazy_builtins():
6011
# register lazy builtins from other modules; called at startup and should
6012
# be only called once.
6013
for (name, aliases, module_name) in [
6014
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6015
('cmd_dpush', [], 'bzrlib.foreign'),
6016
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6017
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6018
('cmd_conflicts', [], 'bzrlib.conflicts'),
6019
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6021
builtin_command_registry.register_lazy(name, aliases, module_name)
5906
# these get imported and then picked up by the scan for cmd_*
5907
# TODO: Some more consistent way to split command definitions across files;
5908
# we do need to load at least some information about them to know of
5909
# aliases. ideally we would avoid loading the implementation until the
5910
# details were needed.
5911
from bzrlib.cmd_version_info import cmd_version_info
5912
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5913
from bzrlib.bundle.commands import (
5916
from bzrlib.foreign import cmd_dpush
5917
from bzrlib.sign_my_commits import cmd_sign_my_commits
5918
from bzrlib.weave_commands import cmd_versionedfile_list, \
5919
cmd_weave_plan_merge, cmd_weave_merge_text