74
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
77
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
80
return internal_tree_files(file_list, default_branch, canonicalize,
81
return internal_tree_files(file_list, default_branch, canonicalize,
83
except errors.FileInWrongBranch, e:
84
raise errors.BzrCommandError("%s is not in the same branch as %s" %
85
(e.path, file_list[0]))
84
88
def tree_files_for_add(file_list):
149
153
# XXX: Bad function name; should possibly also be a class method of
150
154
# WorkingTree rather than a function.
151
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
152
155
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
153
156
apply_view=True):
154
157
"""Convert command-line paths to a WorkingTree and relative paths.
156
Deprecated: use WorkingTree.open_containing_paths instead.
158
159
This is typically used for command-line processors that take one or
159
160
more filenames, and infer the workingtree that contains them.
171
172
:return: workingtree, [relative_paths]
173
return WorkingTree.open_containing_paths(
174
file_list, default_directory='.',
174
if file_list is None or len(file_list) == 0:
175
tree = WorkingTree.open_containing(default_branch)[0]
176
if tree.supports_views() and apply_view:
177
view_files = tree.views.lookup_view()
179
file_list = view_files
180
view_str = views.view_display_str(view_files)
181
note("Ignoring files outside view. View is %s" % view_str)
182
return tree, file_list
183
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
184
return tree, safe_relpath_files(tree, file_list, canonicalize,
185
apply_view=apply_view)
188
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
189
"""Convert file_list into a list of relpaths in tree.
191
:param tree: A tree to operate on.
192
:param file_list: A list of user provided paths or None.
193
:param apply_view: if True and a view is set, apply it or check that
194
specified files are within it
195
:return: A list of relative paths.
196
:raises errors.PathNotChild: When a provided path is in a different tree
199
if file_list is None:
201
if tree.supports_views() and apply_view:
202
view_files = tree.views.lookup_view()
206
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
207
# doesn't - fix that up here before we enter the loop.
209
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
212
for filename in file_list:
214
relpath = fixer(osutils.dereference_path(filename))
215
if view_files and not osutils.is_inside_any(view_files, relpath):
216
raise errors.FileOutsideView(filename, view_files)
217
new_list.append(relpath)
218
except errors.PathNotChild:
219
raise errors.FileInWrongBranch(tree.branch, filename)
179
223
def _get_view_info_for_change_reporter(tree):
191
def _open_directory_or_containing_tree_or_branch(filename, directory):
192
"""Open the tree or branch containing the specified file, unless
193
the --directory option is used to specify a different branch."""
194
if directory is not None:
195
return (None, Branch.open(directory), filename)
196
return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
199
235
# TODO: Make sure no commands unconditionally use the working directory as a
200
236
# branch. If a filename argument is used, the first of them should be used to
201
237
# specify the branch. (Perhaps this can be factored out into some kind of
279
315
raise errors.BzrCommandError('bzr status --revision takes exactly'
280
316
' one or two revision specifiers')
282
tree, relfile_list = WorkingTree.open_containing_paths(file_list)
318
tree, relfile_list = tree_files(file_list)
283
319
# Avoid asking for specific files when that is not needed.
284
320
if relfile_list == ['']:
285
321
relfile_list = None
317
353
self.outf.write(revtext.decode('utf-8'))
320
def run(self, revision_id=None, revision=None, directory=u'.'):
356
def run(self, revision_id=None, revision=None):
321
357
if revision_id is not None and revision is not None:
322
358
raise errors.BzrCommandError('You can only supply one of'
323
359
' revision_id or --revision')
324
360
if revision_id is None and revision is None:
325
361
raise errors.BzrCommandError('You must supply either'
326
362
' --revision or a revision_id')
327
b = WorkingTree.open_containing(directory)[0].branch
363
b = WorkingTree.open_containing(u'.')[0].branch
329
365
revisions = b.repository.revisions
330
366
if revisions is None:
356
392
class cmd_dump_btree(Command):
357
__doc__ = """Dump the contents of a btree index file to stdout.
393
"""Dump the contents of a btree index file to stdout.
359
395
PATH is a btree index file, it can be any URL. This includes things like
360
396
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
468
504
if (working.has_changes()):
469
505
raise errors.UncommittedChanges(working)
470
if working.get_shelf_manager().last_shelf() is not None:
471
raise errors.ShelvedChanges(working)
473
if working.user_url != working.branch.user_url:
507
working_path = working.bzrdir.root_transport.base
508
branch_path = working.branch.bzrdir.root_transport.base
509
if working_path != branch_path:
474
510
raise errors.BzrCommandError("You cannot remove the working tree"
475
511
" from a lightweight checkout")
496
532
wt = WorkingTree.open_containing(location)[0]
497
self.add_cleanup(wt.lock_read().unlock)
498
534
except (errors.NoWorkingTree, errors.NotLocalUrl):
499
535
raise errors.NoWorkingTree(location)
536
self.add_cleanup(wt.unlock)
500
537
revid = wt.last_revision()
502
539
revno_t = wt.branch.revision_id_to_dotted_revno(revid)
505
542
revno = ".".join(str(n) for n in revno_t)
507
544
b = Branch.open_containing(location)[0]
508
self.add_cleanup(b.lock_read().unlock)
546
self.add_cleanup(b.unlock)
509
547
revno = b.revno()
510
548
self.cleanup_now()
511
549
self.outf.write(str(revno) + '\n')
514
552
class cmd_revision_info(Command):
515
__doc__ = """Show revision number and revision id for a given revision identifier.
553
"""Show revision number and revision id for a given revision identifier.
518
556
takes_args = ['revision_info*']
519
557
takes_options = [
521
custom_help('directory',
522
560
help='Branch to examine, '
523
'rather than the one containing the working directory.'),
561
'rather than the one containing the working directory.',
524
565
Option('tree', help='Show revno of working tree'),
532
573
wt = WorkingTree.open_containing(directory)[0]
534
self.add_cleanup(wt.lock_read().unlock)
576
self.add_cleanup(wt.unlock)
535
577
except (errors.NoWorkingTree, errors.NotLocalUrl):
537
579
b = Branch.open_containing(directory)[0]
538
self.add_cleanup(b.lock_read().unlock)
581
self.add_cleanup(b.unlock)
539
582
revision_ids = []
540
583
if revision is not None:
541
584
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
640
683
should_print=(not is_quiet()))
643
self.add_cleanup(base_tree.lock_read().unlock)
686
base_tree.lock_read()
687
self.add_cleanup(base_tree.unlock)
644
688
tree, file_list = tree_files_for_add(file_list)
645
689
added, ignored = tree.smart_add(file_list, not
646
690
no_recurse, action=action, save=not dry_run)
717
761
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
719
763
revision = _get_one_revision('inventory', revision)
720
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
721
self.add_cleanup(work_tree.lock_read().unlock)
764
work_tree, file_list = tree_files(file_list)
765
work_tree.lock_read()
766
self.add_cleanup(work_tree.unlock)
722
767
if revision is not None:
723
768
tree = revision.as_tree(work_tree.branch)
725
770
extra_trees = [work_tree]
726
self.add_cleanup(tree.lock_read().unlock)
772
self.add_cleanup(tree.unlock)
789
835
if len(names_list) < 2:
790
836
raise errors.BzrCommandError("missing file argument")
791
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
792
self.add_cleanup(tree.lock_tree_write().unlock)
837
tree, rel_names = tree_files(names_list, canonicalize=False)
838
tree.lock_tree_write()
839
self.add_cleanup(tree.unlock)
793
840
self._run(tree, names_list, rel_names, after)
795
842
def run_auto(self, names_list, after, dry_run):
800
847
raise errors.BzrCommandError('--after cannot be specified with'
802
work_tree, file_list = WorkingTree.open_containing_paths(
803
names_list, default_directory='.')
804
self.add_cleanup(work_tree.lock_tree_write().unlock)
849
work_tree, file_list = tree_files(names_list, default_branch='.')
850
work_tree.lock_tree_write()
851
self.add_cleanup(work_tree.unlock)
805
852
rename_map.RenameMap.guess_renames(work_tree, dry_run)
807
854
def _run(self, tree, names_list, rel_names, after):
915
962
takes_options = ['remember', 'overwrite', 'revision',
916
963
custom_help('verbose',
917
964
help='Show logs of pulled revisions.'),
918
custom_help('directory',
919
966
help='Branch to pull into, '
920
'rather than the one containing the working directory.'),
967
'rather than the one containing the working directory.',
922
972
help="Perform a local pull in a bound "
923
973
"branch. Local pulls are not applied to "
939
989
tree_to = WorkingTree.open_containing(directory)[0]
940
990
branch_to = tree_to.branch
941
self.add_cleanup(tree_to.lock_write().unlock)
992
self.add_cleanup(tree_to.unlock)
942
993
except errors.NoWorkingTree:
944
995
branch_to = Branch.open_containing(directory)[0]
945
self.add_cleanup(branch_to.lock_write().unlock)
996
branch_to.lock_write()
997
self.add_cleanup(branch_to.unlock)
947
999
if local and not branch_to.get_bound_location():
948
1000
raise errors.LocalRequiresBoundBranch()
980
1032
branch_from = Branch.open(location,
981
1033
possible_transports=possible_transports)
982
self.add_cleanup(branch_from.lock_read().unlock)
1034
branch_from.lock_read()
1035
self.add_cleanup(branch_from.unlock)
984
1037
if branch_to.get_parent() is None or remember:
985
1038
branch_to.set_parent(branch_from.base)
1037
1090
Option('create-prefix',
1038
1091
help='Create the path leading up to the branch '
1039
1092
'if it does not already exist.'),
1040
custom_help('directory',
1041
1094
help='Branch to push from, '
1042
'rather than the one containing the working directory.'),
1095
'rather than the one containing the working directory.',
1043
1099
Option('use-existing-dir',
1044
1100
help='By default push will fail if the target'
1045
1101
' directory exists, but does not already'
1079
1135
revision_id = None
1080
1136
if tree is not None and revision_id is None:
1081
tree.check_changed_or_out_of_date(
1082
strict, 'push_strict',
1083
more_error='Use --no-strict to force the push.',
1084
more_warning='Uncommitted changes will not be pushed.')
1137
tree.warn_if_changed_or_out_of_date(
1138
strict, 'push_strict', 'Use --no-strict to force the push.')
1085
1139
# Get the stacked_on branch, if any
1086
1140
if stacked_on is not None:
1087
1141
stacked_on = urlutils.normalize_url(stacked_on)
1121
1175
class cmd_branch(Command):
1122
__doc__ = """Create a new branch that is a copy of an existing branch.
1176
"""Create a new branch that is a copy of an existing branch.
1124
1178
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1125
1179
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1135
1189
_see_also = ['checkout']
1136
1190
takes_args = ['from_location', 'to_location?']
1137
takes_options = ['revision',
1138
Option('hardlink', help='Hard-link working tree files where possible.'),
1139
Option('files-from', type=str,
1140
help="Get file contents from this tree."),
1191
takes_options = ['revision', Option('hardlink',
1192
help='Hard-link working tree files where possible.'),
1141
1193
Option('no-tree',
1142
1194
help="Create a branch without a working-tree."),
1143
1195
Option('switch',
1162
1214
def run(self, from_location, to_location=None, revision=None,
1163
1215
hardlink=False, stacked=False, standalone=False, no_tree=False,
1164
use_existing_dir=False, switch=False, bind=False,
1216
use_existing_dir=False, switch=False, bind=False):
1166
1217
from bzrlib import switch as _mod_switch
1167
1218
from bzrlib.tag import _merge_tags_if_possible
1168
1219
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1170
if not (hardlink or files_from):
1171
# accelerator_tree is usually slower because you have to read N
1172
# files (no readahead, lots of seeks, etc), but allow the user to
1173
# explicitly request it
1174
accelerator_tree = None
1175
if files_from is not None and files_from != from_location:
1176
accelerator_tree = WorkingTree.open(files_from)
1177
1221
revision = _get_one_revision('branch', revision)
1178
self.add_cleanup(br_from.lock_read().unlock)
1223
self.add_cleanup(br_from.unlock)
1179
1224
if revision is not None:
1180
1225
revision_id = revision.as_revision_id(br_from)
1286
1331
to_location = branch_location
1287
1332
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1288
1333
branch_location)
1289
if not (hardlink or files_from):
1290
# accelerator_tree is usually slower because you have to read N
1291
# files (no readahead, lots of seeks, etc), but allow the user to
1292
# explicitly request it
1293
accelerator_tree = None
1294
1334
revision = _get_one_revision('checkout', revision)
1295
if files_from is not None and files_from != branch_location:
1335
if files_from is not None:
1296
1336
accelerator_tree = WorkingTree.open(files_from)
1297
1337
if revision is not None:
1298
1338
revision_id = revision.as_revision_id(source)
1326
1366
@display_command
1327
1367
def run(self, dir=u'.'):
1328
1368
tree = WorkingTree.open_containing(dir)[0]
1329
self.add_cleanup(tree.lock_read().unlock)
1370
self.add_cleanup(tree.unlock)
1330
1371
new_inv = tree.inventory
1331
1372
old_tree = tree.basis_tree()
1332
self.add_cleanup(old_tree.lock_read().unlock)
1373
old_tree.lock_read()
1374
self.add_cleanup(old_tree.unlock)
1333
1375
old_inv = old_tree.inventory
1335
1377
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1347
1389
class cmd_update(Command):
1348
__doc__ = """Update a tree to have the latest code committed to its branch.
1390
"""Update a tree to have the latest code committed to its branch.
1350
1392
This will perform a merge into the working tree, and may generate
1351
1393
conflicts. If you have any local changes, you will still
1373
1415
master = branch.get_master_branch(
1374
1416
possible_transports=possible_transports)
1375
1417
if master is not None:
1376
1419
branch_location = master.base
1421
tree.lock_tree_write()
1379
1422
branch_location = tree.branch.base
1380
tree.lock_tree_write()
1381
1423
self.add_cleanup(tree.unlock)
1382
1424
# get rid of the final '/' and be ready for display
1383
1425
branch_location = urlutils.unescape_for_display(
1477
1519
class cmd_remove(Command):
1478
__doc__ = """Remove files or directories.
1520
"""Remove files or directories.
1480
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1481
delete them if they can easily be recovered using revert otherwise they
1482
will be backed up (adding an extention of the form .~#~). If no options or
1483
parameters are given Bazaar will scan for files that are being tracked by
1484
Bazaar but missing in your tree and stop tracking them for you.
1522
This makes bzr stop tracking changes to the specified files. bzr will delete
1523
them if they can easily be recovered using revert. If no options or
1524
parameters are given bzr will scan for files that are being tracked by bzr
1525
but missing in your tree and stop tracking them for you.
1486
1527
takes_args = ['file*']
1487
1528
takes_options = ['verbose',
1489
1530
RegistryOption.from_kwargs('file-deletion-strategy',
1490
1531
'The file deletion mode to be used.',
1491
1532
title='Deletion Strategy', value_switches=True, enum_switch=False,
1492
safe='Backup changed files (default).',
1533
safe='Only delete files if they can be'
1534
' safely recovered (default).',
1493
1535
keep='Delete from bzr but leave the working copy.',
1494
1536
force='Delete all the specified files, even if they can not be '
1495
1537
'recovered and even if they are non-empty directories.')]
1499
1541
def run(self, file_list, verbose=False, new=False,
1500
1542
file_deletion_strategy='safe'):
1501
tree, file_list = WorkingTree.open_containing_paths(file_list)
1543
tree, file_list = tree_files(file_list)
1503
1545
if file_list is not None:
1504
1546
file_list = [f for f in file_list]
1506
self.add_cleanup(tree.lock_write().unlock)
1549
self.add_cleanup(tree.unlock)
1507
1550
# Heuristics should probably all move into tree.remove_smart or
1593
1636
_see_also = ['check']
1594
1637
takes_args = ['branch?']
1596
Option('canonicalize-chks',
1597
help='Make sure CHKs are in canonical form (repairs '
1602
def run(self, branch=".", canonicalize_chks=False):
1639
def run(self, branch="."):
1603
1640
from bzrlib.reconcile import reconcile
1604
1641
dir = bzrdir.BzrDir.open(branch)
1605
reconcile(dir, canonicalize_chks=canonicalize_chks)
1608
1645
class cmd_revision_history(Command):
1609
__doc__ = """Display the list of revision ids on a branch."""
1646
"""Display the list of revision ids on a branch."""
1611
1648
_see_also = ['log']
1612
1649
takes_args = ['location?']
1818
1855
class cmd_diff(Command):
1819
__doc__ = """Show differences in the working tree, between revisions or branches.
1856
"""Show differences in the working tree, between revisions or branches.
1821
1858
If no arguments are given, all changes for the current tree are listed.
1822
1859
If files are given, only the changes in those files are listed.
1952
1985
old_branch, new_branch,
1953
1986
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1954
1987
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1955
# GNU diff on Windows uses ANSI encoding for filenames
1956
path_encoding = osutils.get_diff_header_encoding()
1957
1988
return show_diff_trees(old_tree, new_tree, sys.stdout,
1958
1989
specific_files=specific_files,
1959
1990
external_diff_options=diff_options,
1960
1991
old_label=old_label, new_label=new_label,
1961
extra_trees=extra_trees,
1962
path_encoding=path_encoding,
1992
extra_trees=extra_trees, using=using,
1964
1993
format_cls=format)
1967
1996
class cmd_deleted(Command):
1968
__doc__ = """List files deleted in the working tree.
1997
"""List files deleted in the working tree.
1970
1999
# TODO: Show files deleted since a previous revision, or
1971
2000
# between two revisions.
1974
2003
# level of effort but possibly much less IO. (Or possibly not,
1975
2004
# if the directories are very large...)
1976
2005
_see_also = ['status', 'ls']
1977
takes_options = ['directory', 'show-ids']
2006
takes_options = ['show-ids']
1979
2008
@display_command
1980
def run(self, show_ids=False, directory=u'.'):
1981
tree = WorkingTree.open_containing(directory)[0]
1982
self.add_cleanup(tree.lock_read().unlock)
2009
def run(self, show_ids=False):
2010
tree = WorkingTree.open_containing(u'.')[0]
2012
self.add_cleanup(tree.unlock)
1983
2013
old = tree.basis_tree()
1984
self.add_cleanup(old.lock_read().unlock)
2015
self.add_cleanup(old.unlock)
1985
2016
for path, ie in old.inventory.iter_entries():
1986
2017
if not tree.has_id(ie.file_id):
1987
2018
self.outf.write(path)
1994
2025
class cmd_modified(Command):
1995
__doc__ = """List files modified in working tree.
2026
"""List files modified in working tree.
1999
2030
_see_also = ['status', 'ls']
2000
takes_options = ['directory', 'null']
2033
help='Write an ascii NUL (\\0) separator '
2034
'between files rather than a newline.')
2002
2037
@display_command
2003
def run(self, null=False, directory=u'.'):
2004
tree = WorkingTree.open_containing(directory)[0]
2038
def run(self, null=False):
2039
tree = WorkingTree.open_containing(u'.')[0]
2005
2040
td = tree.changes_from(tree.basis_tree())
2006
2041
for path, id, kind, text_modified, meta_modified in td.modified:
2013
2048
class cmd_added(Command):
2014
__doc__ = """List files added in working tree.
2049
"""List files added in working tree.
2018
2053
_see_also = ['status', 'ls']
2019
takes_options = ['directory', 'null']
2056
help='Write an ascii NUL (\\0) separator '
2057
'between files rather than a newline.')
2021
2060
@display_command
2022
def run(self, null=False, directory=u'.'):
2023
wt = WorkingTree.open_containing(directory)[0]
2024
self.add_cleanup(wt.lock_read().unlock)
2061
def run(self, null=False):
2062
wt = WorkingTree.open_containing(u'.')[0]
2064
self.add_cleanup(wt.unlock)
2025
2065
basis = wt.basis_tree()
2026
self.add_cleanup(basis.lock_read().unlock)
2067
self.add_cleanup(basis.unlock)
2027
2068
basis_inv = basis.inventory
2028
2069
inv = wt.inventory
2029
2070
for file_id in inv:
2032
2073
if inv.is_root(file_id) and len(basis_inv) == 0:
2034
2075
path = inv.id2path(file_id)
2035
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2076
if not os.access(osutils.abspath(path), os.F_OK):
2038
2079
self.outf.write(path + '\0')
2238
2279
help='Show just the specified revision.'
2239
2280
' See also "help revisionspec".'),
2241
RegistryOption('authors',
2242
'What names to list as authors - first, all or committer.',
2244
lazy_registry=('bzrlib.log', 'author_list_registry'),
2246
2282
Option('levels',
2247
2283
short_name='n',
2248
2284
help='Number of levels to display - 0 for all, 1 for flat.',
2263
2299
help='Show changes made in each revision as a patch.'),
2264
2300
Option('include-merges',
2265
2301
help='Show merged revisions like --levels 0 does.'),
2266
Option('exclude-common-ancestry',
2267
help='Display only the revisions that are not part'
2268
' of both ancestries (require -rX..Y)'
2271
2303
encoding_type = 'replace'
2284
2316
show_diff=False,
2285
include_merges=False,
2287
exclude_common_ancestry=False,
2317
include_merges=False):
2289
2318
from bzrlib.log import (
2291
2320
make_log_request_dict,
2292
2321
_get_info_for_log_files,
2294
2323
direction = (forward and 'forward') or 'reverse'
2295
if (exclude_common_ancestry
2296
and (revision is None or len(revision) != 2)):
2297
raise errors.BzrCommandError(
2298
'--exclude-common-ancestry requires -r with two revisions')
2299
2324
if include_merges:
2300
2325
if levels is None:
2318
2343
# find the file ids to log and check for directory filtering
2319
2344
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2320
revision, file_list, self.add_cleanup)
2345
revision, file_list)
2346
self.add_cleanup(b.unlock)
2321
2347
for relpath, file_id, kind in file_info_list:
2322
2348
if file_id is None:
2323
2349
raise errors.BzrCommandError(
2342
2368
dir, relpath = bzrdir.BzrDir.open_containing(location)
2343
2369
b = dir.open_branch()
2344
self.add_cleanup(b.lock_read().unlock)
2371
self.add_cleanup(b.unlock)
2345
2372
rev1, rev2 = _get_revision_range(revision, b, self.name())
2347
2374
# Decide on the type of delta & diff filtering to use
2367
2394
show_timezone=timezone,
2368
2395
delta_format=get_verbosity_level(),
2370
show_advice=levels is None,
2371
author_list_handler=authors)
2397
show_advice=levels is None)
2373
2399
# Choose the algorithm for doing the logging. It's annoying
2374
2400
# having multiple code paths like this but necessary until
2393
2419
direction=direction, specific_fileids=file_ids,
2394
2420
start_revision=rev1, end_revision=rev2, limit=limit,
2395
2421
message_search=message, delta_type=delta_type,
2396
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2397
exclude_common_ancestry=exclude_common_ancestry,
2422
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2399
2423
Logger(b, rqst).show(lf)
2472
2496
tree, relpath = WorkingTree.open_containing(filename)
2473
2497
file_id = tree.path2id(relpath)
2474
2498
b = tree.branch
2475
self.add_cleanup(b.lock_read().unlock)
2500
self.add_cleanup(b.unlock)
2476
2501
touching_revs = log.find_touching_revisions(b, file_id)
2477
2502
for revno, revision_id, what in touching_revs:
2478
2503
self.outf.write("%6d %s\n" % (revno, what))
2481
2506
class cmd_ls(Command):
2482
__doc__ = """List files in a tree.
2507
"""List files in a tree.
2485
2510
_see_also = ['status', 'cat']
2491
2516
help='Recurse into subdirectories.'),
2492
2517
Option('from-root',
2493
2518
help='Print paths relative to the root of the branch.'),
2494
Option('unknown', short_name='u',
2495
help='Print unknown files.'),
2519
Option('unknown', help='Print unknown files.'),
2496
2520
Option('versioned', help='Print versioned files.',
2497
2521
short_name='V'),
2498
Option('ignored', short_name='i',
2499
help='Print ignored files.'),
2500
Option('kind', short_name='k',
2522
Option('ignored', help='Print ignored files.'),
2524
help='Write an ascii NUL (\\0) separator '
2525
'between files rather than a newline.'),
2501
2527
help='List entries of a particular kind: file, directory, symlink.',
2507
2531
@display_command
2508
2532
def run(self, revision=None, verbose=False,
2509
2533
recursive=False, from_root=False,
2510
2534
unknown=False, versioned=False, ignored=False,
2511
null=False, kind=None, show_ids=False, path=None, directory=None):
2535
null=False, kind=None, show_ids=False, path=None):
2513
2537
if kind and kind not in ('file', 'directory', 'symlink'):
2514
2538
raise errors.BzrCommandError('invalid kind specified')
2526
2550
raise errors.BzrCommandError('cannot specify both --from-root'
2529
tree, branch, relpath = \
2530
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2553
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2532
2556
# Calculate the prefix to use
2548
2572
view_str = views.view_display_str(view_files)
2549
2573
note("Ignoring files outside view. View is %s" % view_str)
2551
self.add_cleanup(tree.lock_read().unlock)
2576
self.add_cleanup(tree.unlock)
2552
2577
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2553
2578
from_dir=relpath, recursive=recursive):
2554
2579
# Apply additional masking
2598
2623
class cmd_unknowns(Command):
2599
__doc__ = """List unknown files.
2624
"""List unknown files.
2603
2628
_see_also = ['ls']
2604
takes_options = ['directory']
2606
2630
@display_command
2607
def run(self, directory=u'.'):
2608
for f in WorkingTree.open_containing(directory)[0].unknowns():
2632
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2609
2633
self.outf.write(osutils.quotefn(f) + '\n')
2612
2636
class cmd_ignore(Command):
2613
__doc__ = """Ignore specified files or patterns.
2637
"""Ignore specified files or patterns.
2615
2639
See ``bzr help patterns`` for details on the syntax of patterns.
2625
2649
using this command or directly by using an editor, be sure to commit
2628
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2629
the global ignore file can be found in the application data directory as
2630
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2631
Global ignores are not touched by this command. The global ignore file
2632
can be edited directly using an editor.
2634
2652
Patterns prefixed with '!' are exceptions to ignore patterns and take
2635
2653
precedence over regular ignores. Such exceptions are used to specify
2636
2654
files that should be versioned which would otherwise be ignored.
2677
2695
_see_also = ['status', 'ignored', 'patterns']
2678
2696
takes_args = ['name_pattern*']
2679
takes_options = ['directory',
2680
Option('default-rules',
2681
help='Display the default ignore rules that bzr uses.')
2698
Option('old-default-rules',
2699
help='Write out the ignore rules bzr < 0.9 always used.')
2684
def run(self, name_pattern_list=None, default_rules=None,
2702
def run(self, name_pattern_list=None, old_default_rules=None):
2686
2703
from bzrlib import ignores
2687
if default_rules is not None:
2688
# dump the default rules and exit
2689
for pattern in ignores.USER_DEFAULTS:
2704
if old_default_rules is not None:
2705
# dump the rules and exit
2706
for pattern in ignores.OLD_DEFAULTS:
2690
2707
self.outf.write("%s\n" % pattern)
2692
2709
if not name_pattern_list:
2693
2710
raise errors.BzrCommandError("ignore requires at least one "
2694
"NAME_PATTERN or --default-rules.")
2711
"NAME_PATTERN or --old-default-rules")
2695
2712
name_pattern_list = [globbing.normalize_pattern(p)
2696
2713
for p in name_pattern_list]
2698
for p in name_pattern_list:
2699
if not globbing.Globster.is_pattern_valid(p):
2700
bad_patterns += ('\n %s' % p)
2702
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2703
ui.ui_factory.show_error(msg)
2704
raise errors.InvalidPattern('')
2705
2714
for name_pattern in name_pattern_list:
2706
2715
if (name_pattern[0] == '/' or
2707
2716
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2708
2717
raise errors.BzrCommandError(
2709
2718
"NAME_PATTERN should not be an absolute path")
2710
tree, relpath = WorkingTree.open_containing(directory)
2719
tree, relpath = WorkingTree.open_containing(u'.')
2711
2720
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2712
2721
ignored = globbing.Globster(name_pattern_list)
2714
self.add_cleanup(tree.lock_read().unlock)
2715
2724
for entry in tree.list_files():
2717
2726
if id is not None:
2718
2727
filename = entry[0]
2719
2728
if ignored.match(filename):
2720
2729
matches.append(filename)
2721
2731
if len(matches) > 0:
2722
2732
self.outf.write("Warning: the following files are version controlled and"
2723
2733
" match your ignore pattern:\n%s"
2739
2749
encoding_type = 'replace'
2740
2750
_see_also = ['ignore', 'ls']
2741
takes_options = ['directory']
2743
2752
@display_command
2744
def run(self, directory=u'.'):
2745
tree = WorkingTree.open_containing(directory)[0]
2746
self.add_cleanup(tree.lock_read().unlock)
2754
tree = WorkingTree.open_containing(u'.')[0]
2756
self.add_cleanup(tree.unlock)
2747
2757
for path, file_class, kind, file_id, entry in tree.list_files():
2748
2758
if file_class != 'I':
2755
2765
class cmd_lookup_revision(Command):
2756
__doc__ = """Lookup the revision-id from a revision-number
2766
"""Lookup the revision-id from a revision-number
2759
2769
bzr lookup-revision 33
2762
2772
takes_args = ['revno']
2763
takes_options = ['directory']
2765
2774
@display_command
2766
def run(self, revno, directory=u'.'):
2775
def run(self, revno):
2768
2777
revno = int(revno)
2769
2778
except ValueError:
2770
2779
raise errors.BzrCommandError("not a valid revision-number: %r"
2772
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2781
revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2773
2782
self.outf.write("%s\n" % revid)
2776
2785
class cmd_export(Command):
2777
__doc__ = """Export current or past revision to a destination directory or archive.
2786
"""Export current or past revision to a destination directory or archive.
2779
2788
If no revision is specified this exports the last committed revision.
2817
2826
'revision in which it was changed.'),
2819
2828
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2820
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2829
root=None, filters=False, per_file_timestamps=False):
2821
2830
from bzrlib.export import export
2823
2832
if branch_or_subdir is None:
2824
tree = WorkingTree.open_containing(directory)[0]
2833
tree = WorkingTree.open_containing(u'.')[0]
2825
2834
b = tree.branch
2858
2867
@display_command
2859
2868
def run(self, filename, revision=None, name_from_revision=False,
2860
filters=False, directory=None):
2861
2870
if revision is not None and len(revision) != 1:
2862
2871
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2863
2872
" one revision specifier")
2864
2873
tree, branch, relpath = \
2865
_open_directory_or_containing_tree_or_branch(filename, directory)
2866
self.add_cleanup(branch.lock_read().unlock)
2874
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2876
self.add_cleanup(branch.unlock)
2867
2877
return self._run(tree, branch, relpath, filename, revision,
2868
2878
name_from_revision, filters)
3100
3111
properties = {}
3102
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3113
tree, selected_list = tree_files(selected_list)
3103
3114
if selected_list == ['']:
3104
3115
# workaround - commit of root of tree should be exactly the same
3105
3116
# as just default commit in that tree, and succeed even though
3140
3151
def get_message(commit_obj):
3141
3152
"""Callback to get commit message"""
3145
my_message = f.read().decode(osutils.get_user_encoding())
3154
my_message = codecs.open(
3155
file, 'rt', osutils.get_user_encoding()).read()
3148
3156
elif message is not None:
3149
3157
my_message = message
3179
3187
reporter=None, verbose=verbose, revprops=properties,
3180
3188
authors=author, timestamp=commit_stamp,
3181
3189
timezone=offset,
3182
exclude=tree.safe_relpath_files(exclude))
3190
exclude=safe_relpath_files(tree, exclude))
3183
3191
except PointlessCommit:
3184
3192
raise errors.BzrCommandError("No changes to commit."
3185
3193
" Use --unchanged to commit anyhow.")
3201
3209
class cmd_check(Command):
3202
__doc__ = """Validate working tree structure, branch consistency and repository history.
3210
"""Validate working tree structure, branch consistency and repository history.
3204
3212
This command checks various invariants about branch and repository storage
3205
3213
to detect data corruption or bzr bugs.
3305
3313
bzr whoami "Frank Chu <fchu@example.com>"
3307
takes_options = [ 'directory',
3315
takes_options = [ Option('email',
3309
3316
help='Display email address only.'),
3310
3317
Option('branch',
3311
3318
help='Set identity for the current branch instead of '
3315
3322
encoding_type = 'replace'
3317
3324
@display_command
3318
def run(self, email=False, branch=False, name=None, directory=None):
3325
def run(self, email=False, branch=False, name=None):
3319
3326
if name is None:
3320
if directory is None:
3321
# use branch if we're inside one; otherwise global config
3323
c = Branch.open_containing(u'.')[0].get_config()
3324
except errors.NotBranchError:
3325
c = _mod_config.GlobalConfig()
3327
c = Branch.open(directory).get_config()
3327
# use branch if we're inside one; otherwise global config
3329
c = Branch.open_containing('.')[0].get_config()
3330
except errors.NotBranchError:
3331
c = config.GlobalConfig()
3329
3333
self.outf.write(c.user_email() + '\n')
3334
3338
# display a warning if an email address isn't included in the given name.
3336
_mod_config.extract_email_address(name)
3340
config.extract_email_address(name)
3337
3341
except errors.NoEmailInUsername, e:
3338
3342
warning('"%s" does not seem to contain an email address. '
3339
3343
'This is allowed, but not recommended.', name)
3341
3345
# use global config unless --branch given
3343
if directory is None:
3344
c = Branch.open_containing(u'.')[0].get_config()
3346
c = Branch.open(directory).get_config()
3347
c = Branch.open_containing('.')[0].get_config()
3348
c = _mod_config.GlobalConfig()
3349
c = config.GlobalConfig()
3349
3350
c.set_user_option('email', name)
3352
3353
class cmd_nick(Command):
3353
__doc__ = """Print or set the branch nickname.
3354
"""Print or set the branch nickname.
3355
3356
If unset, the tree root directory name is used as the nickname.
3356
3357
To print the current nickname, execute with no argument.
3362
3363
_see_also = ['info']
3363
3364
takes_args = ['nickname?']
3364
takes_options = ['directory']
3365
def run(self, nickname=None, directory=u'.'):
3366
branch = Branch.open_containing(directory)[0]
3365
def run(self, nickname=None):
3366
branch = Branch.open_containing(u'.')[0]
3367
3367
if nickname is None:
3368
3368
self.printme(branch)
3418
3418
'bzr alias --remove expects an alias to remove.')
3419
3419
# If alias is not found, print something like:
3420
3420
# unalias: foo: not found
3421
c = _mod_config.GlobalConfig()
3421
c = config.GlobalConfig()
3422
3422
c.unset_alias(alias_name)
3424
3424
@display_command
3425
3425
def print_aliases(self):
3426
3426
"""Print out the defined aliases in a similar format to bash."""
3427
aliases = _mod_config.GlobalConfig().get_aliases()
3427
aliases = config.GlobalConfig().get_aliases()
3428
3428
for key, value in sorted(aliases.iteritems()):
3429
3429
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3441
3441
def set_alias(self, alias_name, alias_command):
3442
3442
"""Save the alias in the global config."""
3443
c = _mod_config.GlobalConfig()
3443
c = config.GlobalConfig()
3444
3444
c.set_alias(alias_name, alias_command)
3447
3447
class cmd_selftest(Command):
3448
__doc__ = """Run internal test suite.
3448
"""Run internal test suite.
3450
3450
If arguments are given, they are regular expressions that say which tests
3451
3451
should run. Tests matching any expression are run, and other tests are
3519
3519
'throughout the test suite.',
3520
3520
type=get_transport_type),
3521
3521
Option('benchmark',
3522
help='Run the benchmarks rather than selftests.',
3522
help='Run the benchmarks rather than selftests.'),
3524
3523
Option('lsprof-timed',
3525
3524
help='Generate lsprof output for benchmarked'
3526
3525
' sections of code.'),
3527
3526
Option('lsprof-tests',
3528
3527
help='Generate lsprof output for each test.'),
3528
Option('cache-dir', type=str,
3529
help='Cache intermediate benchmark output in this '
3529
3531
Option('first',
3530
3532
help='Run all tests, but run specified tests first.',
3531
3533
short_name='f',
3566
3568
def run(self, testspecs_list=None, verbose=False, one=False,
3567
3569
transport=None, benchmark=None,
3570
lsprof_timed=None, cache_dir=None,
3569
3571
first=False, list_only=False,
3570
3572
randomize=None, exclude=None, strict=False,
3571
3573
load_list=None, debugflag=None, starting_with=None, subunit=False,
3572
3574
parallel=None, lsprof_tests=False):
3573
from bzrlib import tests
3575
from bzrlib.tests import selftest
3576
import bzrlib.benchmarks as benchmarks
3577
from bzrlib.benchmarks import tree_creator
3579
# Make deprecation warnings visible, unless -Werror is set
3580
symbol_versioning.activate_deprecation_warnings(override=False)
3582
if cache_dir is not None:
3583
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3575
3584
if testspecs_list is not None:
3576
3585
pattern = '|'.join(testspecs_list)
3583
3592
raise errors.BzrCommandError("subunit not available. subunit "
3584
3593
"needs to be installed to use --subunit.")
3585
3594
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3586
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3587
# stdout, which would corrupt the subunit stream.
3588
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3589
# following code can be deleted when it's sufficiently deployed
3590
# -- vila/mgz 20100514
3591
if (sys.platform == "win32"
3592
and getattr(sys.stdout, 'fileno', None) is not None):
3594
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3596
3596
self.additional_selftest_args.setdefault(
3597
3597
'suite_decorators', []).append(parallel)
3599
raise errors.BzrCommandError(
3600
"--benchmark is no longer supported from bzr 2.2; "
3601
"use bzr-usertest instead")
3602
test_suite_factory = None
3599
test_suite_factory = benchmarks.test_suite
3600
# Unless user explicitly asks for quiet, be verbose in benchmarks
3601
verbose = not is_quiet()
3602
# TODO: should possibly lock the history file...
3603
benchfile = open(".perf_history", "at", buffering=1)
3604
self.add_cleanup(benchfile.close)
3606
test_suite_factory = None
3603
3608
selftest_kwargs = {"verbose": verbose,
3604
3609
"pattern": pattern,
3605
3610
"stop_on_failure": one,
3607
3612
"test_suite_factory": test_suite_factory,
3608
3613
"lsprof_timed": lsprof_timed,
3609
3614
"lsprof_tests": lsprof_tests,
3615
"bench_history": benchfile,
3610
3616
"matching_tests_first": first,
3611
3617
"list_only": list_only,
3612
3618
"random_seed": randomize,
3617
3623
"starting_with": starting_with
3619
3625
selftest_kwargs.update(self.additional_selftest_args)
3621
# Make deprecation warnings visible, unless -Werror is set
3622
cleanup = symbol_versioning.activate_deprecation_warnings(
3625
result = tests.selftest(**selftest_kwargs)
3626
result = selftest(**selftest_kwargs)
3628
3627
return int(not result)
3631
3630
class cmd_version(Command):
3632
__doc__ = """Show version of bzr."""
3631
"""Show version of bzr."""
3634
3633
encoding_type = 'replace'
3635
3634
takes_options = [
3658
3657
class cmd_find_merge_base(Command):
3659
__doc__ = """Find and print a base revision for merging two branches."""
3658
"""Find and print a base revision for merging two branches."""
3660
3659
# TODO: Options to specify revisions on either side, as if
3661
3660
# merging only part of the history.
3662
3661
takes_args = ['branch', 'other']
3669
3668
branch1 = Branch.open_containing(branch)[0]
3670
3669
branch2 = Branch.open_containing(other)[0]
3671
self.add_cleanup(branch1.lock_read().unlock)
3672
self.add_cleanup(branch2.lock_read().unlock)
3671
self.add_cleanup(branch1.unlock)
3673
self.add_cleanup(branch2.unlock)
3673
3674
last1 = ensure_null(branch1.last_revision())
3674
3675
last2 = ensure_null(branch2.last_revision())
3769
3770
' completely merged into the source, pull from the'
3770
3771
' source rather than merging. When this happens,'
3771
3772
' you do not need to commit the result.'),
3772
custom_help('directory',
3773
3774
help='Branch to merge into, '
3774
'rather than the one containing the working directory.'),
3775
'rather than the one containing the working directory.',
3775
3779
Option('preview', help='Instead of merging, show a diff of the'
3777
3781
Option('interactive', help='Select changes interactively.',
3810
3814
unversioned_filter=tree.is_ignored, view_info=view_info)
3811
3815
pb = ui.ui_factory.nested_progress_bar()
3812
3816
self.add_cleanup(pb.finished)
3813
self.add_cleanup(tree.lock_write().unlock)
3818
self.add_cleanup(tree.unlock)
3814
3819
if location is not None:
3816
3821
mergeable = bundle.read_mergeable_from_url(location,
3877
3882
def _do_preview(self, merger):
3878
3883
from bzrlib.diff import show_diff_trees
3879
3884
result_tree = self._get_preview(merger)
3880
path_encoding = osutils.get_diff_header_encoding()
3881
3885
show_diff_trees(merger.this_tree, result_tree, self.outf,
3882
old_label='', new_label='',
3883
path_encoding=path_encoding)
3886
old_label='', new_label='')
3885
3888
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3886
3889
merger.change_reporter = change_reporter
4073
4076
from bzrlib.conflicts import restore
4074
4077
if merge_type is None:
4075
4078
merge_type = _mod_merge.Merge3Merger
4076
tree, file_list = WorkingTree.open_containing_paths(file_list)
4077
self.add_cleanup(tree.lock_write().unlock)
4079
tree, file_list = tree_files(file_list)
4081
self.add_cleanup(tree.unlock)
4078
4082
parents = tree.get_parent_ids()
4079
4083
if len(parents) != 2:
4080
4084
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4135
4139
class cmd_revert(Command):
4136
__doc__ = """Revert files to a previous revision.
4140
"""Revert files to a previous revision.
4138
4142
Giving a list of files will revert only those files. Otherwise, all files
4139
4143
will be reverted. If the revision is not specified with '--revision', the
4190
4194
def run(self, revision=None, no_backup=False, file_list=None,
4191
4195
forget_merges=None):
4192
tree, file_list = WorkingTree.open_containing_paths(file_list)
4193
self.add_cleanup(tree.lock_tree_write().unlock)
4196
tree, file_list = tree_files(file_list)
4197
tree.lock_tree_write()
4198
self.add_cleanup(tree.unlock)
4194
4199
if forget_merges:
4195
4200
tree.set_parent_ids(tree.get_parent_ids()[:1])
4313
4317
theirs_only=False,
4314
4318
log_format=None, long=False, short=False, line=False,
4315
4319
show_ids=False, verbose=False, this=False, other=False,
4316
include_merges=False, revision=None, my_revision=None,
4320
include_merges=False, revision=None, my_revision=None):
4318
4321
from bzrlib.missing import find_unmerged, iter_log_revisions
4319
4322
def message(s):
4320
4323
if not is_quiet():
4351
4355
if remote_branch.base == local_branch.base:
4352
4356
remote_branch = local_branch
4354
self.add_cleanup(remote_branch.lock_read().unlock)
4358
remote_branch.lock_read()
4359
self.add_cleanup(remote_branch.unlock)
4356
4361
local_revid_range = _revision_range_to_revid_range(
4357
4362
_get_revision_range(my_revision, local_branch,
4412
4417
message("Branches are up to date.\n")
4413
4418
self.cleanup_now()
4414
4419
if not status_code and parent is None and other_branch is not None:
4415
self.add_cleanup(local_branch.lock_write().unlock)
4420
local_branch.lock_write()
4421
self.add_cleanup(local_branch.unlock)
4416
4422
# handle race conditions - a parent might be set while we run.
4417
4423
if local_branch.get_parent() is None:
4418
4424
local_branch.set_parent(remote_branch.base)
4422
4428
class cmd_pack(Command):
4423
__doc__ = """Compress the data within a repository.
4425
This operation compresses the data within a bazaar repository. As
4426
bazaar supports automatic packing of repository, this operation is
4427
normally not required to be done manually.
4429
During the pack operation, bazaar takes a backup of existing repository
4430
data, i.e. pack files. This backup is eventually removed by bazaar
4431
automatically when it is safe to do so. To save disk space by removing
4432
the backed up pack files, the --clean-obsolete-packs option may be
4435
Warning: If you use --clean-obsolete-packs and your machine crashes
4436
during or immediately after repacking, you may be left with a state
4437
where the deletion has been written to disk but the new packs have not
4438
been. In this case the repository may be unusable.
4429
"""Compress the data within a repository."""
4441
4431
_see_also = ['repositories']
4442
4432
takes_args = ['branch_or_repo?']
4444
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4447
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4434
def run(self, branch_or_repo='.'):
4448
4435
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4450
4437
branch = dir.open_branch()
4451
4438
repository = branch.repository
4452
4439
except errors.NotBranchError:
4453
4440
repository = dir.open_repository()
4454
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4457
4444
class cmd_plugins(Command):
4458
__doc__ = """List the installed plugins.
4445
"""List the installed plugins.
4460
4447
This command displays the list of installed plugins including
4461
4448
version of plugin and a short description of each.
4548
4536
Option('long', help='Show commit date in annotations.'),
4553
4540
encoding_type = 'exact'
4555
4542
@display_command
4556
4543
def run(self, filename, all=False, long=False, revision=None,
4557
show_ids=False, directory=None):
4558
4545
from bzrlib.annotate import annotate_file, annotate_file_tree
4559
4546
wt, branch, relpath = \
4560
_open_directory_or_containing_tree_or_branch(filename, directory)
4547
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4561
4548
if wt is not None:
4562
self.add_cleanup(wt.lock_read().unlock)
4550
self.add_cleanup(wt.unlock)
4564
self.add_cleanup(branch.lock_read().unlock)
4553
self.add_cleanup(branch.unlock)
4565
4554
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4566
self.add_cleanup(tree.lock_read().unlock)
4556
self.add_cleanup(tree.unlock)
4567
4557
if wt is not None:
4568
4558
file_id = wt.path2id(relpath)
4584
4574
class cmd_re_sign(Command):
4585
__doc__ = """Create a digital signature for an existing revision."""
4575
"""Create a digital signature for an existing revision."""
4586
4576
# TODO be able to replace existing ones.
4588
4578
hidden = True # is this right ?
4589
4579
takes_args = ['revision_id*']
4590
takes_options = ['directory', 'revision']
4580
takes_options = ['revision']
4592
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4582
def run(self, revision_id_list=None, revision=None):
4593
4583
if revision_id_list is not None and revision is not None:
4594
4584
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4595
4585
if revision_id_list is None and revision is None:
4596
4586
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4597
b = WorkingTree.open_containing(directory)[0].branch
4598
self.add_cleanup(b.lock_write().unlock)
4587
b = WorkingTree.open_containing(u'.')[0].branch
4589
self.add_cleanup(b.unlock)
4599
4590
return self._run(b, revision_id_list, revision)
4601
4592
def _run(self, b, revision_id_list, revision):
4649
4640
class cmd_bind(Command):
4650
__doc__ = """Convert the current branch into a checkout of the supplied branch.
4651
If no branch is supplied, rebind to the last bound location.
4641
"""Convert the current branch into a checkout of the supplied branch.
4653
4643
Once converted into a checkout, commits must succeed on the master branch
4654
4644
before they will be applied to the local branch.
4661
4651
_see_also = ['checkouts', 'unbind']
4662
4652
takes_args = ['location?']
4663
takes_options = ['directory']
4665
def run(self, location=None, directory=u'.'):
4666
b, relpath = Branch.open_containing(directory)
4655
def run(self, location=None):
4656
b, relpath = Branch.open_containing(u'.')
4667
4657
if location is None:
4669
4659
location = b.get_old_bound_location()
4697
4687
_see_also = ['checkouts', 'bind']
4698
4688
takes_args = []
4699
takes_options = ['directory']
4701
def run(self, directory=u'.'):
4702
b, relpath = Branch.open_containing(directory)
4692
b, relpath = Branch.open_containing(u'.')
4703
4693
if not b.unbind():
4704
4694
raise errors.BzrCommandError('Local branch is not bound')
4707
4697
class cmd_uncommit(Command):
4708
__doc__ = """Remove the last committed revision.
4698
"""Remove the last committed revision.
4710
4700
--verbose will print out what is being removed.
4711
4701
--dry-run will go through all the motions, but not actually
4751
4741
b = control.open_branch()
4753
4743
if tree is not None:
4754
self.add_cleanup(tree.lock_write().unlock)
4745
self.add_cleanup(tree.unlock)
4756
self.add_cleanup(b.lock_write().unlock)
4748
self.add_cleanup(b.unlock)
4757
4749
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4759
4751
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4813
4805
class cmd_break_lock(Command):
4814
__doc__ = """Break a dead lock.
4816
This command breaks a lock on a repository, branch, working directory or
4806
"""Break a dead lock on a repository, branch or working directory.
4819
4808
CAUTION: Locks should only be broken when you are sure that the process
4820
4809
holding the lock has been stopped.
4827
4816
bzr break-lock bzr+ssh://example.com/bzr/foo
4828
bzr break-lock --conf ~/.bazaar
4831
4818
takes_args = ['location?']
4834
help='LOCATION is the directory where the config lock is.'),
4837
def run(self, location=None, config=False):
4820
def run(self, location=None, show=False):
4838
4821
if location is None:
4839
4822
location = u'.'
4841
conf = _mod_config.LockableConfig(file_name=location)
4844
control, relpath = bzrdir.BzrDir.open_containing(location)
4846
control.break_lock()
4847
except NotImplementedError:
4823
control, relpath = bzrdir.BzrDir.open_containing(location)
4825
control.break_lock()
4826
except NotImplementedError:
4851
4830
class cmd_wait_until_signalled(Command):
4852
__doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4831
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4854
4833
This just prints a line to signal when it is ready, then blocks on stdin.
4880
4859
'result in a dynamically allocated port. The default port '
4881
4860
'depends on the protocol.',
4883
custom_help('directory',
4884
help='Serve contents of this directory.'),
4863
help='Serve contents of this directory.',
4885
4865
Option('allow-writes',
4886
4866
help='By default the server is a readonly server. Supplying '
4887
4867
'--allow-writes enables write access to the contents of '
4915
4895
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4916
4896
protocol=None):
4917
from bzrlib import transport
4897
from bzrlib.transport import get_transport, transport_server_registry
4918
4898
if directory is None:
4919
4899
directory = os.getcwd()
4920
4900
if protocol is None:
4921
protocol = transport.transport_server_registry.get()
4901
protocol = transport_server_registry.get()
4922
4902
host, port = self.get_host_and_port(port)
4923
4903
url = urlutils.local_path_to_url(directory)
4924
4904
if not allow_writes:
4925
4905
url = 'readonly+' + url
4926
t = transport.get_transport(url)
4927
protocol(t, host, port, inet)
4906
transport = get_transport(url)
4907
protocol(transport, host, port, inet)
4930
4910
class cmd_join(Command):
4931
__doc__ = """Combine a tree into its containing tree.
4911
"""Combine a tree into its containing tree.
4933
4913
This command requires the target tree to be in a rich-root format.
5042
5021
encoding_type = 'exact'
5044
5023
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5045
sign=False, revision=None, mail_to=None, message=None,
5024
sign=False, revision=None, mail_to=None, message=None):
5047
5025
from bzrlib.revision import ensure_null, NULL_REVISION
5048
5026
include_patch, include_bundle = {
5049
5027
'plain': (False, False),
5050
5028
'diff': (True, False),
5051
5029
'bundle': (True, True),
5053
branch = Branch.open(directory)
5031
branch = Branch.open('.')
5054
5032
stored_submit_branch = branch.get_submit_branch()
5055
5033
if submit_branch is None:
5056
5034
submit_branch = stored_submit_branch
5141
5119
given, in which case it is sent to a file.
5143
5121
Mail is sent using your preferred mail program. This should be transparent
5144
on Windows (it uses MAPI). On Unix, it requires the xdg-email utility.
5122
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5145
5123
If the preferred client can't be found (or used), your editor will be used.
5147
5125
To use a specific mail program, set the mail_client configuration option.
5362
5344
class cmd_tags(Command):
5363
__doc__ = """List tags.
5365
5347
This command shows a table of tag names and the revisions they reference.
5368
5350
_see_also = ['tag']
5369
5351
takes_options = [
5370
custom_help('directory',
5371
help='Branch whose tags should be displayed.'),
5353
help='Branch whose tags should be displayed.',
5372
5357
RegistryOption.from_kwargs('sort',
5373
5358
'Sort tags by different criteria.', title='Sorting',
5374
5359
alpha='Sort tags lexicographically (default).',
5523
5509
class cmd_switch(Command):
5524
__doc__ = """Set the branch of a checkout and update.
5510
"""Set the branch of a checkout and update.
5526
5512
For lightweight checkouts, this changes the branch being referenced.
5527
5513
For heavyweight checkouts, this checks that there are no local commits
5546
5532
takes_args = ['to_location?']
5547
takes_options = ['directory',
5533
takes_options = [Option('force',
5549
5534
help='Switch even if local commits will be lost.'),
5551
5536
Option('create-branch', short_name='b',
5556
5541
def run(self, to_location=None, force=False, create_branch=False,
5557
revision=None, directory=u'.'):
5558
5543
from bzrlib import switch
5559
tree_location = directory
5560
5545
revision = _get_one_revision('switch', revision)
5561
5546
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5562
5547
if to_location is None:
5563
5548
if revision is None:
5564
5549
raise errors.BzrCommandError('You must supply either a'
5565
5550
' revision or a location')
5566
to_location = tree_location
5568
5553
branch = control_dir.open_branch()
5569
5554
had_explicit_nick = branch.get_config().has_explicit_nickname()
5820
5804
class cmd_shelve(Command):
5821
__doc__ = """Temporarily set aside some changes from the current tree.
5805
"""Temporarily set aside some changes from the current tree.
5823
5807
Shelve allows you to temporarily put changes you've made "on the shelf",
5824
5808
ie. out of the way, until a later time when you can bring them back from
5860
5843
_see_also = ['unshelve']
5862
5845
def run(self, revision=None, all=False, file_list=None, message=None,
5863
writer=None, list=False, destroy=False, directory=u'.'):
5846
writer=None, list=False, destroy=False):
5865
5848
return self.run_for_list()
5866
5849
from bzrlib.shelf_ui import Shelver
5868
5851
writer = bzrlib.option.diff_writer_registry.get()
5870
5853
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5871
file_list, message, destroy=destroy, directory=directory)
5854
file_list, message, destroy=destroy)
5917
5900
_see_also = ['shelve']
5919
def run(self, shelf_id=None, action='apply', directory=u'.'):
5902
def run(self, shelf_id=None, action='apply'):
5920
5903
from bzrlib.shelf_ui import Unshelver
5921
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5904
unshelver = Unshelver.from_args(shelf_id, action)
5923
5906
unshelver.run()
5941
5924
To check what clean-tree will do, use --dry-run.
5943
takes_options = ['directory',
5944
Option('ignored', help='Delete all ignored files.'),
5926
takes_options = [Option('ignored', help='Delete all ignored files.'),
5945
5927
Option('detritus', help='Delete conflict files, merge'
5946
5928
' backups, and failed selftest dirs.'),
5947
5929
Option('unknown',
5950
5932
' deleting them.'),
5951
5933
Option('force', help='Do not prompt before deleting.')]
5952
5934
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5953
force=False, directory=u'.'):
5954
5936
from bzrlib.clean_tree import clean_tree
5955
5937
if not (unknown or ignored or detritus):
5959
clean_tree(directory, unknown=unknown, ignored=ignored,
5960
detritus=detritus, dry_run=dry_run, no_prompt=force)
5941
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5942
dry_run=dry_run, no_prompt=force)
5963
5945
class cmd_reference(Command):
5964
__doc__ = """list, view and set branch locations for nested trees.
5946
"""list, view and set branch locations for nested trees.
5966
5948
If no arguments are provided, lists the branch locations for nested trees.
5967
5949
If one argument is provided, display the branch location for that tree.