60
60
from bzrlib.workingtree import WorkingTree
63
from bzrlib.commands import Command, display_command
63
from bzrlib.commands import (
65
builtin_command_registry,
64
68
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)
231
243
# TODO: Make sure no commands unconditionally use the working directory as a
232
244
# branch. If a filename argument is used, the first of them should be used to
233
245
# specify the branch. (Perhaps this can be factored out into some kind of
330
342
class cmd_cat_revision(Command):
331
"""Write out metadata for a revision.
343
__doc__ = """Write out metadata for a revision.
333
345
The revision to print can either be specified by a specific
334
346
revision identifier, or you can use --revision.
349
361
self.outf.write(revtext.decode('utf-8'))
352
def run(self, revision_id=None, revision=None):
364
def run(self, revision_id=None, revision=None, directory=u'.'):
353
365
if revision_id is not None and revision is not None:
354
366
raise errors.BzrCommandError('You can only supply one of'
355
367
' revision_id or --revision')
356
368
if revision_id is None and revision is None:
357
369
raise errors.BzrCommandError('You must supply either'
358
370
' --revision or a revision_id')
359
b = WorkingTree.open_containing(u'.')[0].branch
371
b = WorkingTree.open_containing(directory)[0].branch
361
373
revisions = b.repository.revisions
362
374
if revisions is None:
388
400
class cmd_dump_btree(Command):
389
"""Dump the contents of a btree index file to stdout.
401
__doc__ = """Dump the contents of a btree index file to stdout.
391
403
PATH is a btree index file, it can be any URL. This includes things like
392
404
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
500
512
if (working.has_changes()):
501
513
raise errors.UncommittedChanges(working)
503
working_path = working.bzrdir.root_transport.base
504
branch_path = working.branch.bzrdir.root_transport.base
505
if working_path != branch_path:
515
if working.user_url != working.branch.user_url:
506
516
raise errors.BzrCommandError("You cannot remove the working tree"
507
517
" from a lightweight checkout")
548
558
class cmd_revision_info(Command):
549
"""Show revision number and revision id for a given revision identifier.
559
__doc__ = """Show revision number and revision id for a given revision identifier.
552
562
takes_args = ['revision_info*']
553
563
takes_options = [
565
custom_help('directory',
556
566
help='Branch to examine, '
557
'rather than the one containing the working directory.',
567
'rather than the one containing the working directory.'),
561
568
Option('tree', help='Show revno of working tree'),
958
965
takes_options = ['remember', 'overwrite', 'revision',
959
966
custom_help('verbose',
960
967
help='Show logs of pulled revisions.'),
968
custom_help('directory',
962
969
help='Branch to pull into, '
963
'rather than the one containing the working directory.',
970
'rather than the one containing the working directory.'),
968
972
help="Perform a local pull in a bound "
969
973
"branch. Local pulls are not applied to "
985
989
tree_to = WorkingTree.open_containing(directory)[0]
986
990
branch_to = tree_to.branch
992
self.add_cleanup(tree_to.unlock)
987
993
except errors.NoWorkingTree:
989
995
branch_to = Branch.open_containing(directory)[0]
996
branch_to.lock_write()
997
self.add_cleanup(branch_to.unlock)
991
999
if local and not branch_to.get_bound_location():
992
1000
raise errors.LocalRequiresBoundBranch()
1024
1032
branch_from = Branch.open(location,
1025
1033
possible_transports=possible_transports)
1034
branch_from.lock_read()
1035
self.add_cleanup(branch_from.unlock)
1027
1037
if branch_to.get_parent() is None or remember:
1028
1038
branch_to.set_parent(branch_from.base)
1030
if branch_from is not branch_to:
1031
branch_from.lock_read()
1032
self.add_cleanup(branch_from.unlock)
1033
1040
if revision is not None:
1034
1041
revision_id = revision.as_revision_id(branch_from)
1036
branch_to.lock_write()
1037
self.add_cleanup(branch_to.unlock)
1038
1043
if tree_to is not None:
1039
1044
view_info = _get_view_info_for_change_reporter(tree_to)
1040
1045
change_reporter = delta._ChangeReporter(
1085
1090
Option('create-prefix',
1086
1091
help='Create the path leading up to the branch '
1087
1092
'if it does not already exist.'),
1093
custom_help('directory',
1089
1094
help='Branch to push from, '
1090
'rather than the one containing the working directory.',
1095
'rather than the one containing the working directory.'),
1094
1096
Option('use-existing-dir',
1095
1097
help='By default push will fail if the target'
1096
1098
' directory exists, but does not already'
1122
1124
# Get the source branch
1123
1125
(tree, br_from,
1124
1126
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1126
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1127
if strict is None: strict = True # default value
1128
1127
# Get the tip's revision_id
1129
1128
revision = _get_one_revision('push', revision)
1130
1129
if revision is not None:
1131
1130
revision_id = revision.in_history(br_from).rev_id
1133
1132
revision_id = None
1134
if strict and tree is not None and revision_id is None:
1135
if (tree.has_changes()):
1136
raise errors.UncommittedChanges(
1137
tree, more='Use --no-strict to force the push.')
1138
if tree.last_revision() != tree.branch.last_revision():
1139
# The tree has lost sync with its branch, there is little
1140
# chance that the user is aware of it but he can still force
1141
# the push with --no-strict
1142
raise errors.OutOfDateTree(
1143
tree, more='Use --no-strict to force the push.')
1133
if tree is not None and revision_id is None:
1134
tree.check_changed_or_out_of_date(
1135
strict, 'push_strict',
1136
more_error='Use --no-strict to force the push.',
1137
more_warning='Uncommitted changes will not be pushed.')
1145
1138
# Get the stacked_on branch, if any
1146
1139
if stacked_on is not None:
1147
1140
stacked_on = urlutils.normalize_url(stacked_on)
1181
1174
class cmd_branch(Command):
1182
"""Create a new branch that is a copy of an existing branch.
1175
__doc__ = """Create a new branch that is a copy of an existing branch.
1184
1177
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1185
1178
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1294
1287
class cmd_checkout(Command):
1295
"""Create a new checkout of an existing branch.
1288
__doc__ = """Create a new checkout of an existing branch.
1297
1290
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1298
1291
the branch found in '.'. This is useful if you have removed the working tree
1395
1388
class cmd_update(Command):
1396
"""Update a tree to have the latest code committed to its branch.
1389
__doc__ = """Update a tree to have the latest code committed to its branch.
1398
1391
This will perform a merge into the working tree, and may generate
1399
1392
conflicts. If you have any local changes, you will still
1428
1421
branch_location = tree.branch.base
1429
1422
self.add_cleanup(tree.unlock)
1430
1423
# get rid of the final '/' and be ready for display
1431
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1424
branch_location = urlutils.unescape_for_display(
1425
branch_location.rstrip('/'),
1433
1427
existing_pending_merges = tree.get_parent_ids()[1:]
1434
1428
if master is None:
1444
1438
revision_id = branch.last_revision()
1445
1439
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1446
revno = branch.revision_id_to_revno(revision_id)
1447
note("Tree is up to date at revision %d of branch %s" %
1448
(revno, branch_location))
1440
revno = branch.revision_id_to_dotted_revno(revision_id)
1441
note("Tree is up to date at revision %s of branch %s" %
1442
('.'.join(map(str, revno)), branch_location))
1450
1444
view_info = _get_view_info_for_change_reporter(tree)
1451
1445
change_reporter = delta._ChangeReporter(
1463
1457
"bzr update --revision only works"
1464
1458
" for a revision in the branch history"
1465
1459
% (e.revision))
1466
revno = tree.branch.revision_id_to_revno(
1460
revno = tree.branch.revision_id_to_dotted_revno(
1467
1461
_mod_revision.ensure_null(tree.last_revision()))
1468
note('Updated to revision %d of branch %s' %
1469
(revno, branch_location))
1470
if tree.get_parent_ids()[1:] != existing_pending_merges:
1462
note('Updated to revision %s of branch %s' %
1463
('.'.join(map(str, revno)), branch_location))
1464
parent_ids = tree.get_parent_ids()
1465
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1471
1466
note('Your local commits will now show as pending merges with '
1472
1467
"'bzr status', and can be committed with 'bzr commit'.")
1473
1468
if conflicts != 0:
1479
1474
class cmd_info(Command):
1480
"""Show information about a working tree, branch or repository.
1475
__doc__ = """Show information about a working tree, branch or repository.
1482
1477
This command will show all known locations and formats associated to the
1483
1478
tree, branch or repository.
1577
1572
class cmd_file_id(Command):
1578
"""Print file_id of a particular file or directory.
1573
__doc__ = """Print file_id of a particular file or directory.
1580
1575
The file_id is assigned when the file is first added and remains the
1581
1576
same through all revisions where the file exists, even when it is
1599
1594
class cmd_file_path(Command):
1600
"""Print path of file_ids to a file or directory.
1595
__doc__ = """Print path of file_ids to a file or directory.
1602
1597
This prints one line for each directory down to the target,
1603
1598
starting at the branch root.
1665
1660
class cmd_ancestry(Command):
1666
"""List all revisions merged into this branch."""
1661
__doc__ = """List all revisions merged into this branch."""
1668
1663
_see_also = ['log', 'revision-history']
1669
1664
takes_args = ['location?']
1799
1794
class cmd_init_repository(Command):
1800
"""Create a shared repository for branches to share storage space.
1795
__doc__ = """Create a shared repository for branches to share storage space.
1802
1797
New branches created under the repository directory will store their
1803
1798
revisions in the repository, not in the branch directory. For branches
1859
1854
class cmd_diff(Command):
1860
"""Show differences in the working tree, between revisions or branches.
1855
__doc__ = """Show differences in the working tree, between revisions or branches.
1862
1857
If no arguments are given, all changes for the current tree are listed.
1863
1858
If files are given, only the changes in those files are listed.
1949
1944
help='Use this command to compare files.',
1947
RegistryOption('format',
1948
help='Diff format to use.',
1949
lazy_registry=('bzrlib.diff', 'format_registry'),
1950
value_switches=False, title='Diff format'),
1953
1952
aliases = ['di', 'dif']
1954
1953
encoding_type = 'exact'
1956
1955
@display_command
1957
1956
def run(self, revision=None, file_list=None, diff_options=None,
1958
prefix=None, old=None, new=None, using=None):
1959
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1957
prefix=None, old=None, new=None, using=None, format=None):
1958
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1961
1961
if (prefix is None) or (prefix == '0'):
1962
1962
# diff -p0 format
1976
1976
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1977
1977
' one or two revision specifiers')
1979
if using is not None and format is not None:
1980
raise errors.BzrCommandError('--using and --format are mutually '
1979
1983
(old_tree, new_tree,
1980
1984
old_branch, new_branch,
1981
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1982
file_list, revision, old, new, apply_view=True)
1985
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1986
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1983
1987
return show_diff_trees(old_tree, new_tree, sys.stdout,
1984
1988
specific_files=specific_files,
1985
1989
external_diff_options=diff_options,
1986
1990
old_label=old_label, new_label=new_label,
1987
extra_trees=extra_trees, using=using)
1991
extra_trees=extra_trees, using=using,
1990
1995
class cmd_deleted(Command):
1991
"""List files deleted in the working tree.
1996
__doc__ = """List files deleted in the working tree.
1993
1998
# TODO: Show files deleted since a previous revision, or
1994
1999
# between two revisions.
1997
2002
# level of effort but possibly much less IO. (Or possibly not,
1998
2003
# if the directories are very large...)
1999
2004
_see_also = ['status', 'ls']
2000
takes_options = ['show-ids']
2005
takes_options = ['directory', 'show-ids']
2002
2007
@display_command
2003
def run(self, show_ids=False):
2004
tree = WorkingTree.open_containing(u'.')[0]
2008
def run(self, show_ids=False, directory=u'.'):
2009
tree = WorkingTree.open_containing(directory)[0]
2005
2010
tree.lock_read()
2006
2011
self.add_cleanup(tree.unlock)
2007
2012
old = tree.basis_tree()
2019
2024
class cmd_modified(Command):
2020
"""List files modified in working tree.
2025
__doc__ = """List files modified in working tree.
2024
2029
_see_also = ['status', 'ls']
2030
takes_options = ['directory',
2027
2032
help='Write an ascii NUL (\\0) separator '
2028
2033
'between files rather than a newline.')
2031
2036
@display_command
2032
def run(self, null=False):
2033
tree = WorkingTree.open_containing(u'.')[0]
2037
def run(self, null=False, directory=u'.'):
2038
tree = WorkingTree.open_containing(directory)[0]
2034
2039
td = tree.changes_from(tree.basis_tree())
2035
2040
for path, id, kind, text_modified, meta_modified in td.modified:
2042
2047
class cmd_added(Command):
2043
"""List files added in working tree.
2048
__doc__ = """List files added in working tree.
2047
2052
_see_also = ['status', 'ls']
2053
takes_options = ['directory',
2050
2055
help='Write an ascii NUL (\\0) separator '
2051
2056
'between files rather than a newline.')
2054
2059
@display_command
2055
def run(self, null=False):
2056
wt = WorkingTree.open_containing(u'.')[0]
2060
def run(self, null=False, directory=u'.'):
2061
wt = WorkingTree.open_containing(directory)[0]
2058
2063
self.add_cleanup(wt.unlock)
2059
2064
basis = wt.basis_tree()
2067
2072
if inv.is_root(file_id) and len(basis_inv) == 0:
2069
2074
path = inv.id2path(file_id)
2070
if not os.access(osutils.abspath(path), os.F_OK):
2075
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2073
2078
self.outf.write(path + '\0')
2298
2303
help='Show changes made in each revision as a patch.'),
2299
2304
Option('include-merges',
2300
2305
help='Show merged revisions like --levels 0 does.'),
2306
Option('exclude-common-ancestry',
2307
help='Display only the revisions that are not part'
2308
' of both ancestries (require -rX..Y)'
2302
2311
encoding_type = 'replace'
2315
2324
show_diff=False,
2316
2325
include_merges=False,
2327
exclude_common_ancestry=False,
2318
2329
from bzrlib.log import (
2320
2331
make_log_request_dict,
2321
2332
_get_info_for_log_files,
2323
2334
direction = (forward and 'forward') or 'reverse'
2335
if (exclude_common_ancestry
2336
and (revision is None or len(revision) != 2)):
2337
raise errors.BzrCommandError(
2338
'--exclude-common-ancestry requires -r with two revisions')
2324
2339
if include_merges:
2325
2340
if levels is None:
2420
2435
direction=direction, specific_fileids=file_ids,
2421
2436
start_revision=rev1, end_revision=rev2, limit=limit,
2422
2437
message_search=message, delta_type=delta_type,
2423
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2438
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2439
exclude_common_ancestry=exclude_common_ancestry,
2424
2441
Logger(b, rqst).show(lf)
2528
2545
help='List entries of a particular kind: file, directory, symlink.',
2532
2550
@display_command
2533
2551
def run(self, revision=None, verbose=False,
2534
2552
recursive=False, from_root=False,
2535
2553
unknown=False, versioned=False, ignored=False,
2536
null=False, kind=None, show_ids=False, path=None):
2554
null=False, kind=None, show_ids=False, path=None, directory=None):
2538
2556
if kind and kind not in ('file', 'directory', 'symlink'):
2539
2557
raise errors.BzrCommandError('invalid kind specified')
2551
2569
raise errors.BzrCommandError('cannot specify both --from-root'
2554
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2572
tree, branch, relpath = \
2573
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2557
2575
# Calculate the prefix to use
2624
2642
class cmd_unknowns(Command):
2625
"""List unknown files.
2643
__doc__ = """List unknown files.
2629
2647
_see_also = ['ls']
2648
takes_options = ['directory']
2631
2650
@display_command
2633
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2651
def run(self, directory=u'.'):
2652
for f in WorkingTree.open_containing(directory)[0].unknowns():
2634
2653
self.outf.write(osutils.quotefn(f) + '\n')
2637
2656
class cmd_ignore(Command):
2638
"""Ignore specified files or patterns.
2657
__doc__ = """Ignore specified files or patterns.
2640
2659
See ``bzr help patterns`` for details on the syntax of patterns.
2650
2669
using this command or directly by using an editor, be sure to commit
2672
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2673
the global ignore file can be found in the application data directory as
2674
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2675
Global ignores are not touched by this command. The global ignore file
2676
can be edited directly using an editor.
2653
2678
Patterns prefixed with '!' are exceptions to ignore patterns and take
2654
2679
precedence over regular ignores. Such exceptions are used to specify
2655
2680
files that should be versioned which would otherwise be ignored.
2696
2721
_see_also = ['status', 'ignored', 'patterns']
2697
2722
takes_args = ['name_pattern*']
2699
Option('old-default-rules',
2700
help='Write out the ignore rules bzr < 0.9 always used.')
2723
takes_options = ['directory',
2724
Option('default-rules',
2725
help='Display the default ignore rules that bzr uses.')
2703
def run(self, name_pattern_list=None, old_default_rules=None):
2728
def run(self, name_pattern_list=None, default_rules=None,
2704
2730
from bzrlib import ignores
2705
if old_default_rules is not None:
2706
# dump the rules and exit
2707
for pattern in ignores.OLD_DEFAULTS:
2731
if default_rules is not None:
2732
# dump the default rules and exit
2733
for pattern in ignores.USER_DEFAULTS:
2708
2734
self.outf.write("%s\n" % pattern)
2710
2736
if not name_pattern_list:
2711
2737
raise errors.BzrCommandError("ignore requires at least one "
2712
"NAME_PATTERN or --old-default-rules")
2738
"NAME_PATTERN or --default-rules.")
2713
2739
name_pattern_list = [globbing.normalize_pattern(p)
2714
2740
for p in name_pattern_list]
2715
2741
for name_pattern in name_pattern_list:
2717
2743
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2718
2744
raise errors.BzrCommandError(
2719
2745
"NAME_PATTERN should not be an absolute path")
2720
tree, relpath = WorkingTree.open_containing(u'.')
2746
tree, relpath = WorkingTree.open_containing(directory)
2721
2747
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2722
2748
ignored = globbing.Globster(name_pattern_list)
2750
2776
encoding_type = 'replace'
2751
2777
_see_also = ['ignore', 'ls']
2778
takes_options = ['directory']
2753
2780
@display_command
2755
tree = WorkingTree.open_containing(u'.')[0]
2781
def run(self, directory=u'.'):
2782
tree = WorkingTree.open_containing(directory)[0]
2756
2783
tree.lock_read()
2757
2784
self.add_cleanup(tree.unlock)
2758
2785
for path, file_class, kind, file_id, entry in tree.list_files():
2766
2793
class cmd_lookup_revision(Command):
2767
"""Lookup the revision-id from a revision-number
2794
__doc__ = """Lookup the revision-id from a revision-number
2770
2797
bzr lookup-revision 33
2773
2800
takes_args = ['revno']
2801
takes_options = ['directory']
2775
2803
@display_command
2776
def run(self, revno):
2804
def run(self, revno, directory=u'.'):
2778
2806
revno = int(revno)
2779
2807
except ValueError:
2780
2808
raise errors.BzrCommandError("not a valid revision-number: %r"
2782
revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2810
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2783
2811
self.outf.write("%s\n" % revid)
2786
2814
class cmd_export(Command):
2787
"""Export current or past revision to a destination directory or archive.
2815
__doc__ = """Export current or past revision to a destination directory or archive.
2789
2817
If no revision is specified this exports the last committed revision.
2827
2855
'revision in which it was changed.'),
2829
2857
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2830
root=None, filters=False, per_file_timestamps=False):
2858
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2831
2859
from bzrlib.export import export
2833
2861
if branch_or_subdir is None:
2834
tree = WorkingTree.open_containing(u'.')[0]
2862
tree = WorkingTree.open_containing(directory)[0]
2835
2863
b = tree.branch
2868
2896
@display_command
2869
2897
def run(self, filename, revision=None, name_from_revision=False,
2898
filters=False, directory=None):
2871
2899
if revision is not None and len(revision) != 1:
2872
2900
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2873
2901
" one revision specifier")
2874
2902
tree, branch, relpath = \
2875
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2903
_open_directory_or_containing_tree_or_branch(filename, directory)
2876
2904
branch.lock_read()
2877
2905
self.add_cleanup(branch.unlock)
2878
2906
return self._run(tree, branch, relpath, filename, revision,
3056
3084
"the master branch until a normal commit "
3057
3085
"is performed."
3087
Option('show-diff', short_name='p',
3060
3088
help='When no message is supplied, show the diff along'
3061
3089
' with the status summary in the message editor.'),
3142
3170
'(use --file "%(f)s" to take commit message from that file)'
3143
3171
% { 'f': message })
3144
3172
ui.ui_factory.show_warning(warning_msg)
3174
message = message.replace('\r\n', '\n')
3175
message = message.replace('\r', '\n')
3177
raise errors.BzrCommandError(
3178
"please specify either --message or --file")
3146
3180
def get_message(commit_obj):
3147
3181
"""Callback to get commit message"""
3148
my_message = message
3149
if my_message is not None and '\r' in my_message:
3150
my_message = my_message.replace('\r\n', '\n')
3151
my_message = my_message.replace('\r', '\n')
3152
if my_message is None and not file:
3153
t = make_commit_message_template_encoded(tree,
3183
my_message = codecs.open(
3184
file, 'rt', osutils.get_user_encoding()).read()
3185
elif message is not None:
3186
my_message = message
3188
# No message supplied: make one up.
3189
# text is the status of the tree
3190
text = make_commit_message_template_encoded(tree,
3154
3191
selected_list, diff=show_diff,
3155
3192
output_encoding=osutils.get_user_encoding())
3193
# start_message is the template generated from hooks
3194
# XXX: Warning - looks like hooks return unicode,
3195
# make_commit_message_template_encoded returns user encoding.
3196
# We probably want to be using edit_commit_message instead to
3156
3198
start_message = generate_commit_message_template(commit_obj)
3157
my_message = edit_commit_message_encoded(t,
3199
my_message = edit_commit_message_encoded(text,
3158
3200
start_message=start_message)
3159
3201
if my_message is None:
3160
3202
raise errors.BzrCommandError("please specify a commit"
3161
3203
" message with either --message or --file")
3162
elif my_message and file:
3163
raise errors.BzrCommandError(
3164
"please specify either --message or --file")
3166
my_message = codecs.open(file, 'rt',
3167
osutils.get_user_encoding()).read()
3168
3204
if my_message == "":
3169
3205
raise errors.BzrCommandError("empty commit message specified")
3170
3206
return my_message
3182
3218
timezone=offset,
3183
3219
exclude=safe_relpath_files(tree, exclude))
3184
3220
except PointlessCommit:
3185
# FIXME: This should really happen before the file is read in;
3186
# perhaps prepare the commit; get the message; then actually commit
3187
3221
raise errors.BzrCommandError("No changes to commit."
3188
3222
" Use --unchanged to commit anyhow.")
3189
3223
except ConflictsInTree:
3204
3238
class cmd_check(Command):
3205
"""Validate working tree structure, branch consistency and repository history.
3239
__doc__ = """Validate working tree structure, branch consistency and repository history.
3207
3241
This command checks various invariants about branch and repository storage
3208
3242
to detect data corruption or bzr bugs.
3358
3392
_see_also = ['info']
3359
3393
takes_args = ['nickname?']
3360
def run(self, nickname=None):
3361
branch = Branch.open_containing(u'.')[0]
3394
takes_options = ['directory']
3395
def run(self, nickname=None, directory=u'.'):
3396
branch = Branch.open_containing(directory)[0]
3362
3397
if nickname is None:
3363
3398
self.printme(branch)
3442
3477
class cmd_selftest(Command):
3443
"""Run internal test suite.
3478
__doc__ = """Run internal test suite.
3445
3480
If arguments are given, they are regular expressions that say which tests
3446
3481
should run. Tests matching any expression are run, and other tests are
3587
3622
raise errors.BzrCommandError("subunit not available. subunit "
3588
3623
"needs to be installed to use --subunit.")
3589
3624
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3625
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3626
# stdout, which would corrupt the subunit stream.
3627
if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3629
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3591
3631
self.additional_selftest_args.setdefault(
3592
3632
'suite_decorators', []).append(parallel)
3652
3692
class cmd_find_merge_base(Command):
3653
"""Find and print a base revision for merging two branches."""
3693
__doc__ = """Find and print a base revision for merging two branches."""
3654
3694
# TODO: Options to specify revisions on either side, as if
3655
3695
# merging only part of the history.
3656
3696
takes_args = ['branch', 'other']
3678
3718
class cmd_merge(Command):
3679
"""Perform a three-way merge.
3719
__doc__ = """Perform a three-way merge.
3681
3721
The source of the merge can be specified either in the form of a branch,
3682
3722
or in the form of a path to a file containing a merge directive generated
3765
3805
' completely merged into the source, pull from the'
3766
3806
' source rather than merging. When this happens,'
3767
3807
' you do not need to commit the result.'),
3808
custom_help('directory',
3769
3809
help='Branch to merge into, '
3770
'rather than the one containing the working directory.',
3810
'rather than the one containing the working directory.'),
3774
3811
Option('preview', help='Instead of merging, show a diff of the'
3776
3813
Option('interactive', help='Select changes interactively.',
4069
4106
def run(self, file_list=None, merge_type=None, show_base=False,
4070
4107
reprocess=False):
4108
from bzrlib.conflicts import restore
4071
4109
if merge_type is None:
4072
4110
merge_type = _mod_merge.Merge3Merger
4073
4111
tree, file_list = tree_files(file_list)
4133
4171
class cmd_revert(Command):
4134
"""Revert files to a previous revision.
4172
__doc__ = """Revert files to a previous revision.
4136
4174
Giving a list of files will revert only those files. Otherwise, all files
4137
4175
will be reverted. If the revision is not specified with '--revision', the
4188
4226
def run(self, revision=None, no_backup=False, file_list=None,
4189
4227
forget_merges=None):
4190
4228
tree, file_list = tree_files(file_list)
4229
tree.lock_tree_write()
4192
4230
self.add_cleanup(tree.unlock)
4193
4231
if forget_merges:
4194
4232
tree.set_parent_ids(tree.get_parent_ids()[:1])
4345
4386
remote_branch = Branch.open(other_branch)
4346
4387
if remote_branch.base == local_branch.base:
4347
4388
remote_branch = local_branch
4390
remote_branch.lock_read()
4391
self.add_cleanup(remote_branch.unlock)
4349
local_branch.lock_read()
4350
self.add_cleanup(local_branch.unlock)
4351
4393
local_revid_range = _revision_range_to_revid_range(
4352
4394
_get_revision_range(my_revision, local_branch,
4355
remote_branch.lock_read()
4356
self.add_cleanup(remote_branch.unlock)
4357
4397
remote_revid_range = _revision_range_to_revid_range(
4358
4398
_get_revision_range(revision,
4359
4399
remote_branch, self.name()))
4420
4460
class cmd_pack(Command):
4421
"""Compress the data within a repository."""
4461
__doc__ = """Compress the data within a repository.
4463
This operation compresses the data within a bazaar repository. As
4464
bazaar supports automatic packing of repository, this operation is
4465
normally not required to be done manually.
4467
During the pack operation, bazaar takes a backup of existing repository
4468
data, i.e. pack files. This backup is eventually removed by bazaar
4469
automatically when it is safe to do so. To save disk space by removing
4470
the backed up pack files, the --clean-obsolete-packs option may be
4473
Warning: If you use --clean-obsolete-packs and your machine crashes
4474
during or immediately after repacking, you may be left with a state
4475
where the deletion has been written to disk but the new packs have not
4476
been. In this case the repository may be unusable.
4423
4479
_see_also = ['repositories']
4424
4480
takes_args = ['branch_or_repo?']
4482
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4426
def run(self, branch_or_repo='.'):
4485
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4427
4486
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4429
4488
branch = dir.open_branch()
4430
4489
repository = branch.repository
4431
4490
except errors.NotBranchError:
4432
4491
repository = dir.open_repository()
4492
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4436
4495
class cmd_plugins(Command):
4437
"""List the installed plugins.
4496
__doc__ = """List the installed plugins.
4439
4498
This command displays the list of installed plugins including
4440
4499
version of plugin and a short description of each.
4513
4572
class cmd_annotate(Command):
4514
"""Show the origin of each line in a file.
4573
__doc__ = """Show the origin of each line in a file.
4516
4575
This prints out the given file with an annotation on the left side
4517
4576
indicating which revision, author and date introduced the change.
4528
4587
Option('long', help='Show commit date in annotations.'),
4532
4592
encoding_type = 'exact'
4534
4594
@display_command
4535
4595
def run(self, filename, all=False, long=False, revision=None,
4596
show_ids=False, directory=None):
4537
4597
from bzrlib.annotate import annotate_file, annotate_file_tree
4538
4598
wt, branch, relpath = \
4539
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4599
_open_directory_or_containing_tree_or_branch(filename, directory)
4540
4600
if wt is not None:
4542
4602
self.add_cleanup(wt.unlock)
4566
4626
class cmd_re_sign(Command):
4567
"""Create a digital signature for an existing revision."""
4627
__doc__ = """Create a digital signature for an existing revision."""
4568
4628
# TODO be able to replace existing ones.
4570
4630
hidden = True # is this right ?
4571
4631
takes_args = ['revision_id*']
4572
takes_options = ['revision']
4632
takes_options = ['directory', 'revision']
4574
def run(self, revision_id_list=None, revision=None):
4634
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4575
4635
if revision_id_list is not None and revision is not None:
4576
4636
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4577
4637
if revision_id_list is None and revision is None:
4578
4638
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4579
b = WorkingTree.open_containing(u'.')[0].branch
4639
b = WorkingTree.open_containing(directory)[0].branch
4581
4641
self.add_cleanup(b.unlock)
4582
4642
return self._run(b, revision_id_list, revision)
4632
4692
class cmd_bind(Command):
4633
"""Convert the current branch into a checkout of the supplied branch.
4693
__doc__ = """Convert the current branch into a checkout of the supplied branch.
4694
If no branch is supplied, rebind to the last bound location.
4635
4696
Once converted into a checkout, commits must succeed on the master branch
4636
4697
before they will be applied to the local branch.
4643
4704
_see_also = ['checkouts', 'unbind']
4644
4705
takes_args = ['location?']
4706
takes_options = ['directory']
4647
def run(self, location=None):
4648
b, relpath = Branch.open_containing(u'.')
4708
def run(self, location=None, directory=u'.'):
4709
b, relpath = Branch.open_containing(directory)
4649
4710
if location is None:
4651
4712
location = b.get_old_bound_location()
4672
4733
class cmd_unbind(Command):
4673
"""Convert the current checkout into a regular branch.
4734
__doc__ = """Convert the current checkout into a regular branch.
4675
4736
After unbinding, the local branch is considered independent and subsequent
4676
4737
commits will be local only.
4679
4740
_see_also = ['checkouts', 'bind']
4680
4741
takes_args = []
4742
takes_options = ['directory']
4684
b, relpath = Branch.open_containing(u'.')
4744
def run(self, directory=u'.'):
4745
b, relpath = Branch.open_containing(directory)
4685
4746
if not b.unbind():
4686
4747
raise errors.BzrCommandError('Local branch is not bound')
4689
4750
class cmd_uncommit(Command):
4690
"""Remove the last committed revision.
4751
__doc__ = """Remove the last committed revision.
4692
4753
--verbose will print out what is being removed.
4693
4754
--dry-run will go through all the motions, but not actually
4797
4858
class cmd_break_lock(Command):
4798
"""Break a dead lock on a repository, branch or working directory.
4859
__doc__ = """Break a dead lock on a repository, branch or working directory.
4800
4861
CAUTION: Locks should only be broken when you are sure that the process
4801
4862
holding the lock has been stopped.
4851
4912
'result in a dynamically allocated port. The default port '
4852
4913
'depends on the protocol.',
4855
help='Serve contents of this directory.',
4915
custom_help('directory',
4916
help='Serve contents of this directory.'),
4857
4917
Option('allow-writes',
4858
4918
help='By default the server is a readonly server. Supplying '
4859
4919
'--allow-writes enables write access to the contents of '
4948
5008
class cmd_split(Command):
4949
"""Split a subdirectory of a tree into a separate tree.
5009
__doc__ = """Split a subdirectory of a tree into a separate tree.
4951
5011
This command will produce a target tree in a format that supports
4952
5012
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4974
5034
class cmd_merge_directive(Command):
4975
"""Generate a merge directive for auto-merge tools.
5035
__doc__ = """Generate a merge directive for auto-merge tools.
4977
5037
A directive requests a merge to be performed, and also provides all the
4978
5038
information necessary to do so. This means it must either include a
5263
5323
class cmd_tag(Command):
5264
"""Create, remove or modify a tag naming a revision.
5324
__doc__ = """Create, remove or modify a tag naming a revision.
5266
5326
Tags give human-meaningful names to revisions. Commands that take a -r
5267
5327
(--revision) option can be given -rtag:X, where X is any previously
5288
5348
Option('delete',
5289
5349
help='Delete this tag rather than placing it.',
5292
help='Branch in which to place the tag.',
5351
custom_help('directory',
5352
help='Branch in which to place the tag.'),
5296
5353
Option('force',
5297
5354
help='Replace existing tags.',
5336
5393
class cmd_tags(Command):
5394
__doc__ = """List tags.
5339
5396
This command shows a table of tag names and the revisions they reference.
5342
5399
_see_also = ['tag']
5343
5400
takes_options = [
5345
help='Branch whose tags should be displayed.',
5401
custom_help('directory',
5402
help='Branch whose tags should be displayed.'),
5349
5403
RegistryOption.from_kwargs('sort',
5350
5404
'Sort tags by different criteria.', title='Sorting',
5351
5405
alpha='Sort tags lexicographically (default).',
5501
5555
class cmd_switch(Command):
5502
"""Set the branch of a checkout and update.
5556
__doc__ = """Set the branch of a checkout and update.
5504
5558
For lightweight checkouts, this changes the branch being referenced.
5505
5559
For heavyweight checkouts, this checks that there are no local commits
5796
5850
class cmd_shelve(Command):
5797
"""Temporarily set aside some changes from the current tree.
5851
__doc__ = """Temporarily set aside some changes from the current tree.
5799
5853
Shelve allows you to temporarily put changes you've made "on the shelf",
5800
5854
ie. out of the way, until a later time when you can bring them back from
5871
5925
class cmd_unshelve(Command):
5872
"""Restore shelved changes.
5926
__doc__ = """Restore shelved changes.
5874
5928
By default, the most recently shelved changes are restored. However if you
5875
5929
specify a shelf by id those changes will be restored instead. This works
5903
5957
class cmd_clean_tree(Command):
5904
"""Remove unwanted files from working tree.
5958
__doc__ = """Remove unwanted files from working tree.
5906
5960
By default, only unknown files, not ignored files, are deleted. Versioned
5907
5961
files are never deleted.
5916
5970
To check what clean-tree will do, use --dry-run.
5918
takes_options = [Option('ignored', help='Delete all ignored files.'),
5972
takes_options = ['directory',
5973
Option('ignored', help='Delete all ignored files.'),
5919
5974
Option('detritus', help='Delete conflict files, merge'
5920
5975
' backups, and failed selftest dirs.'),
5921
5976
Option('unknown',
5924
5979
' deleting them.'),
5925
5980
Option('force', help='Do not prompt before deleting.')]
5926
5981
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5982
force=False, directory=u'.'):
5928
5983
from bzrlib.clean_tree import clean_tree
5929
5984
if not (unknown or ignored or detritus):
5933
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5934
dry_run=dry_run, no_prompt=force)
5988
clean_tree(directory, unknown=unknown, ignored=ignored,
5989
detritus=detritus, dry_run=dry_run, no_prompt=force)
5937
5992
class cmd_reference(Command):
5938
"""list, view and set branch locations for nested trees.
5993
__doc__ = """list, view and set branch locations for nested trees.
5940
5995
If no arguments are provided, lists the branch locations for nested trees.
5941
5996
If one argument is provided, display the branch location for that tree.
5981
6036
self.outf.write('%s %s\n' % (path, location))
5984
from bzrlib.cmd_version_info import cmd_version_info
5985
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5986
from bzrlib.foreign import cmd_dpush
5987
from bzrlib.sign_my_commits import cmd_sign_my_commits
6039
def _register_lazy_builtins():
6040
# register lazy builtins from other modules; called at startup and should
6041
# be only called once.
6042
for (name, aliases, module_name) in [
6043
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6044
('cmd_dpush', [], 'bzrlib.foreign'),
6045
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6046
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6047
('cmd_conflicts', [], 'bzrlib.conflicts'),
6048
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6050
builtin_command_registry.register_lazy(name, aliases, module_name)