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
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)
515
if working.user_url != working.branch.user_url:
516
raise errors.BzrCommandError("You cannot remove the working tree"
517
" from a lightweight checkout")
519
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()
522
485
class cmd_revno(Command):
523
__doc__ = """Show current revision number.
486
"""Show current revision number.
525
488
This is equal to the number of revisions on this branch.
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'),
712
678
def run(self, dir_list):
713
679
for d in dir_list:
714
681
wt, dd = WorkingTree.open_containing(d)
715
base = os.path.dirname(dd)
716
id = wt.path2id(base)
720
self.outf.write('added %s\n' % d)
722
raise errors.NotVersionedError(path=base)
683
self.outf.write('added %s\n' % d)
725
686
class cmd_relpath(Command):
726
__doc__ = """Show path of a file relative to root"""
687
"""Show path of a file relative to root"""
728
689
takes_args = ['filename']
965
926
takes_options = ['remember', 'overwrite', 'revision',
966
927
custom_help('verbose',
967
928
help='Show logs of pulled revisions.'),
968
custom_help('directory',
969
930
help='Branch to pull into, '
970
'rather than the one containing the working directory.'),
931
'rather than the one containing the working directory.',
972
936
help="Perform a local pull in a bound "
973
937
"branch. Local pulls are not applied to "
1032
992
branch_from = Branch.open(location,
1033
993
possible_transports=possible_transports)
995
if branch_to.get_parent() is None or remember:
996
branch_to.set_parent(branch_from.base)
998
if branch_from is not branch_to:
1034
999
branch_from.lock_read()
1035
1000
self.add_cleanup(branch_from.unlock)
1037
if branch_to.get_parent() is None or remember:
1038
branch_to.set_parent(branch_from.base)
1040
1001
if revision is not None:
1041
1002
revision_id = revision.as_revision_id(branch_from)
1004
branch_to.lock_write()
1005
self.add_cleanup(branch_to.unlock)
1043
1006
if tree_to is not None:
1044
1007
view_info = _get_view_info_for_change_reporter(tree_to)
1045
1008
change_reporter = delta._ChangeReporter(
1090
1053
Option('create-prefix',
1091
1054
help='Create the path leading up to the branch '
1092
1055
'if it does not already exist.'),
1093
custom_help('directory',
1094
1057
help='Branch to push from, '
1095
'rather than the one containing the working directory.'),
1058
'rather than the one containing the working directory.',
1096
1062
Option('use-existing-dir',
1097
1063
help='By default push will fail if the target'
1098
1064
' directory exists, but does not already'
1124
1090
# Get the source branch
1125
1091
(tree, br_from,
1126
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
1127
1096
# Get the tip's revision_id
1128
1097
revision = _get_one_revision('push', revision)
1129
1098
if revision is not None:
1130
1099
revision_id = revision.in_history(br_from).rev_id
1132
1101
revision_id = None
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.')
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.')
1138
1113
# Get the stacked_on branch, if any
1139
1114
if stacked_on is not None:
1140
1115
stacked_on = urlutils.normalize_url(stacked_on)
1438
1412
revision_id = branch.last_revision()
1439
1413
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
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))
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))
1444
1418
view_info = _get_view_info_for_change_reporter(tree)
1445
1419
change_reporter = delta._ChangeReporter(
1457
1431
"bzr update --revision only works"
1458
1432
" for a revision in the branch history"
1459
1433
% (e.revision))
1460
revno = tree.branch.revision_id_to_dotted_revno(
1434
revno = tree.branch.revision_id_to_revno(
1461
1435
_mod_revision.ensure_null(tree.last_revision()))
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:
1436
note('Updated to revision %d of branch %s' %
1437
(revno, branch_location))
1438
if tree.get_parent_ids()[1:] != existing_pending_merges:
1466
1439
note('Your local commits will now show as pending merges with '
1467
1440
"'bzr status', and can be committed with 'bzr commit'.")
1468
1441
if conflicts != 0:
1944
1917
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'),
1952
1921
aliases = ['di', 'dif']
1953
1922
encoding_type = 'exact'
1955
1924
@display_command
1956
1925
def run(self, revision=None, file_list=None, diff_options=None,
1957
prefix=None, old=None, new=None, using=None, format=None):
1958
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
1961
1929
if (prefix is None) or (prefix == '0'):
1962
1930
# diff -p0 format
1976
1944
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1977
1945
' 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 '
1983
1947
(old_tree, new_tree,
1984
1948
old_branch, new_branch,
1985
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1986
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1949
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1950
file_list, revision, old, new, apply_view=True)
1987
1951
return show_diff_trees(old_tree, new_tree, sys.stdout,
1988
1952
specific_files=specific_files,
1989
1953
external_diff_options=diff_options,
1990
1954
old_label=old_label, new_label=new_label,
1991
extra_trees=extra_trees, using=using,
1955
extra_trees=extra_trees, using=using)
1995
1958
class cmd_deleted(Command):
1996
__doc__ = """List files deleted in the working tree.
1959
"""List files deleted in the working tree.
1998
1961
# TODO: Show files deleted since a previous revision, or
1999
1962
# between two revisions.
2002
1965
# level of effort but possibly much less IO. (Or possibly not,
2003
1966
# if the directories are very large...)
2004
1967
_see_also = ['status', 'ls']
2005
takes_options = ['directory', 'show-ids']
1968
takes_options = ['show-ids']
2007
1970
@display_command
2008
def run(self, show_ids=False, directory=u'.'):
2009
tree = WorkingTree.open_containing(directory)[0]
1971
def run(self, show_ids=False):
1972
tree = WorkingTree.open_containing(u'.')[0]
2010
1973
tree.lock_read()
2011
1974
self.add_cleanup(tree.unlock)
2012
1975
old = tree.basis_tree()
2024
1987
class cmd_modified(Command):
2025
__doc__ = """List files modified in working tree.
1988
"""List files modified in working tree.
2029
1992
_see_also = ['status', 'ls']
2030
takes_options = ['directory',
2032
1995
help='Write an ascii NUL (\\0) separator '
2033
1996
'between files rather than a newline.')
2036
1999
@display_command
2037
def run(self, null=False, directory=u'.'):
2038
tree = WorkingTree.open_containing(directory)[0]
2000
def run(self, null=False):
2001
tree = WorkingTree.open_containing(u'.')[0]
2039
2002
td = tree.changes_from(tree.basis_tree())
2040
2003
for path, id, kind, text_modified, meta_modified in td.modified:
2047
2010
class cmd_added(Command):
2048
__doc__ = """List files added in working tree.
2011
"""List files added in working tree.
2052
2015
_see_also = ['status', 'ls']
2053
takes_options = ['directory',
2055
2018
help='Write an ascii NUL (\\0) separator '
2056
2019
'between files rather than a newline.')
2059
2022
@display_command
2060
def run(self, null=False, directory=u'.'):
2061
wt = WorkingTree.open_containing(directory)[0]
2023
def run(self, null=False):
2024
wt = WorkingTree.open_containing(u'.')[0]
2063
2026
self.add_cleanup(wt.unlock)
2064
2027
basis = wt.basis_tree()
2428
2381
direction=direction, specific_fileids=file_ids,
2429
2382
start_revision=rev1, end_revision=rev2, limit=limit,
2430
2383
message_search=message, delta_type=delta_type,
2431
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2432
exclude_common_ancestry=exclude_common_ancestry,
2384
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2434
2385
Logger(b, rqst).show(lf)
2455
2406
raise errors.BzrCommandError(
2456
2407
"bzr %s doesn't accept two revisions in different"
2457
2408
" branches." % command_name)
2458
if start_spec.spec is None:
2459
# Avoid loading all the history.
2460
rev1 = RevisionInfo(branch, None, None)
2462
rev1 = start_spec.in_history(branch)
2409
rev1 = start_spec.in_history(branch)
2463
2410
# Avoid loading all of history when we know a missing
2464
2411
# end of range means the last revision ...
2465
2412
if end_spec.spec is None:
2538
2485
help='List entries of a particular kind: file, directory, symlink.',
2543
2489
@display_command
2544
2490
def run(self, revision=None, verbose=False,
2545
2491
recursive=False, from_root=False,
2546
2492
unknown=False, versioned=False, ignored=False,
2547
null=False, kind=None, show_ids=False, path=None, directory=None):
2493
null=False, kind=None, show_ids=False, path=None):
2549
2495
if kind and kind not in ('file', 'directory', 'symlink'):
2550
2496
raise errors.BzrCommandError('invalid kind specified')
2635
2581
class cmd_unknowns(Command):
2636
__doc__ = """List unknown files.
2582
"""List unknown files.
2640
2586
_see_also = ['ls']
2641
takes_options = ['directory']
2643
2588
@display_command
2644
def run(self, directory=u'.'):
2645
for f in WorkingTree.open_containing(directory)[0].unknowns():
2590
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2646
2591
self.outf.write(osutils.quotefn(f) + '\n')
2649
2594
class cmd_ignore(Command):
2650
__doc__ = """Ignore specified files or patterns.
2595
"""Ignore specified files or patterns.
2652
2597
See ``bzr help patterns`` for details on the syntax of patterns.
2662
2607
using this command or directly by using an editor, be sure to commit
2665
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2666
the global ignore file can be found in the application data directory as
2667
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2668
Global ignores are not touched by this command. The global ignore file
2669
can be edited directly using an editor.
2671
2610
Patterns prefixed with '!' are exceptions to ignore patterns and take
2672
2611
precedence over regular ignores. Such exceptions are used to specify
2673
2612
files that should be versioned which would otherwise be ignored.
2714
2653
_see_also = ['status', 'ignored', 'patterns']
2715
2654
takes_args = ['name_pattern*']
2716
takes_options = ['directory',
2717
Option('default-rules',
2718
help='Display the default ignore rules that bzr uses.')
2656
Option('old-default-rules',
2657
help='Write out the ignore rules bzr < 0.9 always used.')
2721
def run(self, name_pattern_list=None, default_rules=None,
2660
def run(self, name_pattern_list=None, old_default_rules=None):
2723
2661
from bzrlib import ignores
2724
if default_rules is not None:
2725
# dump the default rules and exit
2726
for pattern in ignores.USER_DEFAULTS:
2727
self.outf.write("%s\n" % pattern)
2662
if old_default_rules is not None:
2663
# dump the rules and exit
2664
for pattern in ignores.OLD_DEFAULTS:
2729
2667
if not name_pattern_list:
2730
2668
raise errors.BzrCommandError("ignore requires at least one "
2731
"NAME_PATTERN or --default-rules.")
2669
"NAME_PATTERN or --old-default-rules")
2732
2670
name_pattern_list = [globbing.normalize_pattern(p)
2733
2671
for p in name_pattern_list]
2734
2672
for name_pattern in name_pattern_list:
2746
2684
if id is not None:
2747
2685
filename = entry[0]
2748
2686
if ignored.match(filename):
2749
matches.append(filename)
2687
matches.append(filename.encode('utf-8'))
2751
2689
if len(matches) > 0:
2752
self.outf.write("Warning: the following files are version controlled and"
2753
" match your ignore pattern:\n%s"
2754
"\nThese files will continue to be version controlled"
2755
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2690
print "Warning: the following files are version controlled and" \
2691
" match your ignore pattern:\n%s" \
2692
"\nThese files will continue to be version controlled" \
2693
" unless you 'bzr remove' them." % ("\n".join(matches),)
2758
2696
class cmd_ignored(Command):
2759
__doc__ = """List ignored files and the patterns that matched them.
2697
"""List ignored files and the patterns that matched them.
2761
2699
List all the ignored files and the ignore pattern that caused the file to
2769
2707
encoding_type = 'replace'
2770
2708
_see_also = ['ignore', 'ls']
2771
takes_options = ['directory']
2773
2710
@display_command
2774
def run(self, directory=u'.'):
2775
tree = WorkingTree.open_containing(directory)[0]
2712
tree = WorkingTree.open_containing(u'.')[0]
2776
2713
tree.lock_read()
2777
2714
self.add_cleanup(tree.unlock)
2778
2715
for path, file_class, kind, file_id, entry in tree.list_files():
2786
2723
class cmd_lookup_revision(Command):
2787
__doc__ = """Lookup the revision-id from a revision-number
2724
"""Lookup the revision-id from a revision-number
2790
2727
bzr lookup-revision 33
2793
2730
takes_args = ['revno']
2794
takes_options = ['directory']
2796
2732
@display_command
2797
def run(self, revno, directory=u'.'):
2733
def run(self, revno):
2799
2735
revno = int(revno)
2800
2736
except ValueError:
2801
raise errors.BzrCommandError("not a valid revision-number: %r"
2803
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2804
self.outf.write("%s\n" % revid)
2737
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2739
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2807
2742
class cmd_export(Command):
2808
__doc__ = """Export current or past revision to a destination directory or archive.
2743
"""Export current or past revision to a destination directory or archive.
2810
2745
If no revision is specified this exports the last committed revision.
2845
2780
help="Name of the root directory inside the exported file."),
2846
Option('per-file-timestamps',
2847
help='Set modification time of files to that of the last '
2848
'revision in which it was changed.'),
2850
2782
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2851
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2783
root=None, filters=False):
2852
2784
from bzrlib.export import export
2854
2786
if branch_or_subdir is None:
2855
tree = WorkingTree.open_containing(directory)[0]
2787
tree = WorkingTree.open_containing(u'.')[0]
2856
2788
b = tree.branch
2862
2794
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2864
export(rev_tree, dest, format, root, subdir, filtered=filters,
2865
per_file_timestamps=per_file_timestamps)
2796
export(rev_tree, dest, format, root, subdir, filtered=filters)
2866
2797
except errors.NoSuchExportFormat, e:
2867
2798
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2870
2801
class cmd_cat(Command):
2871
__doc__ = """Write the contents of a file as of a given revision to standard output.
2802
"""Write the contents of a file as of a given revision to standard output.
2873
2804
If no revision is nominated, the last revision is used.
2889
2820
@display_command
2890
2821
def run(self, filename, revision=None, name_from_revision=False,
2891
filters=False, directory=None):
2892
2823
if revision is not None and len(revision) != 1:
2893
2824
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2894
2825
" one revision specifier")
2895
2826
tree, branch, relpath = \
2896
_open_directory_or_containing_tree_or_branch(filename, directory)
2827
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2897
2828
branch.lock_read()
2898
2829
self.add_cleanup(branch.unlock)
2899
2830
return self._run(tree, branch, relpath, filename, revision,
2956
2887
class cmd_local_time_offset(Command):
2957
__doc__ = """Show the offset in seconds from GMT to local time."""
2888
"""Show the offset in seconds from GMT to local time."""
2959
2890
@display_command
2961
self.outf.write("%s\n" % osutils.local_time_offset())
2892
print osutils.local_time_offset()
2965
2896
class cmd_commit(Command):
2966
__doc__ = """Commit changes into a new revision.
2897
"""Commit changes into a new revision.
2968
2899
An explanatory message needs to be given for each commit. This is
2969
2900
often done by using the --message option (getting the message from the
3163
3094
'(use --file "%(f)s" to take commit message from that file)'
3164
3095
% { 'f': message })
3165
3096
ui.ui_factory.show_warning(warning_msg)
3167
message = message.replace('\r\n', '\n')
3168
message = message.replace('\r', '\n')
3170
raise errors.BzrCommandError(
3171
"please specify either --message or --file")
3173
3098
def get_message(commit_obj):
3174
3099
"""Callback to get commit message"""
3176
my_message = codecs.open(
3177
file, 'rt', osutils.get_user_encoding()).read()
3178
elif message is not None:
3179
my_message = message
3181
# No message supplied: make one up.
3182
# text is the status of the tree
3183
text = make_commit_message_template_encoded(tree,
3100
my_message = message
3101
if my_message is not None and '\r' in my_message:
3102
my_message = my_message.replace('\r\n', '\n')
3103
my_message = my_message.replace('\r', '\n')
3104
if my_message is None and not file:
3105
t = make_commit_message_template_encoded(tree,
3184
3106
selected_list, diff=show_diff,
3185
3107
output_encoding=osutils.get_user_encoding())
3186
# start_message is the template generated from hooks
3187
# XXX: Warning - looks like hooks return unicode,
3188
# make_commit_message_template_encoded returns user encoding.
3189
# We probably want to be using edit_commit_message instead to
3191
3108
start_message = generate_commit_message_template(commit_obj)
3192
my_message = edit_commit_message_encoded(text,
3109
my_message = edit_commit_message_encoded(t,
3193
3110
start_message=start_message)
3194
3111
if my_message is None:
3195
3112
raise errors.BzrCommandError("please specify a commit"
3196
3113
" message with either --message or --file")
3114
elif my_message and file:
3115
raise errors.BzrCommandError(
3116
"please specify either --message or --file")
3118
my_message = codecs.open(file, 'rt',
3119
osutils.get_user_encoding()).read()
3197
3120
if my_message == "":
3198
3121
raise errors.BzrCommandError("empty commit message specified")
3199
3122
return my_message
3221
3146
raise errors.BzrCommandError("Commit refused because there are"
3222
3147
" unknown files in the working tree.")
3223
3148
except errors.BoundBranchOutOfDate, e:
3224
e.extra_help = ("\n"
3225
'To commit to master branch, run update and then commit.\n'
3226
'You can also pass --local to commit to continue working '
3149
raise errors.BzrCommandError(str(e) + "\n"
3150
'To commit to master branch, run update and then commit.\n'
3151
'You can also pass --local to commit to continue working '
3231
3155
class cmd_check(Command):
3232
__doc__ = """Validate working tree structure, branch consistency and repository history.
3156
"""Validate working tree structure, branch consistency and repository history.
3234
3158
This command checks various invariants about branch and repository storage
3235
3159
to detect data corruption or bzr bugs.
3518
3441
def get_transport_type(typestring):
3519
3442
"""Parse and return a transport specifier."""
3520
3443
if typestring == "sftp":
3521
from bzrlib.tests import stub_sftp
3522
return stub_sftp.SFTPAbsoluteServer
3444
from bzrlib.transport.sftp import SFTPAbsoluteServer
3445
return SFTPAbsoluteServer
3523
3446
if typestring == "memory":
3524
from bzrlib.tests import test_server
3525
return memory.MemoryServer
3447
from bzrlib.transport.memory import MemoryServer
3526
3449
if typestring == "fakenfs":
3527
from bzrlib.tests import test_server
3528
return test_server.FakeNFSServer
3450
from bzrlib.transport.fakenfs import FakeNFSServer
3451
return FakeNFSServer
3529
3452
msg = "No known transport type %s. Supported types are: sftp\n" %\
3531
3454
raise errors.BzrCommandError(msg)
3615
3538
raise errors.BzrCommandError("subunit not available. subunit "
3616
3539
"needs to be installed to use --subunit.")
3617
3540
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3618
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3619
# stdout, which would corrupt the subunit stream.
3620
if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3622
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3624
3542
self.additional_selftest_args.setdefault(
3625
3543
'suite_decorators', []).append(parallel)
3675
3593
class cmd_rocks(Command):
3676
__doc__ = """Statement of optimism."""
3594
"""Statement of optimism."""
3680
3598
@display_command
3682
self.outf.write("It sure does!\n")
3600
print "It sure does!"
3685
3603
class cmd_find_merge_base(Command):
3686
__doc__ = """Find and print a base revision for merging two branches."""
3604
"""Find and print a base revision for merging two branches."""
3687
3605
# TODO: Options to specify revisions on either side, as if
3688
3606
# merging only part of the history.
3689
3607
takes_args = ['branch', 'other']
3705
3623
graph = branch1.repository.get_graph(branch2.repository)
3706
3624
base_rev_id = graph.find_unique_lca(last1, last2)
3708
self.outf.write('merge base is revision %s\n' % base_rev_id)
3626
print 'merge base is revision %s' % base_rev_id
3711
3629
class cmd_merge(Command):
3712
__doc__ = """Perform a three-way merge.
3630
"""Perform a three-way merge.
3714
3632
The source of the merge can be specified either in the form of a branch,
3715
3633
or in the form of a path to a file containing a merge directive generated
3798
3716
' completely merged into the source, pull from the'
3799
3717
' source rather than merging. When this happens,'
3800
3718
' you do not need to commit the result.'),
3801
custom_help('directory',
3802
3720
help='Branch to merge into, '
3803
'rather than the one containing the working directory.'),
3721
'rather than the one containing the working directory.',
3804
3725
Option('preview', help='Instead of merging, show a diff of the'
3806
3727
Option('interactive', help='Select changes interactively.',
3856
3777
raise errors.BzrCommandError(
3857
3778
'Cannot use -r with merge directives or bundles')
3858
3779
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3861
3782
if merger is None and uncommitted:
3862
3783
if revision is not None and len(revision) > 0:
3863
3784
raise errors.BzrCommandError('Cannot use --uncommitted and'
3864
3785
' --revision at the same time.')
3865
merger = self.get_merger_from_uncommitted(tree, location, None)
3786
merger = self.get_merger_from_uncommitted(tree, location, pb)
3866
3787
allow_pending = False
3868
3789
if merger is None:
3869
3790
merger, allow_pending = self._get_merger_from_branch(tree,
3870
location, revision, remember, possible_transports, None)
3791
location, revision, remember, possible_transports, pb)
3872
3793
merger.merge_type = merge_type
3873
3794
merger.reprocess = reprocess
4145
4065
# list, we imply that the working tree text has seen and rejected
4146
4066
# all the changes from the other tree, when in fact those changes
4147
4067
# have not yet been seen.
4068
pb = ui.ui_factory.nested_progress_bar()
4148
4069
tree.set_parent_ids(parents[:1])
4150
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4071
merger = _mod_merge.Merger.from_revision_ids(pb,
4151
4073
merger.interesting_ids = interesting_ids
4152
4074
merger.merge_type = merge_type
4153
4075
merger.show_base = show_base
4230
4153
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4231
4154
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4232
tree.revert(file_list, rev_tree, not no_backup, None,
4233
report_changes=True)
4155
pb = ui.ui_factory.nested_progress_bar()
4157
tree.revert(file_list, rev_tree, not no_backup, pb,
4158
report_changes=True)
4236
4163
class cmd_assert_fail(Command):
4237
__doc__ = """Test reporting of assertion failures"""
4164
"""Test reporting of assertion failures"""
4238
4165
# intended just for use in testing
4379
4303
remote_branch = Branch.open(other_branch)
4380
4304
if remote_branch.base == local_branch.base:
4381
4305
remote_branch = local_branch
4383
remote_branch.lock_read()
4384
self.add_cleanup(remote_branch.unlock)
4307
local_branch.lock_read()
4308
self.add_cleanup(local_branch.unlock)
4386
4309
local_revid_range = _revision_range_to_revid_range(
4387
4310
_get_revision_range(my_revision, local_branch,
4313
remote_branch.lock_read()
4314
self.add_cleanup(remote_branch.unlock)
4390
4315
remote_revid_range = _revision_range_to_revid_range(
4391
4316
_get_revision_range(revision,
4392
4317
remote_branch, self.name()))
4453
4378
class cmd_pack(Command):
4454
__doc__ = """Compress the data within a repository.
4456
This operation compresses the data within a bazaar repository. As
4457
bazaar supports automatic packing of repository, this operation is
4458
normally not required to be done manually.
4460
During the pack operation, bazaar takes a backup of existing repository
4461
data, i.e. pack files. This backup is eventually removed by bazaar
4462
automatically when it is safe to do so. To save disk space by removing
4463
the backed up pack files, the --clean-obsolete-packs option may be
4466
Warning: If you use --clean-obsolete-packs and your machine crashes
4467
during or immediately after repacking, you may be left with a state
4468
where the deletion has been written to disk but the new packs have not
4469
been. In this case the repository may be unusable.
4379
"""Compress the data within a repository."""
4472
4381
_see_also = ['repositories']
4473
4382
takes_args = ['branch_or_repo?']
4475
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4478
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4384
def run(self, branch_or_repo='.'):
4479
4385
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4481
4387
branch = dir.open_branch()
4482
4388
repository = branch.repository
4483
4389
except errors.NotBranchError:
4484
4390
repository = dir.open_repository()
4485
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4488
4394
class cmd_plugins(Command):
4489
__doc__ = """List the installed plugins.
4395
"""List the installed plugins.
4491
4397
This command displays the list of installed plugins including
4492
4398
version of plugin and a short description of each.
4523
4429
doc = '(no description)'
4524
4430
result.append((name_ver, doc, plugin.path()))
4525
4431
for name_ver, doc, path in sorted(result):
4526
self.outf.write("%s\n" % name_ver)
4527
self.outf.write(" %s\n" % doc)
4529
self.outf.write(" %s\n" % path)
4530
self.outf.write("\n")
4533
4439
class cmd_testament(Command):
4534
__doc__ = """Show testament (signing-form) of a revision."""
4440
"""Show testament (signing-form) of a revision."""
4535
4441
takes_options = [
4537
4443
Option('long', help='Produce long-format testament.'),
4580
4486
Option('long', help='Show commit date in annotations.'),
4585
4490
encoding_type = 'exact'
4587
4492
@display_command
4588
4493
def run(self, filename, all=False, long=False, revision=None,
4589
show_ids=False, directory=None):
4590
4495
from bzrlib.annotate import annotate_file, annotate_file_tree
4591
4496
wt, branch, relpath = \
4592
_open_directory_or_containing_tree_or_branch(filename, directory)
4497
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4593
4498
if wt is not None:
4595
4500
self.add_cleanup(wt.unlock)
4619
4524
class cmd_re_sign(Command):
4620
__doc__ = """Create a digital signature for an existing revision."""
4525
"""Create a digital signature for an existing revision."""
4621
4526
# TODO be able to replace existing ones.
4623
4528
hidden = True # is this right ?
4624
4529
takes_args = ['revision_id*']
4625
takes_options = ['directory', 'revision']
4530
takes_options = ['revision']
4627
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4532
def run(self, revision_id_list=None, revision=None):
4628
4533
if revision_id_list is not None and revision is not None:
4629
4534
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4630
4535
if revision_id_list is None and revision is None:
4631
4536
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4632
b = WorkingTree.open_containing(directory)[0].branch
4537
b = WorkingTree.open_containing(u'.')[0].branch
4634
4539
self.add_cleanup(b.unlock)
4635
4540
return self._run(b, revision_id_list, revision)
4697
4601
_see_also = ['checkouts', 'unbind']
4698
4602
takes_args = ['location?']
4699
takes_options = ['directory']
4701
def run(self, location=None, directory=u'.'):
4702
b, relpath = Branch.open_containing(directory)
4605
def run(self, location=None):
4606
b, relpath = Branch.open_containing(u'.')
4703
4607
if location is None:
4705
4609
location = b.get_old_bound_location()
4733
4634
_see_also = ['checkouts', 'bind']
4734
4635
takes_args = []
4735
takes_options = ['directory']
4737
def run(self, directory=u'.'):
4738
b, relpath = Branch.open_containing(directory)
4639
b, relpath = Branch.open_containing(u'.')
4739
4640
if not b.unbind():
4740
4641
raise errors.BzrCommandError('Local branch is not bound')
4743
4644
class cmd_uncommit(Command):
4744
__doc__ = """Remove the last committed revision.
4645
"""Remove the last committed revision.
4746
4647
--verbose will print out what is being removed.
4747
4648
--dry-run will go through all the motions, but not actually
4830
4731
end_revision=last_revno)
4833
self.outf.write('Dry-run, pretending to remove'
4834
' the above revisions.\n')
4734
print 'Dry-run, pretending to remove the above revisions.'
4736
val = raw_input('Press <enter> to continue')
4836
self.outf.write('The above revision(s) will be removed.\n')
4839
if not ui.ui_factory.get_boolean('Are you sure'):
4840
self.outf.write('Canceled')
4738
print 'The above revision(s) will be removed.'
4740
val = raw_input('Are you sure [y/N]? ')
4741
if val.lower() not in ('y', 'yes'):
4843
4745
mutter('Uncommitting from {%s} to {%s}',
4844
4746
last_rev_id, rev_id)
4845
4747
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4846
4748
revno=revno, local=local)
4847
self.outf.write('You can restore the old tip by running:\n'
4848
' bzr pull . -r revid:%s\n' % last_rev_id)
4749
note('You can restore the old tip by running:\n'
4750
' bzr pull . -r revid:%s', last_rev_id)
4851
4753
class cmd_break_lock(Command):
4852
__doc__ = """Break a dead lock on a repository, branch or working directory.
4754
"""Break a dead lock on a repository, branch or working directory.
4854
4756
CAUTION: Locks should only be broken when you are sure that the process
4855
4757
holding the lock has been stopped.
5329
5232
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5330
5233
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5332
If no tag name is specified it will be determined through the
5333
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5334
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5338
5236
_see_also = ['commit', 'tags']
5339
takes_args = ['tag_name?']
5237
takes_args = ['tag_name']
5340
5238
takes_options = [
5341
5239
Option('delete',
5342
5240
help='Delete this tag rather than placing it.',
5344
custom_help('directory',
5345
help='Branch in which to place the tag.'),
5243
help='Branch in which to place the tag.',
5346
5247
Option('force',
5347
5248
help='Replace existing tags.',
5352
def run(self, tag_name=None,
5253
def run(self, tag_name,
5815
5712
self.outf.write(" <no hooks installed>\n")
5818
class cmd_remove_branch(Command):
5819
__doc__ = """Remove a branch.
5821
This will remove the branch from the specified location but
5822
will keep any working tree or repository in place.
5826
Remove the branch at repo/trunk::
5828
bzr remove-branch repo/trunk
5832
takes_args = ["location?"]
5834
aliases = ["rmbranch"]
5836
def run(self, location=None):
5837
if location is None:
5839
branch = Branch.open_containing(location)[0]
5840
branch.bzrdir.destroy_branch()
5843
5715
class cmd_shelve(Command):
5844
__doc__ = """Temporarily set aside some changes from the current tree.
5716
"""Temporarily set aside some changes from the current tree.
5846
5718
Shelve allows you to temporarily put changes you've made "on the shelf",
5847
5719
ie. out of the way, until a later time when you can bring them back from
5963
5835
To check what clean-tree will do, use --dry-run.
5965
takes_options = ['directory',
5966
Option('ignored', help='Delete all ignored files.'),
5837
takes_options = [Option('ignored', help='Delete all ignored files.'),
5967
5838
Option('detritus', help='Delete conflict files, merge'
5968
5839
' backups, and failed selftest dirs.'),
5969
5840
Option('unknown',
5972
5843
' deleting them.'),
5973
5844
Option('force', help='Do not prompt before deleting.')]
5974
5845
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5975
force=False, directory=u'.'):
5976
5847
from bzrlib.clean_tree import clean_tree
5977
5848
if not (unknown or ignored or detritus):
5981
clean_tree(directory, unknown=unknown, ignored=ignored,
5982
detritus=detritus, dry_run=dry_run, no_prompt=force)
5852
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5853
dry_run=dry_run, no_prompt=force)
5985
5856
class cmd_reference(Command):
5986
__doc__ = """list, view and set branch locations for nested trees.
5857
"""list, view and set branch locations for nested trees.
5988
5859
If no arguments are provided, lists the branch locations for nested trees.
5989
5860
If one argument is provided, display the branch location for that tree.
6029
5900
self.outf.write('%s %s\n' % (path, location))
6032
def _register_lazy_builtins():
6033
# register lazy builtins from other modules; called at startup and should
6034
# be only called once.
6035
for (name, aliases, module_name) in [
6036
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6037
('cmd_dpush', [], 'bzrlib.foreign'),
6038
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6039
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6040
('cmd_conflicts', [], 'bzrlib.conflicts'),
6041
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6043
builtin_command_registry.register_lazy(name, aliases, module_name)
5903
# these get imported and then picked up by the scan for cmd_*
5904
# TODO: Some more consistent way to split command definitions across files;
5905
# we do need to load at least some information about them to know of
5906
# aliases. ideally we would avoid loading the implementation until the
5907
# details were needed.
5908
from bzrlib.cmd_version_info import cmd_version_info
5909
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5910
from bzrlib.bundle.commands import (
5913
from bzrlib.foreign import cmd_dpush
5914
from bzrlib.sign_my_commits import cmd_sign_my_commits
5915
from bzrlib.weave_commands import cmd_versionedfile_list, \
5916
cmd_weave_plan_merge, cmd_weave_merge_text