55
55
from bzrlib.branch import Branch
56
56
from bzrlib.conflicts import ConflictList
57
from bzrlib.transport import memory
57
58
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
58
59
from bzrlib.smtp_connection import SMTPConnection
59
60
from bzrlib.workingtree import WorkingTree
62
from bzrlib.commands import Command, display_command
63
from bzrlib.commands import (
65
builtin_command_registry,
63
68
from bzrlib.option import (
339
344
# cat-revision is more for frontends so should be exact
340
345
encoding = 'strict'
347
def print_revision(self, revisions, revid):
348
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
349
record = stream.next()
350
if record.storage_kind == 'absent':
351
raise errors.NoSuchRevision(revisions, revid)
352
revtext = record.get_bytes_as('fulltext')
353
self.outf.write(revtext.decode('utf-8'))
343
356
def run(self, revision_id=None, revision=None):
344
357
if revision_id is not None and revision is not None:
349
362
' --revision or a revision_id')
350
363
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'))
365
revisions = b.repository.revisions
366
if revisions is None:
367
raise errors.BzrCommandError('Repository %r does not support '
368
'access to raw revision texts')
370
b.repository.lock_read()
372
# TODO: jam 20060112 should cat-revision always output utf-8?
373
if revision_id is not None:
374
revision_id = osutils.safe_revision_id(revision_id, warn=False)
376
self.print_revision(revisions, revision_id)
377
except errors.NoSuchRevision:
378
msg = "The repository %s contains no revision %s." % (
379
b.repository.base, revision_id)
380
raise errors.BzrCommandError(msg)
381
elif revision is not None:
384
raise errors.BzrCommandError(
385
'You cannot specify a NULL revision.')
386
rev_id = rev.as_revision_id(b)
387
self.print_revision(revisions, rev_id)
389
b.repository.unlock()
370
392
class cmd_dump_btree(Command):
371
393
"""Dump the contents of a btree index file to stdout.
438
460
for node in bt.iter_all_entries():
439
461
# Node is made up of:
440
462
# (index, key, value, [references])
441
refs_as_tuples = static_tuple.as_tuples(node[3])
466
refs_as_tuples = None
468
refs_as_tuples = static_tuple.as_tuples(refs)
442
469
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
443
470
self.outf.write('%s\n' % (as_tuple,))
452
479
To re-create the working tree, use "bzr checkout".
454
481
_see_also = ['checkout', 'working-trees']
455
takes_args = ['location?']
482
takes_args = ['location*']
456
483
takes_options = [
458
485
help='Remove the working tree even if it has '
459
486
'uncommitted changes.'),
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()
489
def run(self, location_list, force=False):
490
if not location_list:
493
for location in location_list:
494
d = bzrdir.BzrDir.open(location)
497
working = d.open_workingtree()
498
except errors.NoWorkingTree:
499
raise errors.BzrCommandError("No working tree to remove")
500
except errors.NotLocalUrl:
501
raise errors.BzrCommandError("You cannot remove the working tree"
504
if (working.has_changes()):
505
raise errors.UncommittedChanges(working)
507
working_path = working.bzrdir.root_transport.base
508
branch_path = working.branch.bzrdir.root_transport.base
509
if working_path != branch_path:
510
raise errors.BzrCommandError("You cannot remove the working tree"
511
" from a lightweight checkout")
513
d.destroy_workingtree()
485
516
class cmd_revno(Command):
678
709
def run(self, dir_list):
679
710
for d in dir_list:
681
711
wt, dd = WorkingTree.open_containing(d)
683
self.outf.write('added %s\n' % 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)
686
722
class cmd_relpath(Command):
1396
1432
branch_location = tree.branch.base
1397
1433
self.add_cleanup(tree.unlock)
1398
1434
# get rid of the final '/' and be ready for display
1399
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1435
branch_location = urlutils.unescape_for_display(
1436
branch_location.rstrip('/'),
1401
1438
existing_pending_merges = tree.get_parent_ids()[1:]
1402
1439
if master is None:
1917
1954
help='Use this command to compare files.',
1957
RegistryOption('format',
1958
help='Diff format to use.',
1959
lazy_registry=('bzrlib.diff', 'format_registry'),
1960
value_switches=False, title='Diff format'),
1921
1962
aliases = ['di', 'dif']
1922
1963
encoding_type = 'exact'
1924
1965
@display_command
1925
1966
def run(self, revision=None, file_list=None, diff_options=None,
1926
prefix=None, old=None, new=None, using=None):
1927
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1967
prefix=None, old=None, new=None, using=None, format=None):
1968
from bzrlib.diff import (get_trees_and_branches_to_diff,
1929
1971
if (prefix is None) or (prefix == '0'):
1930
1972
# diff -p0 format
1944
1986
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1945
1987
' one or two revision specifiers')
1989
if using is not None and format is not None:
1990
raise errors.BzrCommandError('--using and --format are mutually '
1947
1993
(old_tree, new_tree,
1948
1994
old_branch, new_branch,
1949
1995
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1952
1998
specific_files=specific_files,
1953
1999
external_diff_options=diff_options,
1954
2000
old_label=old_label, new_label=new_label,
1955
extra_trees=extra_trees, using=using)
2001
extra_trees=extra_trees, using=using,
1958
2005
class cmd_deleted(Command):
2191
2238
:Tips & tricks:
2193
2240
GUI tools and IDEs are often better at exploring history than command
2194
line tools. You may prefer qlog or glog 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.
2241
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2242
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2243
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2244
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2202
2246
You may find it useful to add the aliases below to ``bazaar.conf``::
2409
2453
raise errors.BzrCommandError(
2410
2454
"bzr %s doesn't accept two revisions in different"
2411
2455
" branches." % command_name)
2412
rev1 = start_spec.in_history(branch)
2456
if start_spec.spec is None:
2457
# Avoid loading all the history.
2458
rev1 = RevisionInfo(branch, None, None)
2460
rev1 = start_spec.in_history(branch)
2413
2461
# Avoid loading all of history when we know a missing
2414
2462
# end of range means the last revision ...
2415
2463
if end_spec.spec is None:
2665
2713
if old_default_rules is not None:
2666
2714
# dump the rules and exit
2667
2715
for pattern in ignores.OLD_DEFAULTS:
2716
self.outf.write("%s\n" % pattern)
2670
2718
if not name_pattern_list:
2671
2719
raise errors.BzrCommandError("ignore requires at least one "
2687
2735
if id is not None:
2688
2736
filename = entry[0]
2689
2737
if ignored.match(filename):
2690
matches.append(filename.encode('utf-8'))
2738
matches.append(filename)
2692
2740
if len(matches) > 0:
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),)
2741
self.outf.write("Warning: the following files are version controlled and"
2742
" match your ignore pattern:\n%s"
2743
"\nThese files will continue to be version controlled"
2744
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2699
2747
class cmd_ignored(Command):
2738
2786
revno = int(revno)
2739
2787
except ValueError:
2740
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2742
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2788
raise errors.BzrCommandError("not a valid revision-number: %r"
2790
revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2791
self.outf.write("%s\n" % revid)
2745
2794
class cmd_export(Command):
2783
2832
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.'),
2785
2837
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2786
root=None, filters=False):
2838
root=None, filters=False, per_file_timestamps=False):
2787
2839
from bzrlib.export import export
2789
2841
if branch_or_subdir is None:
2797
2849
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2799
export(rev_tree, dest, format, root, subdir, filtered=filters)
2851
export(rev_tree, dest, format, root, subdir, filtered=filters,
2852
per_file_timestamps=per_file_timestamps)
2800
2853
except errors.NoSuchExportFormat, e:
2801
2854
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3097
3150
'(use --file "%(f)s" to take commit message from that file)'
3098
3151
% { 'f': message })
3099
3152
ui.ui_factory.show_warning(warning_msg)
3154
message = message.replace('\r\n', '\n')
3155
message = message.replace('\r', '\n')
3157
raise errors.BzrCommandError(
3158
"please specify either --message or --file")
3101
3160
def get_message(commit_obj):
3102
3161
"""Callback to get commit message"""
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,
3163
my_message = codecs.open(
3164
file, 'rt', osutils.get_user_encoding()).read()
3165
elif message is not None:
3166
my_message = message
3168
# No message supplied: make one up.
3169
# text is the status of the tree
3170
text = make_commit_message_template_encoded(tree,
3109
3171
selected_list, diff=show_diff,
3110
3172
output_encoding=osutils.get_user_encoding())
3173
# start_message is the template generated from hooks
3174
# XXX: Warning - looks like hooks return unicode,
3175
# make_commit_message_template_encoded returns user encoding.
3176
# We probably want to be using edit_commit_message instead to
3111
3178
start_message = generate_commit_message_template(commit_obj)
3112
my_message = edit_commit_message_encoded(t,
3179
my_message = edit_commit_message_encoded(text,
3113
3180
start_message=start_message)
3114
3181
if my_message is None:
3115
3182
raise errors.BzrCommandError("please specify a commit"
3116
3183
" 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()
3123
3184
if my_message == "":
3124
3185
raise errors.BzrCommandError("empty commit message specified")
3125
3186
return my_message
3137
3198
timezone=offset,
3138
3199
exclude=safe_relpath_files(tree, exclude))
3139
3200
except PointlessCommit:
3140
# FIXME: This should really happen before the file is read in;
3141
# perhaps prepare the commit; get the message; then actually commit
3142
3201
raise errors.BzrCommandError("No changes to commit."
3143
3202
" Use --unchanged to commit anyhow.")
3144
3203
except ConflictsInTree:
3149
3208
raise errors.BzrCommandError("Commit refused because there are"
3150
3209
" unknown files in the working tree.")
3151
3210
except errors.BoundBranchOutOfDate, e:
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 '
3211
e.extra_help = ("\n"
3212
'To commit to master branch, run update and then commit.\n'
3213
'You can also pass --local to commit to continue working '
3158
3218
class cmd_check(Command):
3447
3507
from bzrlib.tests import stub_sftp
3448
3508
return stub_sftp.SFTPAbsoluteServer
3449
3509
if typestring == "memory":
3450
from bzrlib.transport.memory import MemoryServer
3510
from bzrlib.tests import test_server
3511
return memory.MemoryServer
3452
3512
if typestring == "fakenfs":
3453
from bzrlib.transport.fakenfs import FakeNFSServer
3454
return FakeNFSServer
3513
from bzrlib.tests import test_server
3514
return test_server.FakeNFSServer
3455
3515
msg = "No known transport type %s. Supported types are: sftp\n" %\
3457
3517
raise errors.BzrCommandError(msg)
3626
3686
graph = branch1.repository.get_graph(branch2.repository)
3627
3687
base_rev_id = graph.find_unique_lca(last1, last2)
3629
print 'merge base is revision %s' % base_rev_id
3689
self.outf.write('merge base is revision %s\n' % base_rev_id)
3632
3692
class cmd_merge(Command):
3780
3840
raise errors.BzrCommandError(
3781
3841
'Cannot use -r with merge directives or bundles')
3782
3842
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3785
3845
if merger is None and uncommitted:
3786
3846
if revision is not None and len(revision) > 0:
3787
3847
raise errors.BzrCommandError('Cannot use --uncommitted and'
3788
3848
' --revision at the same time.')
3789
merger = self.get_merger_from_uncommitted(tree, location, pb)
3849
merger = self.get_merger_from_uncommitted(tree, location, None)
3790
3850
allow_pending = False
3792
3852
if merger is None:
3793
3853
merger, allow_pending = self._get_merger_from_branch(tree,
3794
location, revision, remember, possible_transports, pb)
3854
location, revision, remember, possible_transports, None)
3796
3856
merger.merge_type = merge_type
3797
3857
merger.reprocess = reprocess
4023
4083
def run(self, file_list=None, merge_type=None, show_base=False,
4024
4084
reprocess=False):
4085
from bzrlib.conflicts import restore
4025
4086
if merge_type is None:
4026
4087
merge_type = _mod_merge.Merge3Merger
4027
4088
tree, file_list = tree_files(file_list)
4068
4129
# list, we imply that the working tree text has seen and rejected
4069
4130
# all the changes from the other tree, when in fact those changes
4070
4131
# have not yet been seen.
4071
pb = ui.ui_factory.nested_progress_bar()
4072
4132
tree.set_parent_ids(parents[:1])
4074
merger = _mod_merge.Merger.from_revision_ids(pb,
4134
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4076
4135
merger.interesting_ids = interesting_ids
4077
4136
merger.merge_type = merge_type
4078
4137
merger.show_base = show_base
4156
4214
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4157
4215
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4158
pb = ui.ui_factory.nested_progress_bar()
4160
tree.revert(file_list, rev_tree, not no_backup, pb,
4161
report_changes=True)
4216
tree.revert(file_list, rev_tree, not no_backup, None,
4217
report_changes=True)
4166
4220
class cmd_assert_fail(Command):
4408
4462
adding new commands, providing additional network transports and
4409
4463
customizing log output.
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.
4465
See the Bazaar Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/>
4466
for further information on plugins including where to find them and how to
4467
install them. Instructions are also provided there on how to write new
4468
plugins using the Python programming language.
4416
4470
takes_options = ['verbose']
4432
4486
doc = '(no description)'
4433
4487
result.append((name_ver, doc, plugin.path()))
4434
4488
for name_ver, doc, path in sorted(result):
4489
self.outf.write("%s\n" % name_ver)
4490
self.outf.write(" %s\n" % doc)
4492
self.outf.write(" %s\n" % path)
4493
self.outf.write("\n")
4442
4496
class cmd_testament(Command):
4615
4669
'This format does not remember old locations.')
4617
4671
if location is None:
4618
raise errors.BzrCommandError('No location supplied and no '
4619
'previous location known')
4672
if b.get_bound_location() is not None:
4673
raise errors.BzrCommandError('Branch is already bound')
4675
raise errors.BzrCommandError('No location supplied '
4676
'and no previous location known')
4620
4677
b_other = Branch.open(location)
4622
4679
b.bind(b_other)
4734
4791
end_revision=last_revno)
4737
print 'Dry-run, pretending to remove the above revisions.'
4739
val = raw_input('Press <enter> to continue')
4794
self.outf.write('Dry-run, pretending to remove'
4795
' the above revisions.\n')
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'):
4797
self.outf.write('The above revision(s) will be removed.\n')
4800
if not ui.ui_factory.get_boolean('Are you sure'):
4801
self.outf.write('Canceled')
4748
4804
mutter('Uncommitting from {%s} to {%s}',
4749
4805
last_rev_id, rev_id)
4750
4806
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4751
4807
revno=revno, local=local)
4752
note('You can restore the old tip by running:\n'
4753
' bzr pull . -r revid:%s', last_rev_id)
4808
self.outf.write('You can restore the old tip by running:\n'
4809
' bzr pull . -r revid:%s\n' % last_rev_id)
4756
4812
class cmd_break_lock(Command):
5235
5291
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5236
5292
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5294
If no tag name is specified it will be determined through the
5295
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5296
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5239
5300
_see_also = ['commit', 'tags']
5240
takes_args = ['tag_name']
5301
takes_args = ['tag_name?']
5241
5302
takes_options = [
5242
5303
Option('delete',
5243
5304
help='Delete this tag rather than placing it.',
5274
5337
revision_id = revision[0].as_revision_id(branch)
5276
5339
revision_id = branch.last_revision()
5340
if tag_name is None:
5341
tag_name = branch.automatic_tag_name(revision_id)
5342
if tag_name is None:
5343
raise errors.BzrCommandError(
5344
"Please specify a tag name.")
5277
5345
if (not force) and branch.tags.has_tag(tag_name):
5278
5346
raise errors.TagAlreadyExists(tag_name)
5279
5347
branch.tags.set_tag(tag_name, revision_id)
5715
5783
self.outf.write(" <no hooks installed>\n")
5786
class cmd_remove_branch(Command):
5789
This will remove the branch from the specified location but
5790
will keep any working tree or repository in place.
5794
Remove the branch at repo/trunk::
5796
bzr remove-branch repo/trunk
5800
takes_args = ["location?"]
5802
aliases = ["rmbranch"]
5804
def run(self, location=None):
5805
if location is None:
5807
branch = Branch.open_containing(location)[0]
5808
branch.bzrdir.destroy_branch()
5718
5811
class cmd_shelve(Command):
5719
5812
"""Temporarily set aside some changes from the current tree.
5903
5996
self.outf.write('%s %s\n' % (path, location))
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
5999
def _register_lazy_builtins():
6000
# register lazy builtins from other modules; called at startup and should
6001
# be only called once.
6002
for (name, aliases, module_name) in [
6003
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6004
('cmd_dpush', [], 'bzrlib.foreign'),
6005
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6006
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6007
('cmd_conflicts', [], 'bzrlib.conflicts'),
6008
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6010
builtin_command_registry.register_lazy(name, aliases, module_name)