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)
942
991
except errors.NoWorkingTree:
944
993
branch_to = Branch.open_containing(directory)[0]
945
self.add_cleanup(branch_to.lock_write().unlock)
947
995
if local and not branch_to.get_bound_location():
948
996
raise errors.LocalRequiresBoundBranch()
980
1028
branch_from = Branch.open(location,
981
1029
possible_transports=possible_transports)
982
self.add_cleanup(branch_from.lock_read().unlock)
984
1031
if branch_to.get_parent() is None or remember:
985
1032
branch_to.set_parent(branch_from.base)
1034
if branch_from is not branch_to:
1035
branch_from.lock_read()
1036
self.add_cleanup(branch_from.unlock)
987
1037
if revision is not None:
988
1038
revision_id = revision.as_revision_id(branch_from)
1040
branch_to.lock_write()
1041
self.add_cleanup(branch_to.unlock)
990
1042
if tree_to is not None:
991
1043
view_info = _get_view_info_for_change_reporter(tree_to)
992
1044
change_reporter = delta._ChangeReporter(
1037
1089
Option('create-prefix',
1038
1090
help='Create the path leading up to the branch '
1039
1091
'if it does not already exist.'),
1040
custom_help('directory',
1041
1093
help='Branch to push from, '
1042
'rather than the one containing the working directory.'),
1094
'rather than the one containing the working directory.',
1043
1098
Option('use-existing-dir',
1044
1099
help='By default push will fail if the target'
1045
1100
' directory exists, but does not already'
1071
1126
# Get the source branch
1072
1127
(tree, br_from,
1073
1128
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1130
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1131
if strict is None: strict = True # default value
1074
1132
# Get the tip's revision_id
1075
1133
revision = _get_one_revision('push', revision)
1076
1134
if revision is not None:
1077
1135
revision_id = revision.in_history(br_from).rev_id
1079
1137
revision_id = None
1080
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.')
1138
if strict and tree is not None and revision_id is None:
1139
if (tree.has_changes()):
1140
raise errors.UncommittedChanges(
1141
tree, more='Use --no-strict to force the push.')
1142
if tree.last_revision() != tree.branch.last_revision():
1143
# The tree has lost sync with its branch, there is little
1144
# chance that the user is aware of it but he can still force
1145
# the push with --no-strict
1146
raise errors.OutOfDateTree(
1147
tree, more='Use --no-strict to force the push.')
1085
1149
# Get the stacked_on branch, if any
1086
1150
if stacked_on is not None:
1087
1151
stacked_on = urlutils.normalize_url(stacked_on)
1121
1185
class cmd_branch(Command):
1122
__doc__ = """Create a new branch that is a copy of an existing branch.
1186
"""Create a new branch that is a copy of an existing branch.
1124
1188
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1125
1189
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1135
1199
_see_also = ['checkout']
1136
1200
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."),
1201
takes_options = ['revision', Option('hardlink',
1202
help='Hard-link working tree files where possible.'),
1141
1203
Option('no-tree',
1142
1204
help="Create a branch without a working-tree."),
1143
1205
Option('switch',
1162
1224
def run(self, from_location, to_location=None, revision=None,
1163
1225
hardlink=False, stacked=False, standalone=False, no_tree=False,
1164
use_existing_dir=False, switch=False, bind=False,
1226
use_existing_dir=False, switch=False, bind=False):
1166
1227
from bzrlib import switch as _mod_switch
1167
1228
from bzrlib.tag import _merge_tags_if_possible
1168
1229
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
1231
revision = _get_one_revision('branch', revision)
1178
self.add_cleanup(br_from.lock_read().unlock)
1233
self.add_cleanup(br_from.unlock)
1179
1234
if revision is not None:
1180
1235
revision_id = revision.as_revision_id(br_from)
1286
1341
to_location = branch_location
1287
1342
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1288
1343
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
1344
revision = _get_one_revision('checkout', revision)
1295
if files_from is not None and files_from != branch_location:
1345
if files_from is not None:
1296
1346
accelerator_tree = WorkingTree.open(files_from)
1297
1347
if revision is not None:
1298
1348
revision_id = revision.as_revision_id(source)
1326
1376
@display_command
1327
1377
def run(self, dir=u'.'):
1328
1378
tree = WorkingTree.open_containing(dir)[0]
1329
self.add_cleanup(tree.lock_read().unlock)
1380
self.add_cleanup(tree.unlock)
1330
1381
new_inv = tree.inventory
1331
1382
old_tree = tree.basis_tree()
1332
self.add_cleanup(old_tree.lock_read().unlock)
1383
old_tree.lock_read()
1384
self.add_cleanup(old_tree.unlock)
1333
1385
old_inv = old_tree.inventory
1335
1387
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1347
1399
class cmd_update(Command):
1348
__doc__ = """Update a tree to have the latest code committed to its branch.
1400
"""Update a tree to have the latest code committed to its branch.
1350
1402
This will perform a merge into the working tree, and may generate
1351
1403
conflicts. If you have any local changes, you will still
1373
1425
master = branch.get_master_branch(
1374
1426
possible_transports=possible_transports)
1375
1427
if master is not None:
1376
1429
branch_location = master.base
1431
tree.lock_tree_write()
1379
1432
branch_location = tree.branch.base
1380
tree.lock_tree_write()
1381
1433
self.add_cleanup(tree.unlock)
1382
1434
# get rid of the final '/' and be ready for display
1383
1435
branch_location = urlutils.unescape_for_display(
1420
1472
_mod_revision.ensure_null(tree.last_revision()))
1421
1473
note('Updated to revision %s of branch %s' %
1422
1474
('.'.join(map(str, revno)), branch_location))
1423
parent_ids = tree.get_parent_ids()
1424
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1475
if tree.get_parent_ids()[1:] != existing_pending_merges:
1425
1476
note('Your local commits will now show as pending merges with '
1426
1477
"'bzr status', and can be committed with 'bzr commit'.")
1427
1478
if conflicts != 0:
1477
1528
class cmd_remove(Command):
1478
__doc__ = """Remove files or directories.
1529
"""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.
1531
This makes bzr stop tracking changes to the specified files. bzr will delete
1532
them if they can easily be recovered using revert. If no options or
1533
parameters are given bzr will scan for files that are being tracked by bzr
1534
but missing in your tree and stop tracking them for you.
1486
1536
takes_args = ['file*']
1487
1537
takes_options = ['verbose',
1489
1539
RegistryOption.from_kwargs('file-deletion-strategy',
1490
1540
'The file deletion mode to be used.',
1491
1541
title='Deletion Strategy', value_switches=True, enum_switch=False,
1492
safe='Backup changed files (default).',
1542
safe='Only delete files if they can be'
1543
' safely recovered (default).',
1493
1544
keep='Delete from bzr but leave the working copy.',
1494
1545
force='Delete all the specified files, even if they can not be '
1495
1546
'recovered and even if they are non-empty directories.')]
1499
1550
def run(self, file_list, verbose=False, new=False,
1500
1551
file_deletion_strategy='safe'):
1501
tree, file_list = WorkingTree.open_containing_paths(file_list)
1552
tree, file_list = tree_files(file_list)
1503
1554
if file_list is not None:
1504
1555
file_list = [f for f in file_list]
1506
self.add_cleanup(tree.lock_write().unlock)
1558
self.add_cleanup(tree.unlock)
1507
1559
# Heuristics should probably all move into tree.remove_smart or
1593
1645
_see_also = ['check']
1594
1646
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):
1648
def run(self, branch="."):
1603
1649
from bzrlib.reconcile import reconcile
1604
1650
dir = bzrdir.BzrDir.open(branch)
1605
reconcile(dir, canonicalize_chks=canonicalize_chks)
1608
1654
class cmd_revision_history(Command):
1609
__doc__ = """Display the list of revision ids on a branch."""
1655
"""Display the list of revision ids on a branch."""
1611
1657
_see_also = ['log']
1612
1658
takes_args = ['location?']
1818
1864
class cmd_diff(Command):
1819
__doc__ = """Show differences in the working tree, between revisions or branches.
1865
"""Show differences in the working tree, between revisions or branches.
1821
1867
If no arguments are given, all changes for the current tree are listed.
1822
1868
If files are given, only the changes in those files are listed.
1923
1965
@display_command
1924
1966
def run(self, revision=None, file_list=None, diff_options=None,
1925
1967
prefix=None, old=None, new=None, using=None, format=None):
1926
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1968
from bzrlib.diff import (get_trees_and_branches_to_diff,
1927
1969
show_diff_trees)
1929
1971
if (prefix is None) or (prefix == '0'):
1951
1993
(old_tree, new_tree,
1952
1994
old_branch, new_branch,
1953
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1954
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()
1995
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1996
file_list, revision, old, new, apply_view=True)
1957
1997
return show_diff_trees(old_tree, new_tree, sys.stdout,
1958
1998
specific_files=specific_files,
1959
1999
external_diff_options=diff_options,
1960
2000
old_label=old_label, new_label=new_label,
1961
extra_trees=extra_trees,
1962
path_encoding=path_encoding,
2001
extra_trees=extra_trees, using=using,
1964
2002
format_cls=format)
1967
2005
class cmd_deleted(Command):
1968
__doc__ = """List files deleted in the working tree.
2006
"""List files deleted in the working tree.
1970
2008
# TODO: Show files deleted since a previous revision, or
1971
2009
# between two revisions.
1974
2012
# level of effort but possibly much less IO. (Or possibly not,
1975
2013
# if the directories are very large...)
1976
2014
_see_also = ['status', 'ls']
1977
takes_options = ['directory', 'show-ids']
2015
takes_options = ['show-ids']
1979
2017
@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)
2018
def run(self, show_ids=False):
2019
tree = WorkingTree.open_containing(u'.')[0]
2021
self.add_cleanup(tree.unlock)
1983
2022
old = tree.basis_tree()
1984
self.add_cleanup(old.lock_read().unlock)
2024
self.add_cleanup(old.unlock)
1985
2025
for path, ie in old.inventory.iter_entries():
1986
2026
if not tree.has_id(ie.file_id):
1987
2027
self.outf.write(path)
1994
2034
class cmd_modified(Command):
1995
__doc__ = """List files modified in working tree.
2035
"""List files modified in working tree.
1999
2039
_see_also = ['status', 'ls']
2000
takes_options = ['directory', 'null']
2042
help='Write an ascii NUL (\\0) separator '
2043
'between files rather than a newline.')
2002
2046
@display_command
2003
def run(self, null=False, directory=u'.'):
2004
tree = WorkingTree.open_containing(directory)[0]
2047
def run(self, null=False):
2048
tree = WorkingTree.open_containing(u'.')[0]
2005
2049
td = tree.changes_from(tree.basis_tree())
2006
2050
for path, id, kind, text_modified, meta_modified in td.modified:
2013
2057
class cmd_added(Command):
2014
__doc__ = """List files added in working tree.
2058
"""List files added in working tree.
2018
2062
_see_also = ['status', 'ls']
2019
takes_options = ['directory', 'null']
2065
help='Write an ascii NUL (\\0) separator '
2066
'between files rather than a newline.')
2021
2069
@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)
2070
def run(self, null=False):
2071
wt = WorkingTree.open_containing(u'.')[0]
2073
self.add_cleanup(wt.unlock)
2025
2074
basis = wt.basis_tree()
2026
self.add_cleanup(basis.lock_read().unlock)
2076
self.add_cleanup(basis.unlock)
2027
2077
basis_inv = basis.inventory
2028
2078
inv = wt.inventory
2029
2079
for file_id in inv:
2032
2082
if inv.is_root(file_id) and len(basis_inv) == 0:
2034
2084
path = inv.id2path(file_id)
2035
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2085
if not os.access(osutils.abspath(path), os.F_OK):
2038
2088
self.outf.write(path + '\0')
2238
2288
help='Show just the specified revision.'
2239
2289
' 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
2291
Option('levels',
2247
2292
short_name='n',
2248
2293
help='Number of levels to display - 0 for all, 1 for flat.',
2263
2308
help='Show changes made in each revision as a patch.'),
2264
2309
Option('include-merges',
2265
2310
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
2312
encoding_type = 'replace'
2284
2325
show_diff=False,
2285
include_merges=False,
2287
exclude_common_ancestry=False,
2326
include_merges=False):
2289
2327
from bzrlib.log import (
2291
2329
make_log_request_dict,
2292
2330
_get_info_for_log_files,
2294
2332
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
2333
if include_merges:
2300
2334
if levels is None:
2318
2352
# find the file ids to log and check for directory filtering
2319
2353
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2320
revision, file_list, self.add_cleanup)
2354
revision, file_list)
2355
self.add_cleanup(b.unlock)
2321
2356
for relpath, file_id, kind in file_info_list:
2322
2357
if file_id is None:
2323
2358
raise errors.BzrCommandError(
2342
2377
dir, relpath = bzrdir.BzrDir.open_containing(location)
2343
2378
b = dir.open_branch()
2344
self.add_cleanup(b.lock_read().unlock)
2380
self.add_cleanup(b.unlock)
2345
2381
rev1, rev2 = _get_revision_range(revision, b, self.name())
2347
2383
# Decide on the type of delta & diff filtering to use
2367
2403
show_timezone=timezone,
2368
2404
delta_format=get_verbosity_level(),
2370
show_advice=levels is None,
2371
author_list_handler=authors)
2406
show_advice=levels is None)
2373
2408
# Choose the algorithm for doing the logging. It's annoying
2374
2409
# having multiple code paths like this but necessary until
2393
2428
direction=direction, specific_fileids=file_ids,
2394
2429
start_revision=rev1, end_revision=rev2, limit=limit,
2395
2430
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,
2431
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2399
2432
Logger(b, rqst).show(lf)
2472
2505
tree, relpath = WorkingTree.open_containing(filename)
2473
2506
file_id = tree.path2id(relpath)
2474
2507
b = tree.branch
2475
self.add_cleanup(b.lock_read().unlock)
2509
self.add_cleanup(b.unlock)
2476
2510
touching_revs = log.find_touching_revisions(b, file_id)
2477
2511
for revno, revision_id, what in touching_revs:
2478
2512
self.outf.write("%6d %s\n" % (revno, what))
2481
2515
class cmd_ls(Command):
2482
__doc__ = """List files in a tree.
2516
"""List files in a tree.
2485
2519
_see_also = ['status', 'cat']
2491
2525
help='Recurse into subdirectories.'),
2492
2526
Option('from-root',
2493
2527
help='Print paths relative to the root of the branch.'),
2494
Option('unknown', short_name='u',
2495
help='Print unknown files.'),
2528
Option('unknown', help='Print unknown files.'),
2496
2529
Option('versioned', help='Print versioned files.',
2497
2530
short_name='V'),
2498
Option('ignored', short_name='i',
2499
help='Print ignored files.'),
2500
Option('kind', short_name='k',
2531
Option('ignored', help='Print ignored files.'),
2533
help='Write an ascii NUL (\\0) separator '
2534
'between files rather than a newline.'),
2501
2536
help='List entries of a particular kind: file, directory, symlink.',
2507
2540
@display_command
2508
2541
def run(self, revision=None, verbose=False,
2509
2542
recursive=False, from_root=False,
2510
2543
unknown=False, versioned=False, ignored=False,
2511
null=False, kind=None, show_ids=False, path=None, directory=None):
2544
null=False, kind=None, show_ids=False, path=None):
2513
2546
if kind and kind not in ('file', 'directory', 'symlink'):
2514
2547
raise errors.BzrCommandError('invalid kind specified')
2526
2559
raise errors.BzrCommandError('cannot specify both --from-root'
2529
tree, branch, relpath = \
2530
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2562
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2532
2565
# Calculate the prefix to use
2548
2581
view_str = views.view_display_str(view_files)
2549
2582
note("Ignoring files outside view. View is %s" % view_str)
2551
self.add_cleanup(tree.lock_read().unlock)
2585
self.add_cleanup(tree.unlock)
2552
2586
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2553
2587
from_dir=relpath, recursive=recursive):
2554
2588
# Apply additional masking
2598
2632
class cmd_unknowns(Command):
2599
__doc__ = """List unknown files.
2633
"""List unknown files.
2603
2637
_see_also = ['ls']
2604
takes_options = ['directory']
2606
2639
@display_command
2607
def run(self, directory=u'.'):
2608
for f in WorkingTree.open_containing(directory)[0].unknowns():
2641
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2609
2642
self.outf.write(osutils.quotefn(f) + '\n')
2612
2645
class cmd_ignore(Command):
2613
__doc__ = """Ignore specified files or patterns.
2646
"""Ignore specified files or patterns.
2615
2648
See ``bzr help patterns`` for details on the syntax of patterns.
2625
2658
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
2661
Patterns prefixed with '!' are exceptions to ignore patterns and take
2635
2662
precedence over regular ignores. Such exceptions are used to specify
2636
2663
files that should be versioned which would otherwise be ignored.
2677
2704
_see_also = ['status', 'ignored', 'patterns']
2678
2705
takes_args = ['name_pattern*']
2679
takes_options = ['directory',
2680
Option('default-rules',
2681
help='Display the default ignore rules that bzr uses.')
2707
Option('old-default-rules',
2708
help='Write out the ignore rules bzr < 0.9 always used.')
2684
def run(self, name_pattern_list=None, default_rules=None,
2711
def run(self, name_pattern_list=None, old_default_rules=None):
2686
2712
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:
2713
if old_default_rules is not None:
2714
# dump the rules and exit
2715
for pattern in ignores.OLD_DEFAULTS:
2690
2716
self.outf.write("%s\n" % pattern)
2692
2718
if not name_pattern_list:
2693
2719
raise errors.BzrCommandError("ignore requires at least one "
2694
"NAME_PATTERN or --default-rules.")
2720
"NAME_PATTERN or --old-default-rules")
2695
2721
name_pattern_list = [globbing.normalize_pattern(p)
2696
2722
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
2723
for name_pattern in name_pattern_list:
2706
2724
if (name_pattern[0] == '/' or
2707
2725
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2708
2726
raise errors.BzrCommandError(
2709
2727
"NAME_PATTERN should not be an absolute path")
2710
tree, relpath = WorkingTree.open_containing(directory)
2728
tree, relpath = WorkingTree.open_containing(u'.')
2711
2729
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2712
2730
ignored = globbing.Globster(name_pattern_list)
2714
self.add_cleanup(tree.lock_read().unlock)
2715
2733
for entry in tree.list_files():
2717
2735
if id is not None:
2718
2736
filename = entry[0]
2719
2737
if ignored.match(filename):
2720
2738
matches.append(filename)
2721
2740
if len(matches) > 0:
2722
2741
self.outf.write("Warning: the following files are version controlled and"
2723
2742
" match your ignore pattern:\n%s"
2739
2758
encoding_type = 'replace'
2740
2759
_see_also = ['ignore', 'ls']
2741
takes_options = ['directory']
2743
2761
@display_command
2744
def run(self, directory=u'.'):
2745
tree = WorkingTree.open_containing(directory)[0]
2746
self.add_cleanup(tree.lock_read().unlock)
2763
tree = WorkingTree.open_containing(u'.')[0]
2765
self.add_cleanup(tree.unlock)
2747
2766
for path, file_class, kind, file_id, entry in tree.list_files():
2748
2767
if file_class != 'I':
2755
2774
class cmd_lookup_revision(Command):
2756
__doc__ = """Lookup the revision-id from a revision-number
2775
"""Lookup the revision-id from a revision-number
2759
2778
bzr lookup-revision 33
2762
2781
takes_args = ['revno']
2763
takes_options = ['directory']
2765
2783
@display_command
2766
def run(self, revno, directory=u'.'):
2784
def run(self, revno):
2768
2786
revno = int(revno)
2769
2787
except ValueError:
2770
2788
raise errors.BzrCommandError("not a valid revision-number: %r"
2772
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2790
revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2773
2791
self.outf.write("%s\n" % revid)
2776
2794
class cmd_export(Command):
2777
__doc__ = """Export current or past revision to a destination directory or archive.
2795
"""Export current or past revision to a destination directory or archive.
2779
2797
If no revision is specified this exports the last committed revision.
2817
2835
'revision in which it was changed.'),
2819
2837
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2820
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2838
root=None, filters=False, per_file_timestamps=False):
2821
2839
from bzrlib.export import export
2823
2841
if branch_or_subdir is None:
2824
tree = WorkingTree.open_containing(directory)[0]
2842
tree = WorkingTree.open_containing(u'.')[0]
2825
2843
b = tree.branch
2858
2876
@display_command
2859
2877
def run(self, filename, revision=None, name_from_revision=False,
2860
filters=False, directory=None):
2861
2879
if revision is not None and len(revision) != 1:
2862
2880
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2863
2881
" one revision specifier")
2864
2882
tree, branch, relpath = \
2865
_open_directory_or_containing_tree_or_branch(filename, directory)
2866
self.add_cleanup(branch.lock_read().unlock)
2883
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2885
self.add_cleanup(branch.unlock)
2867
2886
return self._run(tree, branch, relpath, filename, revision,
2868
2887
name_from_revision, filters)
3100
3120
properties = {}
3102
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3122
tree, selected_list = tree_files(selected_list)
3103
3123
if selected_list == ['']:
3104
3124
# workaround - commit of root of tree should be exactly the same
3105
3125
# as just default commit in that tree, and succeed even though
3140
3160
def get_message(commit_obj):
3141
3161
"""Callback to get commit message"""
3145
my_message = f.read().decode(osutils.get_user_encoding())
3163
my_message = codecs.open(
3164
file, 'rt', osutils.get_user_encoding()).read()
3148
3165
elif message is not None:
3149
3166
my_message = message
3179
3196
reporter=None, verbose=verbose, revprops=properties,
3180
3197
authors=author, timestamp=commit_stamp,
3181
3198
timezone=offset,
3182
exclude=tree.safe_relpath_files(exclude))
3199
exclude=safe_relpath_files(tree, exclude))
3183
3200
except PointlessCommit:
3184
3201
raise errors.BzrCommandError("No changes to commit."
3185
3202
" Use --unchanged to commit anyhow.")
3201
3218
class cmd_check(Command):
3202
__doc__ = """Validate working tree structure, branch consistency and repository history.
3219
"""Validate working tree structure, branch consistency and repository history.
3204
3221
This command checks various invariants about branch and repository storage
3205
3222
to detect data corruption or bzr bugs.
3305
3322
bzr whoami "Frank Chu <fchu@example.com>"
3307
takes_options = [ 'directory',
3324
takes_options = [ Option('email',
3309
3325
help='Display email address only.'),
3310
3326
Option('branch',
3311
3327
help='Set identity for the current branch instead of '
3315
3331
encoding_type = 'replace'
3317
3333
@display_command
3318
def run(self, email=False, branch=False, name=None, directory=None):
3334
def run(self, email=False, branch=False, name=None):
3319
3335
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()
3336
# use branch if we're inside one; otherwise global config
3338
c = Branch.open_containing('.')[0].get_config()
3339
except errors.NotBranchError:
3340
c = config.GlobalConfig()
3329
3342
self.outf.write(c.user_email() + '\n')
3334
3347
# display a warning if an email address isn't included in the given name.
3336
_mod_config.extract_email_address(name)
3349
config.extract_email_address(name)
3337
3350
except errors.NoEmailInUsername, e:
3338
3351
warning('"%s" does not seem to contain an email address. '
3339
3352
'This is allowed, but not recommended.', name)
3341
3354
# 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()
3356
c = Branch.open_containing('.')[0].get_config()
3348
c = _mod_config.GlobalConfig()
3358
c = config.GlobalConfig()
3349
3359
c.set_user_option('email', name)
3352
3362
class cmd_nick(Command):
3353
__doc__ = """Print or set the branch nickname.
3363
"""Print or set the branch nickname.
3355
3365
If unset, the tree root directory name is used as the nickname.
3356
3366
To print the current nickname, execute with no argument.
3362
3372
_see_also = ['info']
3363
3373
takes_args = ['nickname?']
3364
takes_options = ['directory']
3365
def run(self, nickname=None, directory=u'.'):
3366
branch = Branch.open_containing(directory)[0]
3374
def run(self, nickname=None):
3375
branch = Branch.open_containing(u'.')[0]
3367
3376
if nickname is None:
3368
3377
self.printme(branch)
3418
3427
'bzr alias --remove expects an alias to remove.')
3419
3428
# If alias is not found, print something like:
3420
3429
# unalias: foo: not found
3421
c = _mod_config.GlobalConfig()
3430
c = config.GlobalConfig()
3422
3431
c.unset_alias(alias_name)
3424
3433
@display_command
3425
3434
def print_aliases(self):
3426
3435
"""Print out the defined aliases in a similar format to bash."""
3427
aliases = _mod_config.GlobalConfig().get_aliases()
3436
aliases = config.GlobalConfig().get_aliases()
3428
3437
for key, value in sorted(aliases.iteritems()):
3429
3438
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3441
3450
def set_alias(self, alias_name, alias_command):
3442
3451
"""Save the alias in the global config."""
3443
c = _mod_config.GlobalConfig()
3452
c = config.GlobalConfig()
3444
3453
c.set_alias(alias_name, alias_command)
3447
3456
class cmd_selftest(Command):
3448
__doc__ = """Run internal test suite.
3457
"""Run internal test suite.
3450
3459
If arguments are given, they are regular expressions that say which tests
3451
3460
should run. Tests matching any expression are run, and other tests are
3519
3528
'throughout the test suite.',
3520
3529
type=get_transport_type),
3521
3530
Option('benchmark',
3522
help='Run the benchmarks rather than selftests.',
3531
help='Run the benchmarks rather than selftests.'),
3524
3532
Option('lsprof-timed',
3525
3533
help='Generate lsprof output for benchmarked'
3526
3534
' sections of code.'),
3527
3535
Option('lsprof-tests',
3528
3536
help='Generate lsprof output for each test.'),
3537
Option('cache-dir', type=str,
3538
help='Cache intermediate benchmark output in this '
3529
3540
Option('first',
3530
3541
help='Run all tests, but run specified tests first.',
3531
3542
short_name='f',
3566
3577
def run(self, testspecs_list=None, verbose=False, one=False,
3567
3578
transport=None, benchmark=None,
3579
lsprof_timed=None, cache_dir=None,
3569
3580
first=False, list_only=False,
3570
3581
randomize=None, exclude=None, strict=False,
3571
3582
load_list=None, debugflag=None, starting_with=None, subunit=False,
3572
3583
parallel=None, lsprof_tests=False):
3573
from bzrlib import tests
3584
from bzrlib.tests import selftest
3585
import bzrlib.benchmarks as benchmarks
3586
from bzrlib.benchmarks import tree_creator
3588
# Make deprecation warnings visible, unless -Werror is set
3589
symbol_versioning.activate_deprecation_warnings(override=False)
3591
if cache_dir is not None:
3592
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3575
3593
if testspecs_list is not None:
3576
3594
pattern = '|'.join(testspecs_list)
3583
3601
raise errors.BzrCommandError("subunit not available. subunit "
3584
3602
"needs to be installed to use --subunit.")
3585
3603
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
3605
self.additional_selftest_args.setdefault(
3597
3606
'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
3608
test_suite_factory = benchmarks.test_suite
3609
# Unless user explicitly asks for quiet, be verbose in benchmarks
3610
verbose = not is_quiet()
3611
# TODO: should possibly lock the history file...
3612
benchfile = open(".perf_history", "at", buffering=1)
3613
self.add_cleanup(benchfile.close)
3615
test_suite_factory = None
3603
3617
selftest_kwargs = {"verbose": verbose,
3604
3618
"pattern": pattern,
3605
3619
"stop_on_failure": one,
3607
3621
"test_suite_factory": test_suite_factory,
3608
3622
"lsprof_timed": lsprof_timed,
3609
3623
"lsprof_tests": lsprof_tests,
3624
"bench_history": benchfile,
3610
3625
"matching_tests_first": first,
3611
3626
"list_only": list_only,
3612
3627
"random_seed": randomize,
3617
3632
"starting_with": starting_with
3619
3634
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)
3635
result = selftest(**selftest_kwargs)
3628
3636
return int(not result)
3631
3639
class cmd_version(Command):
3632
__doc__ = """Show version of bzr."""
3640
"""Show version of bzr."""
3634
3642
encoding_type = 'replace'
3635
3643
takes_options = [
3658
3666
class cmd_find_merge_base(Command):
3659
__doc__ = """Find and print a base revision for merging two branches."""
3667
"""Find and print a base revision for merging two branches."""
3660
3668
# TODO: Options to specify revisions on either side, as if
3661
3669
# merging only part of the history.
3662
3670
takes_args = ['branch', 'other']
3669
3677
branch1 = Branch.open_containing(branch)[0]
3670
3678
branch2 = Branch.open_containing(other)[0]
3671
self.add_cleanup(branch1.lock_read().unlock)
3672
self.add_cleanup(branch2.lock_read().unlock)
3680
self.add_cleanup(branch1.unlock)
3682
self.add_cleanup(branch2.unlock)
3673
3683
last1 = ensure_null(branch1.last_revision())
3674
3684
last2 = ensure_null(branch2.last_revision())
3769
3779
' completely merged into the source, pull from the'
3770
3780
' source rather than merging. When this happens,'
3771
3781
' you do not need to commit the result.'),
3772
custom_help('directory',
3773
3783
help='Branch to merge into, '
3774
'rather than the one containing the working directory.'),
3784
'rather than the one containing the working directory.',
3775
3788
Option('preview', help='Instead of merging, show a diff of the'
3777
3790
Option('interactive', help='Select changes interactively.',
3810
3823
unversioned_filter=tree.is_ignored, view_info=view_info)
3811
3824
pb = ui.ui_factory.nested_progress_bar()
3812
3825
self.add_cleanup(pb.finished)
3813
self.add_cleanup(tree.lock_write().unlock)
3827
self.add_cleanup(tree.unlock)
3814
3828
if location is not None:
3816
3830
mergeable = bundle.read_mergeable_from_url(location,
3877
3891
def _do_preview(self, merger):
3878
3892
from bzrlib.diff import show_diff_trees
3879
3893
result_tree = self._get_preview(merger)
3880
path_encoding = osutils.get_diff_header_encoding()
3881
3894
show_diff_trees(merger.this_tree, result_tree, self.outf,
3882
old_label='', new_label='',
3883
path_encoding=path_encoding)
3895
old_label='', new_label='')
3885
3897
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3886
3898
merger.change_reporter = change_reporter
4073
4085
from bzrlib.conflicts import restore
4074
4086
if merge_type is None:
4075
4087
merge_type = _mod_merge.Merge3Merger
4076
tree, file_list = WorkingTree.open_containing_paths(file_list)
4077
self.add_cleanup(tree.lock_write().unlock)
4088
tree, file_list = tree_files(file_list)
4090
self.add_cleanup(tree.unlock)
4078
4091
parents = tree.get_parent_ids()
4079
4092
if len(parents) != 2:
4080
4093
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4135
4148
class cmd_revert(Command):
4136
__doc__ = """Revert files to a previous revision.
4149
"""Revert files to a previous revision.
4138
4151
Giving a list of files will revert only those files. Otherwise, all files
4139
4152
will be reverted. If the revision is not specified with '--revision', the
4190
4203
def run(self, revision=None, no_backup=False, file_list=None,
4191
4204
forget_merges=None):
4192
tree, file_list = WorkingTree.open_containing_paths(file_list)
4193
self.add_cleanup(tree.lock_tree_write().unlock)
4205
tree, file_list = tree_files(file_list)
4207
self.add_cleanup(tree.unlock)
4194
4208
if forget_merges:
4195
4209
tree.set_parent_ids(tree.get_parent_ids()[:1])
4313
4326
theirs_only=False,
4314
4327
log_format=None, long=False, short=False, line=False,
4315
4328
show_ids=False, verbose=False, this=False, other=False,
4316
include_merges=False, revision=None, my_revision=None,
4329
include_merges=False, revision=None, my_revision=None):
4318
4330
from bzrlib.missing import find_unmerged, iter_log_revisions
4319
4331
def message(s):
4320
4332
if not is_quiet():
4350
4360
remote_branch = Branch.open(other_branch)
4351
4361
if remote_branch.base == local_branch.base:
4352
4362
remote_branch = local_branch
4354
self.add_cleanup(remote_branch.lock_read().unlock)
4364
local_branch.lock_read()
4365
self.add_cleanup(local_branch.unlock)
4356
4366
local_revid_range = _revision_range_to_revid_range(
4357
4367
_get_revision_range(my_revision, local_branch,
4370
remote_branch.lock_read()
4371
self.add_cleanup(remote_branch.unlock)
4360
4372
remote_revid_range = _revision_range_to_revid_range(
4361
4373
_get_revision_range(revision,
4362
4374
remote_branch, self.name()))
4412
4424
message("Branches are up to date.\n")
4413
4425
self.cleanup_now()
4414
4426
if not status_code and parent is None and other_branch is not None:
4415
self.add_cleanup(local_branch.lock_write().unlock)
4427
local_branch.lock_write()
4428
self.add_cleanup(local_branch.unlock)
4416
4429
# handle race conditions - a parent might be set while we run.
4417
4430
if local_branch.get_parent() is None:
4418
4431
local_branch.set_parent(remote_branch.base)
4422
4435
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.
4436
"""Compress the data within a repository."""
4441
4438
_see_also = ['repositories']
4442
4439
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):
4441
def run(self, branch_or_repo='.'):
4448
4442
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4450
4444
branch = dir.open_branch()
4451
4445
repository = branch.repository
4452
4446
except errors.NotBranchError:
4453
4447
repository = dir.open_repository()
4454
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4457
4451
class cmd_plugins(Command):
4458
__doc__ = """List the installed plugins.
4452
"""List the installed plugins.
4460
4454
This command displays the list of installed plugins including
4461
4455
version of plugin and a short description of each.
4548
4543
Option('long', help='Show commit date in annotations.'),
4553
4547
encoding_type = 'exact'
4555
4549
@display_command
4556
4550
def run(self, filename, all=False, long=False, revision=None,
4557
show_ids=False, directory=None):
4558
4552
from bzrlib.annotate import annotate_file, annotate_file_tree
4559
4553
wt, branch, relpath = \
4560
_open_directory_or_containing_tree_or_branch(filename, directory)
4554
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4561
4555
if wt is not None:
4562
self.add_cleanup(wt.lock_read().unlock)
4557
self.add_cleanup(wt.unlock)
4564
self.add_cleanup(branch.lock_read().unlock)
4560
self.add_cleanup(branch.unlock)
4565
4561
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4566
self.add_cleanup(tree.lock_read().unlock)
4563
self.add_cleanup(tree.unlock)
4567
4564
if wt is not None:
4568
4565
file_id = wt.path2id(relpath)
4584
4581
class cmd_re_sign(Command):
4585
__doc__ = """Create a digital signature for an existing revision."""
4582
"""Create a digital signature for an existing revision."""
4586
4583
# TODO be able to replace existing ones.
4588
4585
hidden = True # is this right ?
4589
4586
takes_args = ['revision_id*']
4590
takes_options = ['directory', 'revision']
4587
takes_options = ['revision']
4592
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4589
def run(self, revision_id_list=None, revision=None):
4593
4590
if revision_id_list is not None and revision is not None:
4594
4591
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4595
4592
if revision_id_list is None and revision is None:
4596
4593
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)
4594
b = WorkingTree.open_containing(u'.')[0].branch
4596
self.add_cleanup(b.unlock)
4599
4597
return self._run(b, revision_id_list, revision)
4601
4599
def _run(self, b, revision_id_list, revision):
4649
4647
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.
4648
"""Convert the current branch into a checkout of the supplied branch.
4653
4650
Once converted into a checkout, commits must succeed on the master branch
4654
4651
before they will be applied to the local branch.
4661
4658
_see_also = ['checkouts', 'unbind']
4662
4659
takes_args = ['location?']
4663
takes_options = ['directory']
4665
def run(self, location=None, directory=u'.'):
4666
b, relpath = Branch.open_containing(directory)
4662
def run(self, location=None):
4663
b, relpath = Branch.open_containing(u'.')
4667
4664
if location is None:
4669
4666
location = b.get_old_bound_location()
4697
4694
_see_also = ['checkouts', 'bind']
4698
4695
takes_args = []
4699
takes_options = ['directory']
4701
def run(self, directory=u'.'):
4702
b, relpath = Branch.open_containing(directory)
4699
b, relpath = Branch.open_containing(u'.')
4703
4700
if not b.unbind():
4704
4701
raise errors.BzrCommandError('Local branch is not bound')
4707
4704
class cmd_uncommit(Command):
4708
__doc__ = """Remove the last committed revision.
4705
"""Remove the last committed revision.
4710
4707
--verbose will print out what is being removed.
4711
4708
--dry-run will go through all the motions, but not actually
4751
4748
b = control.open_branch()
4753
4750
if tree is not None:
4754
self.add_cleanup(tree.lock_write().unlock)
4752
self.add_cleanup(tree.unlock)
4756
self.add_cleanup(b.lock_write().unlock)
4755
self.add_cleanup(b.unlock)
4757
4756
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
4759
4758
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4813
4812
class cmd_break_lock(Command):
4814
__doc__ = """Break a dead lock.
4816
This command breaks a lock on a repository, branch, working directory or
4813
"""Break a dead lock on a repository, branch or working directory.
4819
4815
CAUTION: Locks should only be broken when you are sure that the process
4820
4816
holding the lock has been stopped.
4827
4823
bzr break-lock bzr+ssh://example.com/bzr/foo
4828
bzr break-lock --conf ~/.bazaar
4831
4825
takes_args = ['location?']
4834
help='LOCATION is the directory where the config lock is.'),
4837
def run(self, location=None, config=False):
4827
def run(self, location=None, show=False):
4838
4828
if location is None:
4839
4829
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:
4830
control, relpath = bzrdir.BzrDir.open_containing(location)
4832
control.break_lock()
4833
except NotImplementedError:
4851
4837
class cmd_wait_until_signalled(Command):
4852
__doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4838
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4854
4840
This just prints a line to signal when it is ready, then blocks on stdin.
4880
4866
'result in a dynamically allocated port. The default port '
4881
4867
'depends on the protocol.',
4883
custom_help('directory',
4884
help='Serve contents of this directory.'),
4870
help='Serve contents of this directory.',
4885
4872
Option('allow-writes',
4886
4873
help='By default the server is a readonly server. Supplying '
4887
4874
'--allow-writes enables write access to the contents of '
4915
4902
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4916
4903
protocol=None):
4917
from bzrlib import transport
4904
from bzrlib.transport import get_transport, transport_server_registry
4918
4905
if directory is None:
4919
4906
directory = os.getcwd()
4920
4907
if protocol is None:
4921
protocol = transport.transport_server_registry.get()
4908
protocol = transport_server_registry.get()
4922
4909
host, port = self.get_host_and_port(port)
4923
4910
url = urlutils.local_path_to_url(directory)
4924
4911
if not allow_writes:
4925
4912
url = 'readonly+' + url
4926
t = transport.get_transport(url)
4927
protocol(t, host, port, inet)
4913
transport = get_transport(url)
4914
protocol(transport, host, port, inet)
4930
4917
class cmd_join(Command):
4931
__doc__ = """Combine a tree into its containing tree.
4918
"""Combine a tree into its containing tree.
4933
4920
This command requires the target tree to be in a rich-root format.
5042
5028
encoding_type = 'exact'
5044
5030
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5045
sign=False, revision=None, mail_to=None, message=None,
5031
sign=False, revision=None, mail_to=None, message=None):
5047
5032
from bzrlib.revision import ensure_null, NULL_REVISION
5048
5033
include_patch, include_bundle = {
5049
5034
'plain': (False, False),
5050
5035
'diff': (True, False),
5051
5036
'bundle': (True, True),
5053
branch = Branch.open(directory)
5038
branch = Branch.open('.')
5054
5039
stored_submit_branch = branch.get_submit_branch()
5055
5040
if submit_branch is None:
5056
5041
submit_branch = stored_submit_branch
5141
5126
given, in which case it is sent to a file.
5143
5128
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.
5129
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5145
5130
If the preferred client can't be found (or used), your editor will be used.
5147
5132
To use a specific mail program, set the mail_client configuration option.
5362
5351
class cmd_tags(Command):
5363
__doc__ = """List tags.
5365
5354
This command shows a table of tag names and the revisions they reference.
5368
5357
_see_also = ['tag']
5369
5358
takes_options = [
5370
custom_help('directory',
5371
help='Branch whose tags should be displayed.'),
5360
help='Branch whose tags should be displayed.',
5372
5364
RegistryOption.from_kwargs('sort',
5373
5365
'Sort tags by different criteria.', title='Sorting',
5374
5366
alpha='Sort tags lexicographically (default).',
5523
5516
class cmd_switch(Command):
5524
__doc__ = """Set the branch of a checkout and update.
5517
"""Set the branch of a checkout and update.
5526
5519
For lightweight checkouts, this changes the branch being referenced.
5527
5520
For heavyweight checkouts, this checks that there are no local commits
5546
5539
takes_args = ['to_location?']
5547
takes_options = ['directory',
5540
takes_options = [Option('force',
5549
5541
help='Switch even if local commits will be lost.'),
5551
5543
Option('create-branch', short_name='b',
5556
5548
def run(self, to_location=None, force=False, create_branch=False,
5557
revision=None, directory=u'.'):
5558
5550
from bzrlib import switch
5559
tree_location = directory
5560
5552
revision = _get_one_revision('switch', revision)
5561
5553
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5562
5554
if to_location is None:
5563
5555
if revision is None:
5564
5556
raise errors.BzrCommandError('You must supply either a'
5565
5557
' revision or a location')
5566
to_location = tree_location
5568
5560
branch = control_dir.open_branch()
5569
5561
had_explicit_nick = branch.get_config().has_explicit_nickname()
5820
5811
class cmd_shelve(Command):
5821
__doc__ = """Temporarily set aside some changes from the current tree.
5812
"""Temporarily set aside some changes from the current tree.
5823
5814
Shelve allows you to temporarily put changes you've made "on the shelf",
5824
5815
ie. out of the way, until a later time when you can bring them back from
5860
5850
_see_also = ['unshelve']
5862
5852
def run(self, revision=None, all=False, file_list=None, message=None,
5863
writer=None, list=False, destroy=False, directory=u'.'):
5853
writer=None, list=False, destroy=False):
5865
5855
return self.run_for_list()
5866
5856
from bzrlib.shelf_ui import Shelver
5868
5858
writer = bzrlib.option.diff_writer_registry.get()
5870
5860
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5871
file_list, message, destroy=destroy, directory=directory)
5861
file_list, message, destroy=destroy)
5917
5907
_see_also = ['shelve']
5919
def run(self, shelf_id=None, action='apply', directory=u'.'):
5909
def run(self, shelf_id=None, action='apply'):
5920
5910
from bzrlib.shelf_ui import Unshelver
5921
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5911
unshelver = Unshelver.from_args(shelf_id, action)
5923
5913
unshelver.run()
5941
5931
To check what clean-tree will do, use --dry-run.
5943
takes_options = ['directory',
5944
Option('ignored', help='Delete all ignored files.'),
5933
takes_options = [Option('ignored', help='Delete all ignored files.'),
5945
5934
Option('detritus', help='Delete conflict files, merge'
5946
5935
' backups, and failed selftest dirs.'),
5947
5936
Option('unknown',
5950
5939
' deleting them.'),
5951
5940
Option('force', help='Do not prompt before deleting.')]
5952
5941
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5953
force=False, directory=u'.'):
5954
5943
from bzrlib.clean_tree import clean_tree
5955
5944
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)
5948
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5949
dry_run=dry_run, no_prompt=force)
5963
5952
class cmd_reference(Command):
5964
__doc__ = """list, view and set branch locations for nested trees.
5953
"""list, view and set branch locations for nested trees.
5966
5955
If no arguments are provided, lists the branch locations for nested trees.
5967
5956
If one argument is provided, display the branch location for that tree.