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
231
# TODO: Make sure no commands unconditionally use the working directory as a
244
232
# branch. If a filename argument is used, the first of them should be used to
245
233
# specify the branch. (Perhaps this can be factored out into some kind of
350
338
takes_args = ['revision_id?']
351
takes_options = ['directory', 'revision']
339
takes_options = ['revision']
352
340
# cat-revision is more for frontends so should be exact
353
341
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'.'):
344
def run(self, revision_id=None, revision=None):
365
345
if revision_id is not None and revision is not None:
366
346
raise errors.BzrCommandError('You can only supply one of'
367
347
' revision_id or --revision')
368
348
if revision_id is None and revision is None:
369
349
raise errors.BzrCommandError('You must supply either'
370
350
' --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()
351
b = WorkingTree.open_containing(u'.')[0].branch
353
# TODO: jam 20060112 should cat-revision always output utf-8?
354
if revision_id is not None:
355
revision_id = osutils.safe_revision_id(revision_id, warn=False)
357
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
358
except errors.NoSuchRevision:
359
msg = "The repository %s contains no revision %s." % (b.repository.base,
361
raise errors.BzrCommandError(msg)
362
elif revision is not None:
365
raise errors.BzrCommandError('You cannot specify a NULL'
367
rev_id = rev.as_revision_id(b)
368
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
400
371
class cmd_dump_btree(Command):
401
__doc__ = """Dump the contents of a btree index file to stdout.
372
"""Dump the contents of a btree index file to stdout.
403
374
PATH is a btree index file, it can be any URL. This includes things like
404
375
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
468
439
for node in bt.iter_all_entries():
469
440
# Node is made up of:
470
441
# (index, key, value, [references])
474
refs_as_tuples = None
476
refs_as_tuples = static_tuple.as_tuples(refs)
442
refs_as_tuples = static_tuple.as_tuples(node[3])
477
443
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
478
444
self.outf.write('%s\n' % (as_tuple,))
481
447
class cmd_remove_tree(Command):
482
__doc__ = """Remove the working tree from a given branch/checkout.
448
"""Remove the working tree from a given branch/checkout.
484
450
Since a lightweight checkout is little more than a working tree
485
451
this will refuse to run against one.
547
516
revno = ".".join(str(n) for n in revno_t)
549
518
b = Branch.open_containing(location)[0]
550
self.add_cleanup(b.lock_read().unlock)
520
self.add_cleanup(b.unlock)
551
521
revno = b.revno()
552
522
self.cleanup_now()
553
523
self.outf.write(str(revno) + '\n')
556
526
class cmd_revision_info(Command):
557
__doc__ = """Show revision number and revision id for a given revision identifier.
527
"""Show revision number and revision id for a given revision identifier.
560
530
takes_args = ['revision_info*']
561
531
takes_options = [
563
custom_help('directory',
564
534
help='Branch to examine, '
565
'rather than the one containing the working directory.'),
535
'rather than the one containing the working directory.',
566
539
Option('tree', help='Show revno of working tree'),
707
683
def run(self, dir_list):
708
684
for d in dir_list:
709
686
wt, dd = WorkingTree.open_containing(d)
710
base = os.path.dirname(dd)
711
id = wt.path2id(base)
715
self.outf.write('added %s\n' % d)
717
raise errors.NotVersionedError(path=base)
688
self.outf.write('added %s\n' % d)
720
691
class cmd_relpath(Command):
721
__doc__ = """Show path of a file relative to root"""
692
"""Show path of a file relative to root"""
723
694
takes_args = ['filename']
831
804
if len(names_list) < 2:
832
805
raise errors.BzrCommandError("missing file argument")
833
806
tree, rel_names = tree_files(names_list, canonicalize=False)
834
self.add_cleanup(tree.lock_tree_write().unlock)
807
tree.lock_tree_write()
808
self.add_cleanup(tree.unlock)
835
809
self._run(tree, names_list, rel_names, after)
837
811
def run_auto(self, names_list, after, dry_run):
842
816
raise errors.BzrCommandError('--after cannot be specified with'
844
818
work_tree, file_list = tree_files(names_list, default_branch='.')
845
self.add_cleanup(work_tree.lock_tree_write().unlock)
819
work_tree.lock_tree_write()
820
self.add_cleanup(work_tree.unlock)
846
821
rename_map.RenameMap.guess_renames(work_tree, dry_run)
848
823
def _run(self, tree, names_list, rel_names, after):
956
931
takes_options = ['remember', 'overwrite', 'revision',
957
932
custom_help('verbose',
958
933
help='Show logs of pulled revisions.'),
959
custom_help('directory',
960
935
help='Branch to pull into, '
961
'rather than the one containing the working directory.'),
936
'rather than the one containing the working directory.',
963
941
help="Perform a local pull in a bound "
964
942
"branch. Local pulls are not applied to "
1021
997
branch_from = Branch.open(location,
1022
998
possible_transports=possible_transports)
1023
self.add_cleanup(branch_from.lock_read().unlock)
1025
1000
if branch_to.get_parent() is None or remember:
1026
1001
branch_to.set_parent(branch_from.base)
1003
if branch_from is not branch_to:
1004
branch_from.lock_read()
1005
self.add_cleanup(branch_from.unlock)
1028
1006
if revision is not None:
1029
1007
revision_id = revision.as_revision_id(branch_from)
1009
branch_to.lock_write()
1010
self.add_cleanup(branch_to.unlock)
1031
1011
if tree_to is not None:
1032
1012
view_info = _get_view_info_for_change_reporter(tree_to)
1033
1013
change_reporter = delta._ChangeReporter(
1078
1058
Option('create-prefix',
1079
1059
help='Create the path leading up to the branch '
1080
1060
'if it does not already exist.'),
1081
custom_help('directory',
1082
1062
help='Branch to push from, '
1083
'rather than the one containing the working directory.'),
1063
'rather than the one containing the working directory.',
1084
1067
Option('use-existing-dir',
1085
1068
help='By default push will fail if the target'
1086
1069
' directory exists, but does not already'
1112
1095
# Get the source branch
1113
1096
(tree, br_from,
1114
1097
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1099
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1100
if strict is None: strict = True # default value
1115
1101
# Get the tip's revision_id
1116
1102
revision = _get_one_revision('push', revision)
1117
1103
if revision is not None:
1118
1104
revision_id = revision.in_history(br_from).rev_id
1120
1106
revision_id = None
1121
if tree is not None and revision_id is None:
1122
tree.check_changed_or_out_of_date(
1123
strict, 'push_strict',
1124
more_error='Use --no-strict to force the push.',
1125
more_warning='Uncommitted changes will not be pushed.')
1107
if strict and tree is not None and revision_id is None:
1108
if (tree.has_changes()):
1109
raise errors.UncommittedChanges(
1110
tree, more='Use --no-strict to force the push.')
1111
if tree.last_revision() != tree.branch.last_revision():
1112
# The tree has lost sync with its branch, there is little
1113
# chance that the user is aware of it but he can still force
1114
# the push with --no-strict
1115
raise errors.OutOfDateTree(
1116
tree, more='Use --no-strict to force the push.')
1126
1118
# Get the stacked_on branch, if any
1127
1119
if stacked_on is not None:
1128
1120
stacked_on = urlutils.normalize_url(stacked_on)
1399
1394
master = branch.get_master_branch(
1400
1395
possible_transports=possible_transports)
1401
1396
if master is not None:
1402
1398
branch_location = master.base
1400
tree.lock_tree_write()
1405
1401
branch_location = tree.branch.base
1406
tree.lock_tree_write()
1407
1402
self.add_cleanup(tree.unlock)
1408
1403
# get rid of the final '/' and be ready for display
1409
branch_location = urlutils.unescape_for_display(
1410
branch_location.rstrip('/'),
1404
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1412
1406
existing_pending_merges = tree.get_parent_ids()[1:]
1413
1407
if master is None:
1423
1417
revision_id = branch.last_revision()
1424
1418
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1425
revno = branch.revision_id_to_dotted_revno(revision_id)
1426
note("Tree is up to date at revision %s of branch %s" %
1427
('.'.join(map(str, revno)), branch_location))
1419
revno = branch.revision_id_to_revno(revision_id)
1420
note("Tree is up to date at revision %d of branch %s" %
1421
(revno, branch_location))
1429
1423
view_info = _get_view_info_for_change_reporter(tree)
1430
1424
change_reporter = delta._ChangeReporter(
1442
1436
"bzr update --revision only works"
1443
1437
" for a revision in the branch history"
1444
1438
% (e.revision))
1445
revno = tree.branch.revision_id_to_dotted_revno(
1439
revno = tree.branch.revision_id_to_revno(
1446
1440
_mod_revision.ensure_null(tree.last_revision()))
1447
note('Updated to revision %s of branch %s' %
1448
('.'.join(map(str, revno)), branch_location))
1449
parent_ids = tree.get_parent_ids()
1450
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1441
note('Updated to revision %d of branch %s' %
1442
(revno, branch_location))
1443
if tree.get_parent_ids()[1:] != existing_pending_merges:
1451
1444
note('Your local commits will now show as pending merges with '
1452
1445
"'bzr status', and can be committed with 'bzr commit'.")
1453
1446
if conflicts != 0:
1928
1922
help='Use this command to compare files.',
1931
RegistryOption('format',
1932
help='Diff format to use.',
1933
lazy_registry=('bzrlib.diff', 'format_registry'),
1934
value_switches=False, title='Diff format'),
1936
1926
aliases = ['di', 'dif']
1937
1927
encoding_type = 'exact'
1939
1929
@display_command
1940
1930
def run(self, revision=None, file_list=None, diff_options=None,
1941
prefix=None, old=None, new=None, using=None, format=None):
1942
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1931
prefix=None, old=None, new=None, using=None):
1932
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1945
1934
if (prefix is None) or (prefix == '0'):
1946
1935
# diff -p0 format
1960
1949
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1961
1950
' one or two revision specifiers')
1963
if using is not None and format is not None:
1964
raise errors.BzrCommandError('--using and --format are mutually '
1967
1952
(old_tree, new_tree,
1968
1953
old_branch, new_branch,
1969
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1970
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1954
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1955
file_list, revision, old, new, apply_view=True)
1971
1956
return show_diff_trees(old_tree, new_tree, sys.stdout,
1972
1957
specific_files=specific_files,
1973
1958
external_diff_options=diff_options,
1974
1959
old_label=old_label, new_label=new_label,
1975
extra_trees=extra_trees, using=using,
1960
extra_trees=extra_trees, using=using)
1979
1963
class cmd_deleted(Command):
1980
__doc__ = """List files deleted in the working tree.
1964
"""List files deleted in the working tree.
1982
1966
# TODO: Show files deleted since a previous revision, or
1983
1967
# between two revisions.
1986
1970
# level of effort but possibly much less IO. (Or possibly not,
1987
1971
# if the directories are very large...)
1988
1972
_see_also = ['status', 'ls']
1989
takes_options = ['directory', 'show-ids']
1973
takes_options = ['show-ids']
1991
1975
@display_command
1992
def run(self, show_ids=False, directory=u'.'):
1993
tree = WorkingTree.open_containing(directory)[0]
1994
self.add_cleanup(tree.lock_read().unlock)
1976
def run(self, show_ids=False):
1977
tree = WorkingTree.open_containing(u'.')[0]
1979
self.add_cleanup(tree.unlock)
1995
1980
old = tree.basis_tree()
1996
self.add_cleanup(old.lock_read().unlock)
1982
self.add_cleanup(old.unlock)
1997
1983
for path, ie in old.inventory.iter_entries():
1998
1984
if not tree.has_id(ie.file_id):
1999
1985
self.outf.write(path)
2006
1992
class cmd_modified(Command):
2007
__doc__ = """List files modified in working tree.
1993
"""List files modified in working tree.
2011
1997
_see_also = ['status', 'ls']
2012
takes_options = ['directory', 'null']
2000
help='Write an ascii NUL (\\0) separator '
2001
'between files rather than a newline.')
2014
2004
@display_command
2015
def run(self, null=False, directory=u'.'):
2016
tree = WorkingTree.open_containing(directory)[0]
2005
def run(self, null=False):
2006
tree = WorkingTree.open_containing(u'.')[0]
2017
2007
td = tree.changes_from(tree.basis_tree())
2018
2008
for path, id, kind, text_modified, meta_modified in td.modified:
2025
2015
class cmd_added(Command):
2026
__doc__ = """List files added in working tree.
2016
"""List files added in working tree.
2030
2020
_see_also = ['status', 'ls']
2031
takes_options = ['directory', 'null']
2023
help='Write an ascii NUL (\\0) separator '
2024
'between files rather than a newline.')
2033
2027
@display_command
2034
def run(self, null=False, directory=u'.'):
2035
wt = WorkingTree.open_containing(directory)[0]
2036
self.add_cleanup(wt.lock_read().unlock)
2028
def run(self, null=False):
2029
wt = WorkingTree.open_containing(u'.')[0]
2031
self.add_cleanup(wt.unlock)
2037
2032
basis = wt.basis_tree()
2038
self.add_cleanup(basis.lock_read().unlock)
2034
self.add_cleanup(basis.unlock)
2039
2035
basis_inv = basis.inventory
2040
2036
inv = wt.inventory
2041
2037
for file_id in inv:
2250
2246
help='Show just the specified revision.'
2251
2247
' See also "help revisionspec".'),
2253
RegistryOption('authors',
2254
'What names to list as authors - first, all or committer.',
2256
lazy_registry=('bzrlib.log', 'author_list_registry'),
2258
2249
Option('levels',
2259
2250
short_name='n',
2260
2251
help='Number of levels to display - 0 for all, 1 for flat.',
2330
2310
# find the file ids to log and check for directory filtering
2331
2311
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2332
revision, file_list, self.add_cleanup)
2312
revision, file_list)
2313
self.add_cleanup(b.unlock)
2333
2314
for relpath, file_id, kind in file_info_list:
2334
2315
if file_id is None:
2335
2316
raise errors.BzrCommandError(
2405
2386
direction=direction, specific_fileids=file_ids,
2406
2387
start_revision=rev1, end_revision=rev2, limit=limit,
2407
2388
message_search=message, delta_type=delta_type,
2408
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2409
exclude_common_ancestry=exclude_common_ancestry,
2389
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2411
2390
Logger(b, rqst).show(lf)
2432
2411
raise errors.BzrCommandError(
2433
2412
"bzr %s doesn't accept two revisions in different"
2434
2413
" branches." % command_name)
2435
if start_spec.spec is None:
2436
# Avoid loading all the history.
2437
rev1 = RevisionInfo(branch, None, None)
2439
rev1 = start_spec.in_history(branch)
2414
rev1 = start_spec.in_history(branch)
2440
2415
# Avoid loading all of history when we know a missing
2441
2416
# end of range means the last revision ...
2442
2417
if end_spec.spec is None:
2484
2459
tree, relpath = WorkingTree.open_containing(filename)
2485
2460
file_id = tree.path2id(relpath)
2486
2461
b = tree.branch
2487
self.add_cleanup(b.lock_read().unlock)
2463
self.add_cleanup(b.unlock)
2488
2464
touching_revs = log.find_touching_revisions(b, file_id)
2489
2465
for revno, revision_id, what in touching_revs:
2490
2466
self.outf.write("%6d %s\n" % (revno, what))
2493
2469
class cmd_ls(Command):
2494
__doc__ = """List files in a tree.
2470
"""List files in a tree.
2497
2473
_see_also = ['status', 'cat']
2503
2479
help='Recurse into subdirectories.'),
2504
2480
Option('from-root',
2505
2481
help='Print paths relative to the root of the branch.'),
2506
Option('unknown', short_name='u',
2507
help='Print unknown files.'),
2482
Option('unknown', help='Print unknown files.'),
2508
2483
Option('versioned', help='Print versioned files.',
2509
2484
short_name='V'),
2510
Option('ignored', short_name='i',
2511
help='Print ignored files.'),
2512
Option('kind', short_name='k',
2485
Option('ignored', help='Print ignored files.'),
2487
help='Write an ascii NUL (\\0) separator '
2488
'between files rather than a newline.'),
2513
2490
help='List entries of a particular kind: file, directory, symlink.',
2519
2494
@display_command
2520
2495
def run(self, revision=None, verbose=False,
2521
2496
recursive=False, from_root=False,
2522
2497
unknown=False, versioned=False, ignored=False,
2523
null=False, kind=None, show_ids=False, path=None, directory=None):
2498
null=False, kind=None, show_ids=False, path=None):
2525
2500
if kind and kind not in ('file', 'directory', 'symlink'):
2526
2501
raise errors.BzrCommandError('invalid kind specified')
2560
2535
view_str = views.view_display_str(view_files)
2561
2536
note("Ignoring files outside view. View is %s" % view_str)
2563
self.add_cleanup(tree.lock_read().unlock)
2539
self.add_cleanup(tree.unlock)
2564
2540
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2565
2541
from_dir=relpath, recursive=recursive):
2566
2542
# Apply additional masking
2610
2586
class cmd_unknowns(Command):
2611
__doc__ = """List unknown files.
2587
"""List unknown files.
2615
2591
_see_also = ['ls']
2616
takes_options = ['directory']
2618
2593
@display_command
2619
def run(self, directory=u'.'):
2620
for f in WorkingTree.open_containing(directory)[0].unknowns():
2595
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2621
2596
self.outf.write(osutils.quotefn(f) + '\n')
2624
2599
class cmd_ignore(Command):
2625
__doc__ = """Ignore specified files or patterns.
2600
"""Ignore specified files or patterns.
2627
2602
See ``bzr help patterns`` for details on the syntax of patterns.
2637
2612
using this command or directly by using an editor, be sure to commit
2640
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2641
the global ignore file can be found in the application data directory as
2642
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2643
Global ignores are not touched by this command. The global ignore file
2644
can be edited directly using an editor.
2646
2615
Patterns prefixed with '!' are exceptions to ignore patterns and take
2647
2616
precedence over regular ignores. Such exceptions are used to specify
2648
2617
files that should be versioned which would otherwise be ignored.
2689
2658
_see_also = ['status', 'ignored', 'patterns']
2690
2659
takes_args = ['name_pattern*']
2691
takes_options = ['directory',
2692
Option('default-rules',
2693
help='Display the default ignore rules that bzr uses.')
2661
Option('old-default-rules',
2662
help='Write out the ignore rules bzr < 0.9 always used.')
2696
def run(self, name_pattern_list=None, default_rules=None,
2665
def run(self, name_pattern_list=None, old_default_rules=None):
2698
2666
from bzrlib import ignores
2699
if default_rules is not None:
2700
# dump the default rules and exit
2701
for pattern in ignores.USER_DEFAULTS:
2702
self.outf.write("%s\n" % pattern)
2667
if old_default_rules is not None:
2668
# dump the rules and exit
2669
for pattern in ignores.OLD_DEFAULTS:
2704
2672
if not name_pattern_list:
2705
2673
raise errors.BzrCommandError("ignore requires at least one "
2706
"NAME_PATTERN or --default-rules.")
2674
"NAME_PATTERN or --old-default-rules")
2707
2675
name_pattern_list = [globbing.normalize_pattern(p)
2708
2676
for p in name_pattern_list]
2709
2677
for name_pattern in name_pattern_list:
2721
2689
if id is not None:
2722
2690
filename = entry[0]
2723
2691
if ignored.match(filename):
2724
matches.append(filename)
2692
matches.append(filename.encode('utf-8'))
2726
2694
if len(matches) > 0:
2727
self.outf.write("Warning: the following files are version controlled and"
2728
" match your ignore pattern:\n%s"
2729
"\nThese files will continue to be version controlled"
2730
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2695
print "Warning: the following files are version controlled and" \
2696
" match your ignore pattern:\n%s" \
2697
"\nThese files will continue to be version controlled" \
2698
" unless you 'bzr remove' them." % ("\n".join(matches),)
2733
2701
class cmd_ignored(Command):
2734
__doc__ = """List ignored files and the patterns that matched them.
2702
"""List ignored files and the patterns that matched them.
2736
2704
List all the ignored files and the ignore pattern that caused the file to
2744
2712
encoding_type = 'replace'
2745
2713
_see_also = ['ignore', 'ls']
2746
takes_options = ['directory']
2748
2715
@display_command
2749
def run(self, directory=u'.'):
2750
tree = WorkingTree.open_containing(directory)[0]
2751
self.add_cleanup(tree.lock_read().unlock)
2717
tree = WorkingTree.open_containing(u'.')[0]
2719
self.add_cleanup(tree.unlock)
2752
2720
for path, file_class, kind, file_id, entry in tree.list_files():
2753
2721
if file_class != 'I':
2760
2728
class cmd_lookup_revision(Command):
2761
__doc__ = """Lookup the revision-id from a revision-number
2729
"""Lookup the revision-id from a revision-number
2764
2732
bzr lookup-revision 33
2767
2735
takes_args = ['revno']
2768
takes_options = ['directory']
2770
2737
@display_command
2771
def run(self, revno, directory=u'.'):
2738
def run(self, revno):
2773
2740
revno = int(revno)
2774
2741
except ValueError:
2775
raise errors.BzrCommandError("not a valid revision-number: %r"
2777
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2778
self.outf.write("%s\n" % revid)
2742
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2744
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2781
2747
class cmd_export(Command):
2782
__doc__ = """Export current or past revision to a destination directory or archive.
2748
"""Export current or past revision to a destination directory or archive.
2784
2750
If no revision is specified this exports the last committed revision.
2819
2785
help="Name of the root directory inside the exported file."),
2820
Option('per-file-timestamps',
2821
help='Set modification time of files to that of the last '
2822
'revision in which it was changed.'),
2824
2787
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2825
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2788
root=None, filters=False):
2826
2789
from bzrlib.export import export
2828
2791
if branch_or_subdir is None:
2829
tree = WorkingTree.open_containing(directory)[0]
2792
tree = WorkingTree.open_containing(u'.')[0]
2830
2793
b = tree.branch
2836
2799
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2838
export(rev_tree, dest, format, root, subdir, filtered=filters,
2839
per_file_timestamps=per_file_timestamps)
2801
export(rev_tree, dest, format, root, subdir, filtered=filters)
2840
2802
except errors.NoSuchExportFormat, e:
2841
2803
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2844
2806
class cmd_cat(Command):
2845
__doc__ = """Write the contents of a file as of a given revision to standard output.
2807
"""Write the contents of a file as of a given revision to standard output.
2847
2809
If no revision is nominated, the last revision is used.
2863
2825
@display_command
2864
2826
def run(self, filename, revision=None, name_from_revision=False,
2865
filters=False, directory=None):
2866
2828
if revision is not None and len(revision) != 1:
2867
2829
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2868
2830
" one revision specifier")
2869
2831
tree, branch, relpath = \
2870
_open_directory_or_containing_tree_or_branch(filename, directory)
2871
self.add_cleanup(branch.lock_read().unlock)
2832
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2834
self.add_cleanup(branch.unlock)
2872
2835
return self._run(tree, branch, relpath, filename, revision,
2873
2836
name_from_revision, filters)
2928
2892
class cmd_local_time_offset(Command):
2929
__doc__ = """Show the offset in seconds from GMT to local time."""
2893
"""Show the offset in seconds from GMT to local time."""
2931
2895
@display_command
2933
self.outf.write("%s\n" % osutils.local_time_offset())
2897
print osutils.local_time_offset()
2937
2901
class cmd_commit(Command):
2938
__doc__ = """Commit changes into a new revision.
2902
"""Commit changes into a new revision.
2940
2904
An explanatory message needs to be given for each commit. This is
2941
2905
often done by using the --message option (getting the message from the
3135
3099
'(use --file "%(f)s" to take commit message from that file)'
3136
3100
% { 'f': message })
3137
3101
ui.ui_factory.show_warning(warning_msg)
3139
message = message.replace('\r\n', '\n')
3140
message = message.replace('\r', '\n')
3142
raise errors.BzrCommandError(
3143
"please specify either --message or --file")
3145
3103
def get_message(commit_obj):
3146
3104
"""Callback to get commit message"""
3148
f = codecs.open(file, 'rt', osutils.get_user_encoding())
3150
my_message = f.read()
3153
elif message is not None:
3154
my_message = message
3156
# No message supplied: make one up.
3157
# text is the status of the tree
3158
text = make_commit_message_template_encoded(tree,
3105
my_message = message
3106
if my_message is not None and '\r' in my_message:
3107
my_message = my_message.replace('\r\n', '\n')
3108
my_message = my_message.replace('\r', '\n')
3109
if my_message is None and not file:
3110
t = make_commit_message_template_encoded(tree,
3159
3111
selected_list, diff=show_diff,
3160
3112
output_encoding=osutils.get_user_encoding())
3161
# start_message is the template generated from hooks
3162
# XXX: Warning - looks like hooks return unicode,
3163
# make_commit_message_template_encoded returns user encoding.
3164
# We probably want to be using edit_commit_message instead to
3166
3113
start_message = generate_commit_message_template(commit_obj)
3167
my_message = edit_commit_message_encoded(text,
3114
my_message = edit_commit_message_encoded(t,
3168
3115
start_message=start_message)
3169
3116
if my_message is None:
3170
3117
raise errors.BzrCommandError("please specify a commit"
3171
3118
" message with either --message or --file")
3119
elif my_message and file:
3120
raise errors.BzrCommandError(
3121
"please specify either --message or --file")
3123
my_message = codecs.open(file, 'rt',
3124
osutils.get_user_encoding()).read()
3172
3125
if my_message == "":
3173
3126
raise errors.BzrCommandError("empty commit message specified")
3174
3127
return my_message
3196
3151
raise errors.BzrCommandError("Commit refused because there are"
3197
3152
" unknown files in the working tree.")
3198
3153
except errors.BoundBranchOutOfDate, e:
3199
e.extra_help = ("\n"
3200
'To commit to master branch, run update and then commit.\n'
3201
'You can also pass --local to commit to continue working '
3154
raise errors.BzrCommandError(str(e) + "\n"
3155
'To commit to master branch, run update and then commit.\n'
3156
'You can also pass --local to commit to continue working '
3206
3160
class cmd_check(Command):
3207
__doc__ = """Validate working tree structure, branch consistency and repository history.
3161
"""Validate working tree structure, branch consistency and repository history.
3209
3163
This command checks various invariants about branch and repository storage
3210
3164
to detect data corruption or bzr bugs.
3590
3543
raise errors.BzrCommandError("subunit not available. subunit "
3591
3544
"needs to be installed to use --subunit.")
3592
3545
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3593
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3594
# stdout, which would corrupt the subunit stream.
3595
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3596
# following code can be deleted when it's sufficiently deployed
3597
# -- vila/mgz 20100514
3598
if (sys.platform == "win32"
3599
and getattr(sys.stdout, 'fileno', None) is not None):
3601
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3603
3547
self.additional_selftest_args.setdefault(
3604
3548
'suite_decorators', []).append(parallel)
3654
3598
class cmd_rocks(Command):
3655
__doc__ = """Statement of optimism."""
3599
"""Statement of optimism."""
3659
3603
@display_command
3661
self.outf.write("It sure does!\n")
3605
print "It sure does!"
3664
3608
class cmd_find_merge_base(Command):
3665
__doc__ = """Find and print a base revision for merging two branches."""
3609
"""Find and print a base revision for merging two branches."""
3666
3610
# TODO: Options to specify revisions on either side, as if
3667
3611
# merging only part of the history.
3668
3612
takes_args = ['branch', 'other']
3675
3619
branch1 = Branch.open_containing(branch)[0]
3676
3620
branch2 = Branch.open_containing(other)[0]
3677
self.add_cleanup(branch1.lock_read().unlock)
3678
self.add_cleanup(branch2.lock_read().unlock)
3622
self.add_cleanup(branch1.unlock)
3624
self.add_cleanup(branch2.unlock)
3679
3625
last1 = ensure_null(branch1.last_revision())
3680
3626
last2 = ensure_null(branch2.last_revision())
3682
3628
graph = branch1.repository.get_graph(branch2.repository)
3683
3629
base_rev_id = graph.find_unique_lca(last1, last2)
3685
self.outf.write('merge base is revision %s\n' % base_rev_id)
3631
print 'merge base is revision %s' % base_rev_id
3688
3634
class cmd_merge(Command):
3689
__doc__ = """Perform a three-way merge.
3635
"""Perform a three-way merge.
3691
3637
The source of the merge can be specified either in the form of a branch,
3692
3638
or in the form of a path to a file containing a merge directive generated
3775
3721
' completely merged into the source, pull from the'
3776
3722
' source rather than merging. When this happens,'
3777
3723
' you do not need to commit the result.'),
3778
custom_help('directory',
3779
3725
help='Branch to merge into, '
3780
'rather than the one containing the working directory.'),
3726
'rather than the one containing the working directory.',
3781
3730
Option('preview', help='Instead of merging, show a diff of the'
3783
3732
Option('interactive', help='Select changes interactively.',
4075
4025
def run(self, file_list=None, merge_type=None, show_base=False,
4076
4026
reprocess=False):
4077
from bzrlib.conflicts import restore
4078
4027
if merge_type is None:
4079
4028
merge_type = _mod_merge.Merge3Merger
4080
4029
tree, file_list = tree_files(file_list)
4081
self.add_cleanup(tree.lock_write().unlock)
4031
self.add_cleanup(tree.unlock)
4082
4032
parents = tree.get_parent_ids()
4083
4033
if len(parents) != 2:
4084
4034
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4352
4301
remote_branch = Branch.open(other_branch)
4353
4302
if remote_branch.base == local_branch.base:
4354
4303
remote_branch = local_branch
4356
self.add_cleanup(remote_branch.lock_read().unlock)
4305
local_branch.lock_read()
4306
self.add_cleanup(local_branch.unlock)
4358
4307
local_revid_range = _revision_range_to_revid_range(
4359
4308
_get_revision_range(my_revision, local_branch,
4311
remote_branch.lock_read()
4312
self.add_cleanup(remote_branch.unlock)
4362
4313
remote_revid_range = _revision_range_to_revid_range(
4363
4314
_get_revision_range(revision,
4364
4315
remote_branch, self.name()))
4424
4376
class cmd_pack(Command):
4425
__doc__ = """Compress the data within a repository.
4427
This operation compresses the data within a bazaar repository. As
4428
bazaar supports automatic packing of repository, this operation is
4429
normally not required to be done manually.
4431
During the pack operation, bazaar takes a backup of existing repository
4432
data, i.e. pack files. This backup is eventually removed by bazaar
4433
automatically when it is safe to do so. To save disk space by removing
4434
the backed up pack files, the --clean-obsolete-packs option may be
4437
Warning: If you use --clean-obsolete-packs and your machine crashes
4438
during or immediately after repacking, you may be left with a state
4439
where the deletion has been written to disk but the new packs have not
4440
been. In this case the repository may be unusable.
4377
"""Compress the data within a repository."""
4443
4379
_see_also = ['repositories']
4444
4380
takes_args = ['branch_or_repo?']
4446
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4449
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4382
def run(self, branch_or_repo='.'):
4450
4383
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4452
4385
branch = dir.open_branch()
4453
4386
repository = branch.repository
4454
4387
except errors.NotBranchError:
4455
4388
repository = dir.open_repository()
4456
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4459
4392
class cmd_plugins(Command):
4460
__doc__ = """List the installed plugins.
4393
"""List the installed plugins.
4462
4395
This command displays the list of installed plugins including
4463
4396
version of plugin and a short description of each.
4494
4427
doc = '(no description)'
4495
4428
result.append((name_ver, doc, plugin.path()))
4496
4429
for name_ver, doc, path in sorted(result):
4497
self.outf.write("%s\n" % name_ver)
4498
self.outf.write(" %s\n" % doc)
4500
self.outf.write(" %s\n" % path)
4501
self.outf.write("\n")
4504
4437
class cmd_testament(Command):
4505
__doc__ = """Show testament (signing-form) of a revision."""
4438
"""Show testament (signing-form) of a revision."""
4506
4439
takes_options = [
4508
4441
Option('long', help='Produce long-format testament.'),
4550
4484
Option('long', help='Show commit date in annotations.'),
4555
4488
encoding_type = 'exact'
4557
4490
@display_command
4558
4491
def run(self, filename, all=False, long=False, revision=None,
4559
show_ids=False, directory=None):
4560
4493
from bzrlib.annotate import annotate_file, annotate_file_tree
4561
4494
wt, branch, relpath = \
4562
_open_directory_or_containing_tree_or_branch(filename, directory)
4495
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4563
4496
if wt is not None:
4564
self.add_cleanup(wt.lock_read().unlock)
4498
self.add_cleanup(wt.unlock)
4566
self.add_cleanup(branch.lock_read().unlock)
4501
self.add_cleanup(branch.unlock)
4567
4502
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4568
self.add_cleanup(tree.lock_read().unlock)
4504
self.add_cleanup(tree.unlock)
4569
4505
if wt is not None:
4570
4506
file_id = wt.path2id(relpath)
4586
4522
class cmd_re_sign(Command):
4587
__doc__ = """Create a digital signature for an existing revision."""
4523
"""Create a digital signature for an existing revision."""
4588
4524
# TODO be able to replace existing ones.
4590
4526
hidden = True # is this right ?
4591
4527
takes_args = ['revision_id*']
4592
takes_options = ['directory', 'revision']
4528
takes_options = ['revision']
4594
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4530
def run(self, revision_id_list=None, revision=None):
4595
4531
if revision_id_list is not None and revision is not None:
4596
4532
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4597
4533
if revision_id_list is None and revision is None:
4598
4534
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4599
b = WorkingTree.open_containing(directory)[0].branch
4600
self.add_cleanup(b.lock_write().unlock)
4535
b = WorkingTree.open_containing(u'.')[0].branch
4537
self.add_cleanup(b.unlock)
4601
4538
return self._run(b, revision_id_list, revision)
4603
4540
def _run(self, b, revision_id_list, revision):
4663
4599
_see_also = ['checkouts', 'unbind']
4664
4600
takes_args = ['location?']
4665
takes_options = ['directory']
4667
def run(self, location=None, directory=u'.'):
4668
b, relpath = Branch.open_containing(directory)
4603
def run(self, location=None):
4604
b, relpath = Branch.open_containing(u'.')
4669
4605
if location is None:
4671
4607
location = b.get_old_bound_location()
4699
4635
_see_also = ['checkouts', 'bind']
4700
4636
takes_args = []
4701
takes_options = ['directory']
4703
def run(self, directory=u'.'):
4704
b, relpath = Branch.open_containing(directory)
4640
b, relpath = Branch.open_containing(u'.')
4705
4641
if not b.unbind():
4706
4642
raise errors.BzrCommandError('Local branch is not bound')
4709
4645
class cmd_uncommit(Command):
4710
__doc__ = """Remove the last committed revision.
4646
"""Remove the last committed revision.
4712
4648
--verbose will print out what is being removed.
4713
4649
--dry-run will go through all the motions, but not actually
4753
4689
b = control.open_branch()
4755
4691
if tree is not None:
4756
self.add_cleanup(tree.lock_write().unlock)
4693
self.add_cleanup(tree.unlock)
4758
self.add_cleanup(b.lock_write().unlock)
4696
self.add_cleanup(b.unlock)
4759
4697
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4761
4699
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4794
4733
end_revision=last_revno)
4797
self.outf.write('Dry-run, pretending to remove'
4798
' the above revisions.\n')
4736
ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
4800
self.outf.write('The above revision(s) will be removed.\n')
4738
ui.ui_factory.note('The above revision(s) will be removed.')
4803
if not ui.ui_factory.get_boolean('Are you sure'):
4804
self.outf.write('Canceled')
4741
if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4742
ui.ui_factory.note('Canceled')
4807
4745
mutter('Uncommitting from {%s} to {%s}',
4808
4746
last_rev_id, rev_id)
4809
4747
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4810
4748
revno=revno, local=local)
4811
self.outf.write('You can restore the old tip by running:\n'
4812
' bzr pull . -r revid:%s\n' % last_rev_id)
4749
ui.ui_factory.note('You can restore the old tip by running:\n'
4750
' bzr pull . -r revid:%s' % last_rev_id)
4815
4753
class cmd_break_lock(Command):
4816
__doc__ = """Break a dead lock on a repository, branch or working directory.
4754
"""Break a dead lock on a repository, branch or working directory.
4818
4756
CAUTION: Locks should only be broken when you are sure that the process
4819
4757
holding the lock has been stopped.
5293
5232
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5294
5233
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5296
If no tag name is specified it will be determined through the
5297
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5298
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5302
5236
_see_also = ['commit', 'tags']
5303
takes_args = ['tag_name?']
5237
takes_args = ['tag_name']
5304
5238
takes_options = [
5305
5239
Option('delete',
5306
5240
help='Delete this tag rather than placing it.',
5308
custom_help('directory',
5309
help='Branch in which to place the tag.'),
5243
help='Branch in which to place the tag.',
5310
5247
Option('force',
5311
5248
help='Replace existing tags.',
5316
def run(self, tag_name=None,
5253
def run(self, tag_name,
5322
5259
branch, relpath = Branch.open_containing(directory)
5323
self.add_cleanup(branch.lock_write().unlock)
5261
self.add_cleanup(branch.unlock)
5325
if tag_name is None:
5326
raise errors.BzrCommandError("No tag specified to delete.")
5327
5263
branch.tags.delete_tag(tag_name)
5328
5264
self.outf.write('Deleted tag %s.\n' % tag_name)
5777
5712
self.outf.write(" <no hooks installed>\n")
5780
class cmd_remove_branch(Command):
5781
__doc__ = """Remove a branch.
5783
This will remove the branch from the specified location but
5784
will keep any working tree or repository in place.
5788
Remove the branch at repo/trunk::
5790
bzr remove-branch repo/trunk
5794
takes_args = ["location?"]
5796
aliases = ["rmbranch"]
5798
def run(self, location=None):
5799
if location is None:
5801
branch = Branch.open_containing(location)[0]
5802
branch.bzrdir.destroy_branch()
5805
5715
class cmd_shelve(Command):
5806
__doc__ = """Temporarily set aside some changes from the current tree.
5716
"""Temporarily set aside some changes from the current tree.
5808
5718
Shelve allows you to temporarily put changes you've made "on the shelf",
5809
5719
ie. out of the way, until a later time when you can bring them back from
5924
5835
To check what clean-tree will do, use --dry-run.
5926
takes_options = ['directory',
5927
Option('ignored', help='Delete all ignored files.'),
5837
takes_options = [Option('ignored', help='Delete all ignored files.'),
5928
5838
Option('detritus', help='Delete conflict files, merge'
5929
5839
' backups, and failed selftest dirs.'),
5930
5840
Option('unknown',
5933
5843
' deleting them.'),
5934
5844
Option('force', help='Do not prompt before deleting.')]
5935
5845
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5936
force=False, directory=u'.'):
5937
5847
from bzrlib.clean_tree import clean_tree
5938
5848
if not (unknown or ignored or detritus):
5942
clean_tree(directory, unknown=unknown, ignored=ignored,
5943
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)
5946
5856
class cmd_reference(Command):
5947
__doc__ = """list, view and set branch locations for nested trees.
5857
"""list, view and set branch locations for nested trees.
5949
5859
If no arguments are provided, lists the branch locations for nested trees.
5950
5860
If one argument is provided, display the branch location for that tree.
5990
5900
self.outf.write('%s %s\n' % (path, location))
5993
def _register_lazy_builtins():
5994
# register lazy builtins from other modules; called at startup and should
5995
# be only called once.
5996
for (name, aliases, module_name) in [
5997
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
5998
('cmd_dpush', [], 'bzrlib.foreign'),
5999
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6000
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6001
('cmd_conflicts', [], 'bzrlib.conflicts'),
6002
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6004
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