69
73
_parse_revision_str,
71
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
81
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
74
82
def tree_files(file_list, default_branch=u'.', canonicalize=True,
77
return internal_tree_files(file_list, default_branch, canonicalize,
79
except errors.FileInWrongBranch, e:
80
raise errors.BzrCommandError("%s is not in the same branch as %s" %
81
(e.path, file_list[0]))
84
return internal_tree_files(file_list, default_branch, canonicalize,
84
88
def tree_files_for_add(file_list):
168
175
:return: workingtree, [relative_paths]
170
if file_list is None or len(file_list) == 0:
171
tree = WorkingTree.open_containing(default_branch)[0]
172
if tree.supports_views() and apply_view:
173
view_files = tree.views.lookup_view()
175
file_list = view_files
176
view_str = views.view_display_str(view_files)
177
note("Ignoring files outside view. View is %s" % view_str)
178
return tree, file_list
179
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
180
return tree, safe_relpath_files(tree, file_list, canonicalize,
181
apply_view=apply_view)
184
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
185
"""Convert file_list into a list of relpaths in tree.
187
:param tree: A tree to operate on.
188
:param file_list: A list of user provided paths or None.
189
:param apply_view: if True and a view is set, apply it or check that
190
specified files are within it
191
:return: A list of relative paths.
192
:raises errors.PathNotChild: When a provided path is in a different tree
195
if file_list is None:
197
if tree.supports_views() and apply_view:
198
view_files = tree.views.lookup_view()
202
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
203
# doesn't - fix that up here before we enter the loop.
205
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
208
for filename in file_list:
210
relpath = fixer(osutils.dereference_path(filename))
211
if view_files and not osutils.is_inside_any(view_files, relpath):
212
raise errors.FileOutsideView(filename, view_files)
213
new_list.append(relpath)
214
except errors.PathNotChild:
215
raise errors.FileInWrongBranch(tree.branch, filename)
177
return WorkingTree.open_containing_paths(
178
file_list, default_directory='.',
219
183
def _get_view_info_for_change_reporter(tree):
306
286
def run(self, show_ids=False, file_list=None, revision=None, short=False,
307
versioned=False, no_pending=False, verbose=False):
287
versioned=False, no_pending=False, verbose=False,
308
289
from bzrlib.status import show_tree_status
310
291
if revision and len(revision) > 2:
311
raise errors.BzrCommandError('bzr status --revision takes exactly'
312
' one or two revision specifiers')
292
raise errors.BzrCommandError(gettext('bzr status --revision takes exactly'
293
' one or two revision specifiers'))
314
tree, relfile_list = tree_files(file_list)
295
tree, relfile_list = WorkingTree.open_containing_paths(file_list)
315
296
# Avoid asking for specific files when that is not needed.
316
297
if relfile_list == ['']:
317
298
relfile_list = None
324
305
show_tree_status(tree, show_ids=show_ids,
325
306
specific_files=relfile_list, revision=revision,
326
307
to_file=self.outf, short=short, versioned=versioned,
327
show_pending=(not no_pending), verbose=verbose)
308
show_pending=(not no_pending), verbose=verbose,
309
classify=not no_classify)
330
312
class cmd_cat_revision(Command):
331
"""Write out metadata for a revision.
313
__doc__ = """Write out metadata for a revision.
333
315
The revision to print can either be specified by a specific
334
316
revision identifier, or you can use --revision.
338
320
takes_args = ['revision_id?']
339
takes_options = ['revision']
321
takes_options = ['directory', 'revision']
340
322
# cat-revision is more for frontends so should be exact
341
323
encoding = 'strict'
325
def print_revision(self, revisions, revid):
326
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
327
record = stream.next()
328
if record.storage_kind == 'absent':
329
raise errors.NoSuchRevision(revisions, revid)
330
revtext = record.get_bytes_as('fulltext')
331
self.outf.write(revtext.decode('utf-8'))
344
def run(self, revision_id=None, revision=None):
334
def run(self, revision_id=None, revision=None, directory=u'.'):
345
335
if revision_id is not None and revision is not None:
346
raise errors.BzrCommandError('You can only supply one of'
347
' revision_id or --revision')
336
raise errors.BzrCommandError(gettext('You can only supply one of'
337
' revision_id or --revision'))
348
338
if revision_id is None and revision is None:
349
raise errors.BzrCommandError('You must supply either'
350
' --revision or a revision_id')
351
b = WorkingTree.open_containing(u'.')[0].branch
353
# TODO: jam 20060112 should cat-revision always output utf-8?
354
if revision_id is not None:
355
revision_id = osutils.safe_revision_id(revision_id, warn=False)
357
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
358
except errors.NoSuchRevision:
359
msg = "The repository %s contains no revision %s." % (b.repository.base,
361
raise errors.BzrCommandError(msg)
362
elif revision is not None:
365
raise errors.BzrCommandError('You cannot specify a NULL'
367
rev_id = rev.as_revision_id(b)
368
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
339
raise errors.BzrCommandError(gettext('You must supply either'
340
' --revision or a revision_id'))
342
b = bzrdir.BzrDir.open_containing_tree_or_branch(directory)[1]
344
revisions = b.repository.revisions
345
if revisions is None:
346
raise errors.BzrCommandError(gettext('Repository %r does not support '
347
'access to raw revision texts'))
349
b.repository.lock_read()
351
# TODO: jam 20060112 should cat-revision always output utf-8?
352
if revision_id is not None:
353
revision_id = osutils.safe_revision_id(revision_id, warn=False)
355
self.print_revision(revisions, revision_id)
356
except errors.NoSuchRevision:
357
msg = gettext("The repository {0} contains no revision {1}.").format(
358
b.repository.base, revision_id)
359
raise errors.BzrCommandError(msg)
360
elif revision is not None:
363
raise errors.BzrCommandError(
364
gettext('You cannot specify a NULL revision.'))
365
rev_id = rev.as_revision_id(b)
366
self.print_revision(revisions, rev_id)
368
b.repository.unlock()
371
371
class cmd_dump_btree(Command):
372
"""Dump the contents of a btree index file to stdout.
372
__doc__ = """Dump the contents of a btree index file to stdout.
374
374
PATH is a btree index file, it can be any URL. This includes things like
375
375
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
471
479
working = d.open_workingtree()
472
480
except errors.NoWorkingTree:
473
raise errors.BzrCommandError("No working tree to remove")
481
raise errors.BzrCommandError(gettext("No working tree to remove"))
474
482
except errors.NotLocalUrl:
475
raise errors.BzrCommandError("You cannot remove the working tree"
483
raise errors.BzrCommandError(gettext("You cannot remove the working tree"
484
" of a remote path"))
478
486
if (working.has_changes()):
479
487
raise errors.UncommittedChanges(working)
488
if working.get_shelf_manager().last_shelf() is not None:
489
raise errors.ShelvedChanges(working)
481
working_path = working.bzrdir.root_transport.base
482
branch_path = working.branch.bzrdir.root_transport.base
483
if working_path != branch_path:
484
raise errors.BzrCommandError("You cannot remove the working tree"
485
" from a lightweight checkout")
491
if working.user_url != working.branch.user_url:
492
raise errors.BzrCommandError(gettext("You cannot remove the working tree"
493
" from a lightweight checkout"))
487
495
d.destroy_workingtree()
498
class cmd_repair_workingtree(Command):
499
__doc__ = """Reset the working tree state file.
501
This is not meant to be used normally, but more as a way to recover from
502
filesystem corruption, etc. This rebuilds the working inventory back to a
503
'known good' state. Any new modifications (adding a file, renaming, etc)
504
will be lost, though modified files will still be detected as such.
506
Most users will want something more like "bzr revert" or "bzr update"
507
unless the state file has become corrupted.
509
By default this attempts to recover the current state by looking at the
510
headers of the state file. If the state file is too corrupted to even do
511
that, you can supply --revision to force the state of the tree.
514
takes_options = ['revision', 'directory',
516
help='Reset the tree even if it doesn\'t appear to be'
521
def run(self, revision=None, directory='.', force=False):
522
tree, _ = WorkingTree.open_containing(directory)
523
self.add_cleanup(tree.lock_tree_write().unlock)
527
except errors.BzrError:
528
pass # There seems to be a real error here, so we'll reset
531
raise errors.BzrCommandError(gettext(
532
'The tree does not appear to be corrupt. You probably'
533
' want "bzr revert" instead. Use "--force" if you are'
534
' sure you want to reset the working tree.'))
538
revision_ids = [r.as_revision_id(tree.branch) for r in revision]
540
tree.reset_state(revision_ids)
541
except errors.BzrError, e:
542
if revision_ids is None:
543
extra = (gettext(', the header appears corrupt, try passing -r -1'
544
' to set the state to the last commit'))
547
raise errors.BzrCommandError(gettext('failed to reset the tree state{0}').format(extra))
490
550
class cmd_revno(Command):
491
"""Show current revision number.
551
__doc__ = """Show current revision number.
493
553
This is equal to the number of revisions on this branch.
516
575
revno = ".".join(str(n) for n in revno_t)
518
577
b = Branch.open_containing(location)[0]
520
self.add_cleanup(b.unlock)
578
self.add_cleanup(b.lock_read().unlock)
521
579
revno = b.revno()
522
580
self.cleanup_now()
523
581
self.outf.write(str(revno) + '\n')
526
584
class cmd_revision_info(Command):
527
"""Show revision number and revision id for a given revision identifier.
585
__doc__ = """Show revision number and revision id for a given revision identifier.
530
588
takes_args = ['revision_info*']
531
589
takes_options = [
591
custom_help('directory',
534
592
help='Branch to examine, '
535
'rather than the one containing the working directory.',
593
'rather than the one containing the working directory.'),
539
594
Option('tree', help='Show revno of working tree'),
728
793
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
729
794
if kind and kind not in ['file', 'directory', 'symlink']:
730
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
795
raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
732
797
revision = _get_one_revision('inventory', revision)
733
work_tree, file_list = tree_files(file_list)
734
work_tree.lock_read()
735
self.add_cleanup(work_tree.unlock)
798
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
799
self.add_cleanup(work_tree.lock_read().unlock)
736
800
if revision is not None:
737
801
tree = revision.as_tree(work_tree.branch)
739
803
extra_trees = [work_tree]
741
self.add_cleanup(tree.unlock)
804
self.add_cleanup(tree.lock_read().unlock)
799
863
return self.run_auto(names_list, after, dry_run)
801
raise errors.BzrCommandError('--dry-run requires --auto.')
865
raise errors.BzrCommandError(gettext('--dry-run requires --auto.'))
802
866
if names_list is None:
804
868
if len(names_list) < 2:
805
raise errors.BzrCommandError("missing file argument")
806
tree, rel_names = tree_files(names_list, canonicalize=False)
807
tree.lock_tree_write()
808
self.add_cleanup(tree.unlock)
869
raise errors.BzrCommandError(gettext("missing file argument"))
870
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
871
self.add_cleanup(tree.lock_tree_write().unlock)
809
872
self._run(tree, names_list, rel_names, after)
811
874
def run_auto(self, names_list, after, dry_run):
812
875
if names_list is not None and len(names_list) > 1:
813
raise errors.BzrCommandError('Only one path may be specified to'
876
raise errors.BzrCommandError(gettext('Only one path may be specified to'
816
raise errors.BzrCommandError('--after cannot be specified with'
818
work_tree, file_list = tree_files(names_list, default_branch='.')
819
work_tree.lock_tree_write()
820
self.add_cleanup(work_tree.unlock)
879
raise errors.BzrCommandError(gettext('--after cannot be specified with'
881
work_tree, file_list = WorkingTree.open_containing_paths(
882
names_list, default_directory='.')
883
self.add_cleanup(work_tree.lock_tree_write().unlock)
821
884
rename_map.RenameMap.guess_renames(work_tree, dry_run)
823
886
def _run(self, tree, names_list, rel_names, after):
917
980
match the remote one, use pull --overwrite. This will work even if the two
918
981
branches have diverged.
920
If there is no default location set, the first pull will set it. After
921
that, you can omit the location to use the default. To change the
922
default, use --remember. The value will only be saved if the remote
923
location can be accessed.
983
If there is no default location set, the first pull will set it (use
984
--no-remember to avoid setting it). After that, you can omit the
985
location to use the default. To change the default, use --remember. The
986
value will only be saved if the remote location can be accessed.
925
988
Note: The location can be specified either in the form of a branch,
926
989
or in the form of a path to a file containing a merge directive generated
931
994
takes_options = ['remember', 'overwrite', 'revision',
932
995
custom_help('verbose',
933
996
help='Show logs of pulled revisions.'),
997
custom_help('directory',
935
998
help='Branch to pull into, '
936
'rather than the one containing the working directory.',
999
'rather than the one containing the working directory.'),
941
1001
help="Perform a local pull in a bound "
942
1002
"branch. Local pulls are not applied to "
943
1003
"the master branch."
1006
help="Show base revision text in conflicts.")
946
1008
takes_args = ['location?']
947
1009
encoding_type = 'replace'
949
def run(self, location=None, remember=False, overwrite=False,
1011
def run(self, location=None, remember=None, overwrite=False,
950
1012
revision=None, verbose=False,
951
directory=None, local=False):
1013
directory=None, local=False,
952
1015
# FIXME: too much stuff is in the command class
953
1016
revision_id = None
954
1017
mergeable = None
975
1043
stored_loc = branch_to.get_parent()
976
1044
if location is None:
977
1045
if stored_loc is None:
978
raise errors.BzrCommandError("No pull location known or"
1046
raise errors.BzrCommandError(gettext("No pull location known or"
981
1049
display_url = urlutils.unescape_for_display(stored_loc,
982
1050
self.outf.encoding)
983
1051
if not is_quiet():
984
self.outf.write("Using saved parent location: %s\n" % display_url)
1052
self.outf.write(gettext("Using saved parent location: %s\n") % display_url)
985
1053
location = stored_loc
987
1055
revision = _get_one_revision('pull', revision)
988
1056
if mergeable is not None:
989
1057
if revision is not None:
990
raise errors.BzrCommandError(
991
'Cannot use -r with merge directives or bundles')
1058
raise errors.BzrCommandError(gettext(
1059
'Cannot use -r with merge directives or bundles'))
992
1060
mergeable.install_revisions(branch_to.repository)
993
1061
base_revision_id, revision_id, verified = \
994
1062
mergeable.get_merge_request(branch_to.repository)
1047
1116
do a merge (see bzr help merge) from the other branch, and commit that.
1048
1117
After that you will be able to do a push without '--overwrite'.
1050
If there is no default push location set, the first push will set it.
1051
After that, you can omit the location to use the default. To change the
1052
default, use --remember. The value will only be saved if the remote
1053
location can be accessed.
1119
If there is no default push location set, the first push will set it (use
1120
--no-remember to avoid setting it). After that, you can omit the
1121
location to use the default. To change the default, use --remember. The
1122
value will only be saved if the remote location can be accessed.
1056
1125
_see_also = ['pull', 'update', 'working-trees']
1080
1146
Option('strict',
1081
1147
help='Refuse to push if there are uncommitted changes in'
1082
1148
' the working tree, --no-strict disables the check.'),
1150
help="Don't populate the working tree, even for protocols"
1151
" that support it."),
1084
1153
takes_args = ['location?']
1085
1154
encoding_type = 'replace'
1087
def run(self, location=None, remember=False, overwrite=False,
1156
def run(self, location=None, remember=None, overwrite=False,
1088
1157
create_prefix=False, verbose=False, revision=None,
1089
1158
use_existing_dir=False, directory=None, stacked_on=None,
1090
stacked=False, strict=None):
1159
stacked=False, strict=None, no_tree=False):
1091
1160
from bzrlib.push import _show_push_branch
1093
1162
if directory is None:
1095
1164
# Get the source branch
1096
1165
(tree, br_from,
1097
1166
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1099
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1100
if strict is None: strict = True # default value
1101
1167
# Get the tip's revision_id
1102
1168
revision = _get_one_revision('push', revision)
1103
1169
if revision is not None:
1104
1170
revision_id = revision.in_history(br_from).rev_id
1106
1172
revision_id = None
1107
if strict and tree is not None and revision_id is None:
1108
if (tree.has_changes()):
1109
raise errors.UncommittedChanges(
1110
tree, more='Use --no-strict to force the push.')
1111
if tree.last_revision() != tree.branch.last_revision():
1112
# The tree has lost sync with its branch, there is little
1113
# chance that the user is aware of it but he can still force
1114
# the push with --no-strict
1115
raise errors.OutOfDateTree(
1116
tree, more='Use --no-strict to force the push.')
1173
if tree is not None and revision_id is None:
1174
tree.check_changed_or_out_of_date(
1175
strict, 'push_strict',
1176
more_error='Use --no-strict to force the push.',
1177
more_warning='Uncommitted changes will not be pushed.')
1118
1178
# Get the stacked_on branch, if any
1119
1179
if stacked_on is not None:
1120
1180
stacked_on = urlutils.normalize_url(stacked_on)
1130
1190
# error by the feedback given to them. RBC 20080227.
1131
1191
stacked_on = parent_url
1132
1192
if not stacked_on:
1133
raise errors.BzrCommandError(
1134
"Could not determine branch to refer to.")
1193
raise errors.BzrCommandError(gettext(
1194
"Could not determine branch to refer to."))
1136
1196
# Get the destination location
1137
1197
if location is None:
1138
1198
stored_loc = br_from.get_push_location()
1139
1199
if stored_loc is None:
1140
raise errors.BzrCommandError(
1141
"No push location known or specified.")
1200
raise errors.BzrCommandError(gettext(
1201
"No push location known or specified."))
1143
1203
display_url = urlutils.unescape_for_display(stored_loc,
1144
1204
self.outf.encoding)
1145
self.outf.write("Using saved push location: %s\n" % display_url)
1205
note(gettext("Using saved push location: %s") % display_url)
1146
1206
location = stored_loc
1148
1208
_show_push_branch(br_from, revision_id, location, self.outf,
1149
1209
verbose=verbose, overwrite=overwrite, remember=remember,
1150
1210
stacked_on=stacked_on, create_prefix=create_prefix,
1151
use_existing_dir=use_existing_dir)
1211
use_existing_dir=use_existing_dir, no_tree=no_tree)
1154
1214
class cmd_branch(Command):
1155
"""Create a new branch that is a copy of an existing branch.
1215
__doc__ = """Create a new branch that is a copy of an existing branch.
1157
1217
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1158
1218
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1164
1224
To retrieve the branch as of a particular revision, supply the --revision
1165
1225
parameter, as in "branch foo/bar -r 5".
1227
The synonyms 'clone' and 'get' for this command are deprecated.
1168
1230
_see_also = ['checkout']
1169
1231
takes_args = ['from_location', 'to_location?']
1170
takes_options = ['revision', Option('hardlink',
1171
help='Hard-link working tree files where possible.'),
1232
takes_options = ['revision',
1233
Option('hardlink', help='Hard-link working tree files where possible.'),
1234
Option('files-from', type=str,
1235
help="Get file contents from this tree."),
1172
1236
Option('no-tree',
1173
1237
help="Create a branch without a working-tree."),
1174
1238
Option('switch',
1193
1257
def run(self, from_location, to_location=None, revision=None,
1194
1258
hardlink=False, stacked=False, standalone=False, no_tree=False,
1195
use_existing_dir=False, switch=False, bind=False):
1259
use_existing_dir=False, switch=False, bind=False,
1196
1261
from bzrlib import switch as _mod_switch
1197
1262
from bzrlib.tag import _merge_tags_if_possible
1263
if self.invoked_as in ['get', 'clone']:
1264
ui.ui_factory.show_user_warning(
1265
'deprecated_command',
1266
deprecated_name=self.invoked_as,
1267
recommended_name='branch',
1268
deprecated_in_version='2.4')
1198
1269
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1271
if not (hardlink or files_from):
1272
# accelerator_tree is usually slower because you have to read N
1273
# files (no readahead, lots of seeks, etc), but allow the user to
1274
# explicitly request it
1275
accelerator_tree = None
1276
if files_from is not None and files_from != from_location:
1277
accelerator_tree = WorkingTree.open(files_from)
1200
1278
revision = _get_one_revision('branch', revision)
1202
self.add_cleanup(br_from.unlock)
1279
self.add_cleanup(br_from.lock_read().unlock)
1203
1280
if revision is not None:
1204
1281
revision_id = revision.as_revision_id(br_from)
1238
1315
branch = dir.open_branch()
1239
1316
except errors.NoSuchRevision:
1240
1317
to_transport.delete_tree('.')
1241
msg = "The branch %s has no revision %s." % (from_location,
1318
msg = gettext("The branch {0} has no revision {1}.").format(
1319
from_location, revision)
1243
1320
raise errors.BzrCommandError(msg)
1244
1321
_merge_tags_if_possible(br_from, branch)
1245
1322
# If the source branch is stacked, the new branch may
1246
1323
# be stacked whether we asked for that explicitly or not.
1247
1324
# We therefore need a try/except here and not just 'if stacked:'
1249
note('Created new stacked branch referring to %s.' %
1326
note(gettext('Created new stacked branch referring to %s.') %
1250
1327
branch.get_stacked_on_url())
1251
1328
except (errors.NotStacked, errors.UnstackableBranchFormat,
1252
1329
errors.UnstackableRepositoryFormat), e:
1253
note('Branched %d revision(s).' % branch.revno())
1330
note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
1255
1332
# Bind to the parent
1256
1333
parent_branch = Branch.open(from_location)
1257
1334
branch.bind(parent_branch)
1258
note('New branch bound to %s' % from_location)
1335
note(gettext('New branch bound to %s') % from_location)
1260
1337
# Switch to the new branch
1261
1338
wt, _ = WorkingTree.open_containing('.')
1262
1339
_mod_switch.switch(wt.bzrdir, branch)
1263
note('Switched to branch: %s',
1340
note(gettext('Switched to branch: %s'),
1264
1341
urlutils.unescape_for_display(branch.base, 'utf-8'))
1344
class cmd_branches(Command):
1345
__doc__ = """List the branches available at the current location.
1347
This command will print the names of all the branches at the current location.
1350
takes_args = ['location?']
1352
def run(self, location="."):
1353
dir = bzrdir.BzrDir.open_containing(location)[0]
1354
for branch in dir.list_branches():
1355
if branch.name is None:
1356
self.outf.write(gettext(" (default)\n"))
1358
self.outf.write(" %s\n" % branch.name.encode(self.outf.encoding))
1267
1361
class cmd_checkout(Command):
1268
"""Create a new checkout of an existing branch.
1362
__doc__ = """Create a new checkout of an existing branch.
1270
1364
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1271
1365
the branch found in '.'. This is useful if you have removed the working tree
1375
1472
If you want to discard your local changes, you can just do a
1376
1473
'bzr revert' instead of 'bzr commit' after the update.
1475
If you want to restore a file that has been removed locally, use
1476
'bzr revert' instead of 'bzr update'.
1378
1478
If the tree's branch is bound to a master branch, it will also update
1379
1479
the branch from the master.
1382
1482
_see_also = ['pull', 'working-trees', 'status-flags']
1383
1483
takes_args = ['dir?']
1384
takes_options = ['revision']
1484
takes_options = ['revision',
1486
help="Show base revision text in conflicts."),
1385
1488
aliases = ['up']
1387
def run(self, dir='.', revision=None):
1490
def run(self, dir='.', revision=None, show_base=None):
1388
1491
if revision is not None and len(revision) != 1:
1389
raise errors.BzrCommandError(
1390
"bzr update --revision takes exactly one revision")
1492
raise errors.BzrCommandError(gettext(
1493
"bzr update --revision takes exactly one revision"))
1391
1494
tree = WorkingTree.open_containing(dir)[0]
1392
1495
branch = tree.branch
1393
1496
possible_transports = []
1394
1497
master = branch.get_master_branch(
1395
1498
possible_transports=possible_transports)
1396
1499
if master is not None:
1398
1500
branch_location = master.base
1503
branch_location = tree.branch.base
1400
1504
tree.lock_tree_write()
1401
branch_location = tree.branch.base
1402
1505
self.add_cleanup(tree.unlock)
1403
1506
# get rid of the final '/' and be ready for display
1404
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1507
branch_location = urlutils.unescape_for_display(
1508
branch_location.rstrip('/'),
1406
1510
existing_pending_merges = tree.get_parent_ids()[1:]
1407
1511
if master is None:
1429
1533
change_reporter,
1430
1534
possible_transports=possible_transports,
1431
1535
revision=revision_id,
1537
show_base=show_base)
1433
1538
except errors.NoSuchRevision, e:
1434
raise errors.BzrCommandError(
1539
raise errors.BzrCommandError(gettext(
1435
1540
"branch has no revision %s\n"
1436
1541
"bzr update --revision only works"
1437
" for a revision in the branch history"
1542
" for a revision in the branch history")
1438
1543
% (e.revision))
1439
revno = tree.branch.revision_id_to_revno(
1544
revno = tree.branch.revision_id_to_dotted_revno(
1440
1545
_mod_revision.ensure_null(tree.last_revision()))
1441
note('Updated to revision %d of branch %s' %
1442
(revno, branch_location))
1443
if tree.get_parent_ids()[1:] != existing_pending_merges:
1444
note('Your local commits will now show as pending merges with '
1445
"'bzr status', and can be committed with 'bzr commit'.")
1546
note(gettext('Updated to revision {0} of branch {1}').format(
1547
'.'.join(map(str, revno)), branch_location))
1548
parent_ids = tree.get_parent_ids()
1549
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1550
note(gettext('Your local commits will now show as pending merges with '
1551
"'bzr status', and can be committed with 'bzr commit'."))
1446
1552
if conflicts != 0:
1507
1614
RegistryOption.from_kwargs('file-deletion-strategy',
1508
1615
'The file deletion mode to be used.',
1509
1616
title='Deletion Strategy', value_switches=True, enum_switch=False,
1510
safe='Only delete files if they can be'
1511
' safely recovered (default).',
1617
safe='Backup changed files (default).',
1512
1618
keep='Delete from bzr but leave the working copy.',
1619
no_backup='Don\'t backup changed files.',
1513
1620
force='Delete all the specified files, even if they can not be '
1514
'recovered and even if they are non-empty directories.')]
1621
'recovered and even if they are non-empty directories. '
1622
'(deprecated, use no-backup)')]
1515
1623
aliases = ['rm', 'del']
1516
1624
encoding_type = 'replace'
1518
1626
def run(self, file_list, verbose=False, new=False,
1519
1627
file_deletion_strategy='safe'):
1520
tree, file_list = tree_files(file_list)
1628
if file_deletion_strategy == 'force':
1629
note(gettext("(The --force option is deprecated, rather use --no-backup "
1631
file_deletion_strategy = 'no-backup'
1633
tree, file_list = WorkingTree.open_containing_paths(file_list)
1522
1635
if file_list is not None:
1523
1636
file_list = [f for f in file_list]
1526
self.add_cleanup(tree.unlock)
1638
self.add_cleanup(tree.lock_write().unlock)
1527
1639
# Heuristics should probably all move into tree.remove_smart or
1922
2069
help='Use this command to compare files.',
2072
RegistryOption('format',
2074
help='Diff format to use.',
2075
lazy_registry=('bzrlib.diff', 'format_registry'),
2076
title='Diff format'),
1926
2078
aliases = ['di', 'dif']
1927
2079
encoding_type = 'exact'
1929
2081
@display_command
1930
2082
def run(self, revision=None, file_list=None, diff_options=None,
1931
prefix=None, old=None, new=None, using=None):
1932
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
2083
prefix=None, old=None, new=None, using=None, format=None):
2084
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
1934
2087
if (prefix is None) or (prefix == '0'):
1935
2088
# diff -p0 format
1941
2094
elif ':' in prefix:
1942
2095
old_label, new_label = prefix.split(":")
1944
raise errors.BzrCommandError(
2097
raise errors.BzrCommandError(gettext(
1945
2098
'--prefix expects two values separated by a colon'
1946
' (eg "old/:new/")')
2099
' (eg "old/:new/")'))
1948
2101
if revision and len(revision) > 2:
1949
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1950
' one or two revision specifiers')
2102
raise errors.BzrCommandError(gettext('bzr diff --revision takes exactly'
2103
' one or two revision specifiers'))
2105
if using is not None and format is not None:
2106
raise errors.BzrCommandError(gettext(
2107
'{0} and {1} are mutually exclusive').format(
2108
'--using', '--format'))
1952
2110
(old_tree, new_tree,
1953
2111
old_branch, new_branch,
1954
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1955
file_list, revision, old, new, apply_view=True)
2112
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
2113
file_list, revision, old, new, self.add_cleanup, apply_view=True)
2114
# GNU diff on Windows uses ANSI encoding for filenames
2115
path_encoding = osutils.get_diff_header_encoding()
1956
2116
return show_diff_trees(old_tree, new_tree, sys.stdout,
1957
2117
specific_files=specific_files,
1958
2118
external_diff_options=diff_options,
1959
2119
old_label=old_label, new_label=new_label,
1960
extra_trees=extra_trees, using=using)
2120
extra_trees=extra_trees,
2121
path_encoding=path_encoding,
1963
2126
class cmd_deleted(Command):
1964
"""List files deleted in the working tree.
2127
__doc__ = """List files deleted in the working tree.
1966
2129
# TODO: Show files deleted since a previous revision, or
1967
2130
# between two revisions.
1970
2133
# level of effort but possibly much less IO. (Or possibly not,
1971
2134
# if the directories are very large...)
1972
2135
_see_also = ['status', 'ls']
1973
takes_options = ['show-ids']
2136
takes_options = ['directory', 'show-ids']
1975
2138
@display_command
1976
def run(self, show_ids=False):
1977
tree = WorkingTree.open_containing(u'.')[0]
1979
self.add_cleanup(tree.unlock)
2139
def run(self, show_ids=False, directory=u'.'):
2140
tree = WorkingTree.open_containing(directory)[0]
2141
self.add_cleanup(tree.lock_read().unlock)
1980
2142
old = tree.basis_tree()
1982
self.add_cleanup(old.unlock)
2143
self.add_cleanup(old.lock_read().unlock)
1983
2144
for path, ie in old.inventory.iter_entries():
1984
2145
if not tree.has_id(ie.file_id):
1985
2146
self.outf.write(path)
1992
2153
class cmd_modified(Command):
1993
"""List files modified in working tree.
2154
__doc__ = """List files modified in working tree.
1997
2158
_see_also = ['status', 'ls']
2000
help='Write an ascii NUL (\\0) separator '
2001
'between files rather than a newline.')
2159
takes_options = ['directory', 'null']
2004
2161
@display_command
2005
def run(self, null=False):
2006
tree = WorkingTree.open_containing(u'.')[0]
2162
def run(self, null=False, directory=u'.'):
2163
tree = WorkingTree.open_containing(directory)[0]
2164
self.add_cleanup(tree.lock_read().unlock)
2007
2165
td = tree.changes_from(tree.basis_tree())
2008
2167
for path, id, kind, text_modified, meta_modified in td.modified:
2010
2169
self.outf.write(path + '\0')
2015
2174
class cmd_added(Command):
2016
"""List files added in working tree.
2175
__doc__ = """List files added in working tree.
2020
2179
_see_also = ['status', 'ls']
2023
help='Write an ascii NUL (\\0) separator '
2024
'between files rather than a newline.')
2180
takes_options = ['directory', 'null']
2027
2182
@display_command
2028
def run(self, null=False):
2029
wt = WorkingTree.open_containing(u'.')[0]
2031
self.add_cleanup(wt.unlock)
2183
def run(self, null=False, directory=u'.'):
2184
wt = WorkingTree.open_containing(directory)[0]
2185
self.add_cleanup(wt.lock_read().unlock)
2032
2186
basis = wt.basis_tree()
2034
self.add_cleanup(basis.unlock)
2187
self.add_cleanup(basis.lock_read().unlock)
2035
2188
basis_inv = basis.inventory
2036
2189
inv = wt.inventory
2037
2190
for file_id in inv:
2038
if file_id in basis_inv:
2191
if basis_inv.has_id(file_id):
2040
2193
if inv.is_root(file_id) and len(basis_inv) == 0:
2042
2195
path = inv.id2path(file_id)
2043
if not os.access(osutils.abspath(path), os.F_OK):
2196
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2046
2199
self.outf.write(path + '\0')
2264
2425
Option('show-diff',
2265
2426
short_name='p',
2266
2427
help='Show changes made in each revision as a patch.'),
2267
Option('include-merges',
2428
Option('include-merged',
2268
2429
help='Show merged revisions like --levels 0 does.'),
2430
Option('include-merges', hidden=True,
2431
help='Historical alias for --include-merged.'),
2432
Option('omit-merges',
2433
help='Do not report commits with more than one parent.'),
2434
Option('exclude-common-ancestry',
2435
help='Display only the revisions that are not part'
2436
' of both ancestries (require -rX..Y)'
2438
Option('signatures',
2439
help='Show digital signature validity'),
2442
help='Show revisions whose properties match this '
2445
ListOption('match-message',
2446
help='Show revisions whose message matches this '
2449
ListOption('match-committer',
2450
help='Show revisions whose committer matches this '
2453
ListOption('match-author',
2454
help='Show revisions whose authors match this '
2457
ListOption('match-bugs',
2458
help='Show revisions whose bugs match this '
2270
2462
encoding_type = 'replace'
2283
2475
show_diff=False,
2284
include_merges=False):
2476
include_merged=None,
2478
exclude_common_ancestry=False,
2482
match_committer=None,
2486
include_merges=symbol_versioning.DEPRECATED_PARAMETER,
2285
2488
from bzrlib.log import (
2287
2490
make_log_request_dict,
2288
2491
_get_info_for_log_files,
2290
2493
direction = (forward and 'forward') or 'reverse'
2494
if symbol_versioning.deprecated_passed(include_merges):
2495
ui.ui_factory.show_user_warning(
2496
'deprecated_command_option',
2497
deprecated_name='--include-merges',
2498
recommended_name='--include-merged',
2499
deprecated_in_version='2.5',
2500
command=self.invoked_as)
2501
if include_merged is None:
2502
include_merged = include_merges
2504
raise errors.BzrCommandError(gettext(
2505
'{0} and {1} are mutually exclusive').format(
2506
'--include-merges', '--include-merged'))
2507
if include_merged is None:
2508
include_merged = False
2509
if (exclude_common_ancestry
2510
and (revision is None or len(revision) != 2)):
2511
raise errors.BzrCommandError(gettext(
2512
'--exclude-common-ancestry requires -r with two revisions'))
2292
2514
if levels is None:
2295
raise errors.BzrCommandError(
2296
'--levels and --include-merges are mutually exclusive')
2517
raise errors.BzrCommandError(gettext(
2518
'{0} and {1} are mutually exclusive').format(
2519
'--levels', '--include-merged'))
2298
2521
if change is not None:
2299
2522
if len(change) > 1:
2300
2523
raise errors.RangeInChangeOption()
2301
2524
if revision is not None:
2302
raise errors.BzrCommandError(
2303
'--revision and --change are mutually exclusive')
2525
raise errors.BzrCommandError(gettext(
2526
'{0} and {1} are mutually exclusive').format(
2527
'--revision', '--change'))
2305
2529
revision = change
2408
2653
# b is taken from revision[0].get_branch(), and
2409
2654
# show_log will use its revision_history. Having
2410
2655
# different branches will lead to weird behaviors.
2411
raise errors.BzrCommandError(
2656
raise errors.BzrCommandError(gettext(
2412
2657
"bzr %s doesn't accept two revisions in different"
2413
" branches." % command_name)
2414
rev1 = start_spec.in_history(branch)
2658
" branches.") % command_name)
2659
if start_spec.spec is None:
2660
# Avoid loading all the history.
2661
rev1 = RevisionInfo(branch, None, None)
2663
rev1 = start_spec.in_history(branch)
2415
2664
# Avoid loading all of history when we know a missing
2416
2665
# end of range means the last revision ...
2417
2666
if end_spec.spec is None:
2479
2727
help='Recurse into subdirectories.'),
2480
2728
Option('from-root',
2481
2729
help='Print paths relative to the root of the branch.'),
2482
Option('unknown', help='Print unknown files.'),
2730
Option('unknown', short_name='u',
2731
help='Print unknown files.'),
2483
2732
Option('versioned', help='Print versioned files.',
2484
2733
short_name='V'),
2485
Option('ignored', help='Print ignored files.'),
2487
help='Write an ascii NUL (\\0) separator '
2488
'between files rather than a newline.'),
2734
Option('ignored', short_name='i',
2735
help='Print ignored files.'),
2736
Option('kind', short_name='k',
2490
2737
help='List entries of a particular kind: file, directory, symlink.',
2494
2743
@display_command
2495
2744
def run(self, revision=None, verbose=False,
2496
2745
recursive=False, from_root=False,
2497
2746
unknown=False, versioned=False, ignored=False,
2498
null=False, kind=None, show_ids=False, path=None):
2747
null=False, kind=None, show_ids=False, path=None, directory=None):
2500
2749
if kind and kind not in ('file', 'directory', 'symlink'):
2501
raise errors.BzrCommandError('invalid kind specified')
2750
raise errors.BzrCommandError(gettext('invalid kind specified'))
2503
2752
if verbose and null:
2504
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2753
raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
2505
2754
all = not (unknown or versioned or ignored)
2507
2756
selection = {'I':ignored, '?':unknown, 'V':versioned}
2658
2922
_see_also = ['status', 'ignored', 'patterns']
2659
2923
takes_args = ['name_pattern*']
2661
Option('old-default-rules',
2662
help='Write out the ignore rules bzr < 0.9 always used.')
2924
takes_options = ['directory',
2925
Option('default-rules',
2926
help='Display the default ignore rules that bzr uses.')
2665
def run(self, name_pattern_list=None, old_default_rules=None):
2929
def run(self, name_pattern_list=None, default_rules=None,
2666
2931
from bzrlib import ignores
2667
if old_default_rules is not None:
2668
# dump the rules and exit
2669
for pattern in ignores.OLD_DEFAULTS:
2932
if default_rules is not None:
2933
# dump the default rules and exit
2934
for pattern in ignores.USER_DEFAULTS:
2935
self.outf.write("%s\n" % pattern)
2672
2937
if not name_pattern_list:
2673
raise errors.BzrCommandError("ignore requires at least one "
2674
"NAME_PATTERN or --old-default-rules")
2938
raise errors.BzrCommandError(gettext("ignore requires at least one "
2939
"NAME_PATTERN or --default-rules."))
2675
2940
name_pattern_list = [globbing.normalize_pattern(p)
2676
2941
for p in name_pattern_list]
2943
bad_patterns_count = 0
2944
for p in name_pattern_list:
2945
if not globbing.Globster.is_pattern_valid(p):
2946
bad_patterns_count += 1
2947
bad_patterns += ('\n %s' % p)
2949
msg = (ngettext('Invalid ignore pattern found. %s',
2950
'Invalid ignore patterns found. %s',
2951
bad_patterns_count) % bad_patterns)
2952
ui.ui_factory.show_error(msg)
2953
raise errors.InvalidPattern('')
2677
2954
for name_pattern in name_pattern_list:
2678
2955
if (name_pattern[0] == '/' or
2679
2956
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2680
raise errors.BzrCommandError(
2681
"NAME_PATTERN should not be an absolute path")
2682
tree, relpath = WorkingTree.open_containing(u'.')
2957
raise errors.BzrCommandError(gettext(
2958
"NAME_PATTERN should not be an absolute path"))
2959
tree, relpath = WorkingTree.open_containing(directory)
2683
2960
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2684
2961
ignored = globbing.Globster(name_pattern_list)
2963
self.add_cleanup(tree.lock_read().unlock)
2687
2964
for entry in tree.list_files():
2689
2966
if id is not None:
2690
2967
filename = entry[0]
2691
2968
if ignored.match(filename):
2692
matches.append(filename.encode('utf-8'))
2969
matches.append(filename)
2694
2970
if len(matches) > 0:
2695
print "Warning: the following files are version controlled and" \
2696
" match your ignore pattern:\n%s" \
2697
"\nThese files will continue to be version controlled" \
2698
" unless you 'bzr remove' them." % ("\n".join(matches),)
2971
self.outf.write(gettext("Warning: the following files are version "
2972
"controlled and match your ignore pattern:\n%s"
2973
"\nThese files will continue to be version controlled"
2974
" unless you 'bzr remove' them.\n") % ("\n".join(matches),))
2701
2977
class cmd_ignored(Command):
2702
"""List ignored files and the patterns that matched them.
2978
__doc__ = """List ignored files and the patterns that matched them.
2704
2980
List all the ignored files and the ignore pattern that caused the file to
2728
3004
class cmd_lookup_revision(Command):
2729
"""Lookup the revision-id from a revision-number
3005
__doc__ = """Lookup the revision-id from a revision-number
2732
3008
bzr lookup-revision 33
2735
3011
takes_args = ['revno']
3012
takes_options = ['directory']
2737
3014
@display_command
2738
def run(self, revno):
3015
def run(self, revno, directory=u'.'):
2740
3017
revno = int(revno)
2741
3018
except ValueError:
2742
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2744
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
3019
raise errors.BzrCommandError(gettext("not a valid revision-number: %r")
3021
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
3022
self.outf.write("%s\n" % revid)
2747
3025
class cmd_export(Command):
2748
"""Export current or past revision to a destination directory or archive.
3026
__doc__ = """Export current or past revision to a destination directory or archive.
2750
3028
If no revision is specified this exports the last committed revision.
2785
3064
help="Name of the root directory inside the exported file."),
3065
Option('per-file-timestamps',
3066
help='Set modification time of files to that of the last '
3067
'revision in which it was changed.'),
2787
3069
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2788
root=None, filters=False):
3070
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2789
3071
from bzrlib.export import export
2791
3073
if branch_or_subdir is None:
2792
tree = WorkingTree.open_containing(u'.')[0]
3074
tree = WorkingTree.open_containing(directory)[0]
2793
3075
b = tree.branch
2799
3081
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2801
export(rev_tree, dest, format, root, subdir, filtered=filters)
3083
export(rev_tree, dest, format, root, subdir, filtered=filters,
3084
per_file_timestamps=per_file_timestamps)
2802
3085
except errors.NoSuchExportFormat, e:
2803
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3086
raise errors.BzrCommandError(gettext('Unsupported export format: %s') % e.format)
2806
3089
class cmd_cat(Command):
2807
"""Write the contents of a file as of a given revision to standard output.
3090
__doc__ = """Write the contents of a file as of a given revision to standard output.
2809
3092
If no revision is nominated, the last revision is used.
2825
3108
@display_command
2826
3109
def run(self, filename, revision=None, name_from_revision=False,
3110
filters=False, directory=None):
2828
3111
if revision is not None and len(revision) != 1:
2829
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2830
" one revision specifier")
3112
raise errors.BzrCommandError(gettext("bzr cat --revision takes exactly"
3113
" one revision specifier"))
2831
3114
tree, branch, relpath = \
2832
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2834
self.add_cleanup(branch.unlock)
3115
_open_directory_or_containing_tree_or_branch(filename, directory)
3116
self.add_cleanup(branch.lock_read().unlock)
2835
3117
return self._run(tree, branch, relpath, filename, revision,
2836
3118
name_from_revision, filters)
2840
3122
if tree is None:
2841
3123
tree = b.basis_tree()
2842
3124
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2843
rev_tree.lock_read()
2844
self.add_cleanup(rev_tree.unlock)
3125
self.add_cleanup(rev_tree.lock_read().unlock)
2846
3127
old_file_id = rev_tree.path2id(relpath)
3129
# TODO: Split out this code to something that generically finds the
3130
# best id for a path across one or more trees; it's like
3131
# find_ids_across_trees but restricted to find just one. -- mbp
2848
3133
if name_from_revision:
2849
3134
# Try in revision if requested
2850
3135
if old_file_id is None:
2851
raise errors.BzrCommandError(
2852
"%r is not present in revision %s" % (
3136
raise errors.BzrCommandError(gettext(
3137
"{0!r} is not present in revision {1}").format(
2853
3138
filename, rev_tree.get_revision_id()))
2855
content = rev_tree.get_file_text(old_file_id)
3140
actual_file_id = old_file_id
2857
3142
cur_file_id = tree.path2id(relpath)
2859
if cur_file_id is not None:
2860
# Then try with the actual file id
2862
content = rev_tree.get_file_text(cur_file_id)
2864
except errors.NoSuchId:
2865
# The actual file id didn't exist at that time
2867
if not found and old_file_id is not None:
2868
# Finally try with the old file id
2869
content = rev_tree.get_file_text(old_file_id)
2872
# Can't be found anywhere
2873
raise errors.BzrCommandError(
2874
"%r is not present in revision %s" % (
3143
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3144
actual_file_id = cur_file_id
3145
elif old_file_id is not None:
3146
actual_file_id = old_file_id
3148
raise errors.BzrCommandError(gettext(
3149
"{0!r} is not present in revision {1}").format(
2875
3150
filename, rev_tree.get_revision_id()))
2877
from bzrlib.filters import (
2878
ContentFilterContext,
2879
filtered_output_bytes,
2881
filters = rev_tree._content_filter_stack(relpath)
2882
chunks = content.splitlines(True)
2883
content = filtered_output_bytes(chunks, filters,
2884
ContentFilterContext(relpath, rev_tree))
2886
self.outf.writelines(content)
3152
from bzrlib.filter_tree import ContentFilterTree
3153
filter_tree = ContentFilterTree(rev_tree,
3154
rev_tree._content_filter_stack)
3155
content = filter_tree.get_file_text(actual_file_id)
2889
self.outf.write(content)
3157
content = rev_tree.get_file_text(actual_file_id)
3159
self.outf.write(content)
2892
3162
class cmd_local_time_offset(Command):
2893
"""Show the offset in seconds from GMT to local time."""
3163
__doc__ = """Show the offset in seconds from GMT to local time."""
2895
3165
@display_command
2897
print osutils.local_time_offset()
3167
self.outf.write("%s\n" % osutils.local_time_offset())
2901
3171
class cmd_commit(Command):
2902
"""Commit changes into a new revision.
3172
__doc__ = """Commit changes into a new revision.
2904
3174
An explanatory message needs to be given for each commit. This is
2905
3175
often done by using the --message option (getting the message from the
2953
3223
to trigger updates to external systems like bug trackers. The --fixes
2954
3224
option can be used to record the association between a revision and
2955
3225
one or more bugs. See ``bzr help bugs`` for details.
2957
A selective commit may fail in some cases where the committed
2958
tree would be invalid. Consider::
2963
bzr commit foo -m "committing foo"
2964
bzr mv foo/bar foo/baz
2967
bzr commit foo/bar -m "committing bar but not baz"
2969
In the example above, the last commit will fail by design. This gives
2970
the user the opportunity to decide whether they want to commit the
2971
rename at the same time, separately first, or not at all. (As a general
2972
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2974
# TODO: Run hooks on tree to-be-committed, and after commit.
2976
# TODO: Strict commit that fails if there are deleted files.
2977
# (what does "deleted files" mean ??)
2979
# TODO: Give better message for -s, --summary, used by tla people
2981
# XXX: verbose currently does nothing
2983
3228
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
2984
3229
takes_args = ['selected*']
3013
3258
"the master branch until a normal commit "
3014
3259
"is performed."
3261
Option('show-diff', short_name='p',
3017
3262
help='When no message is supplied, show the diff along'
3018
3263
' with the status summary in the message editor.'),
3265
help='When committing to a foreign version control '
3266
'system do not push data that can not be natively '
3020
3269
aliases = ['ci', 'checkin']
3022
3271
def _iter_bug_fix_urls(self, fixes, branch):
3272
default_bugtracker = None
3023
3273
# Configure the properties for bug fixing attributes.
3024
3274
for fixed_bug in fixes:
3025
3275
tokens = fixed_bug.split(':')
3026
if len(tokens) != 2:
3027
raise errors.BzrCommandError(
3276
if len(tokens) == 1:
3277
if default_bugtracker is None:
3278
branch_config = branch.get_config()
3279
default_bugtracker = branch_config.get_user_option(
3281
if default_bugtracker is None:
3282
raise errors.BzrCommandError(gettext(
3283
"No tracker specified for bug %s. Use the form "
3284
"'tracker:id' or specify a default bug tracker "
3285
"using the `bugtracker` option.\nSee "
3286
"\"bzr help bugs\" for more information on this "
3287
"feature. Commit refused.") % fixed_bug)
3288
tag = default_bugtracker
3290
elif len(tokens) != 2:
3291
raise errors.BzrCommandError(gettext(
3028
3292
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3029
3293
"See \"bzr help bugs\" for more information on this "
3030
"feature.\nCommit refused." % fixed_bug)
3031
tag, bug_id = tokens
3294
"feature.\nCommit refused.") % fixed_bug)
3296
tag, bug_id = tokens
3033
3298
yield bugtracker.get_bug_url(tag, branch, bug_id)
3034
3299
except errors.UnknownBugTrackerAbbreviation:
3035
raise errors.BzrCommandError(
3036
'Unrecognized bug %s. Commit refused.' % fixed_bug)
3300
raise errors.BzrCommandError(gettext(
3301
'Unrecognized bug %s. Commit refused.') % fixed_bug)
3037
3302
except errors.MalformedBugIdentifier, e:
3038
raise errors.BzrCommandError(
3039
"%s\nCommit refused." % (str(e),))
3303
raise errors.BzrCommandError(gettext(
3304
"%s\nCommit refused.") % (str(e),))
3041
3306
def run(self, message=None, file=None, verbose=False, selected_list=None,
3042
3307
unchanged=False, strict=False, local=False, fixes=None,
3043
author=None, show_diff=False, exclude=None, commit_time=None):
3308
author=None, show_diff=False, exclude=None, commit_time=None,
3044
3310
from bzrlib.errors import (
3045
3311
PointlessCommit,
3046
3312
ConflictsInTree,
3058
3325
commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3059
3326
except ValueError, e:
3060
raise errors.BzrCommandError(
3061
"Could not parse --commit-time: " + str(e))
3063
# TODO: Need a blackbox test for invoking the external editor; may be
3064
# slightly problematic to run this cross-platform.
3066
# TODO: do more checks that the commit will succeed before
3067
# spending the user's valuable time typing a commit message.
3327
raise errors.BzrCommandError(gettext(
3328
"Could not parse --commit-time: " + str(e)))
3069
3330
properties = {}
3071
tree, selected_list = tree_files(selected_list)
3332
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3072
3333
if selected_list == ['']:
3073
3334
# workaround - commit of root of tree should be exactly the same
3074
3335
# as just default commit in that tree, and succeed even though
3099
3360
'(use --file "%(f)s" to take commit message from that file)'
3100
3361
% { 'f': message })
3101
3362
ui.ui_factory.show_warning(warning_msg)
3364
message = message.replace('\r\n', '\n')
3365
message = message.replace('\r', '\n')
3367
raise errors.BzrCommandError(gettext(
3368
"please specify either --message or --file"))
3103
3370
def get_message(commit_obj):
3104
3371
"""Callback to get commit message"""
3105
my_message = message
3106
if my_message is not None and '\r' in my_message:
3107
my_message = my_message.replace('\r\n', '\n')
3108
my_message = my_message.replace('\r', '\n')
3109
if my_message is None and not file:
3110
t = make_commit_message_template_encoded(tree,
3375
my_message = f.read().decode(osutils.get_user_encoding())
3378
elif message is not None:
3379
my_message = message
3381
# No message supplied: make one up.
3382
# text is the status of the tree
3383
text = make_commit_message_template_encoded(tree,
3111
3384
selected_list, diff=show_diff,
3112
3385
output_encoding=osutils.get_user_encoding())
3113
start_message = generate_commit_message_template(commit_obj)
3114
my_message = edit_commit_message_encoded(t,
3115
start_message=start_message)
3116
if my_message is None:
3117
raise errors.BzrCommandError("please specify a commit"
3118
" message with either --message or --file")
3119
elif my_message and file:
3120
raise errors.BzrCommandError(
3121
"please specify either --message or --file")
3123
my_message = codecs.open(file, 'rt',
3124
osutils.get_user_encoding()).read()
3125
if my_message == "":
3126
raise errors.BzrCommandError("empty commit message specified")
3386
# start_message is the template generated from hooks
3387
# XXX: Warning - looks like hooks return unicode,
3388
# make_commit_message_template_encoded returns user encoding.
3389
# We probably want to be using edit_commit_message instead to
3391
my_message = set_commit_message(commit_obj)
3392
if my_message is None:
3393
start_message = generate_commit_message_template(commit_obj)
3394
my_message = edit_commit_message_encoded(text,
3395
start_message=start_message)
3396
if my_message is None:
3397
raise errors.BzrCommandError(gettext("please specify a commit"
3398
" message with either --message or --file"))
3399
if my_message == "":
3400
raise errors.BzrCommandError(gettext("Empty commit message specified."
3401
" Please specify a commit message with either"
3402
" --message or --file or leave a blank message"
3403
" with --message \"\"."))
3127
3404
return my_message
3129
3406
# The API permits a commit with a filter of [] to mean 'select nothing'
3137
3414
reporter=None, verbose=verbose, revprops=properties,
3138
3415
authors=author, timestamp=commit_stamp,
3139
3416
timezone=offset,
3140
exclude=safe_relpath_files(tree, exclude))
3417
exclude=tree.safe_relpath_files(exclude),
3141
3419
except PointlessCommit:
3142
# FIXME: This should really happen before the file is read in;
3143
# perhaps prepare the commit; get the message; then actually commit
3144
raise errors.BzrCommandError("No changes to commit."
3145
" Use --unchanged to commit anyhow.")
3420
raise errors.BzrCommandError(gettext("No changes to commit."
3421
" Please 'bzr add' the files you want to commit, or use"
3422
" --unchanged to force an empty commit."))
3146
3423
except ConflictsInTree:
3147
raise errors.BzrCommandError('Conflicts detected in working '
3424
raise errors.BzrCommandError(gettext('Conflicts detected in working '
3148
3425
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3150
3427
except StrictCommitFailed:
3151
raise errors.BzrCommandError("Commit refused because there are"
3152
" unknown files in the working tree.")
3428
raise errors.BzrCommandError(gettext("Commit refused because there are"
3429
" unknown files in the working tree."))
3153
3430
except errors.BoundBranchOutOfDate, e:
3154
raise errors.BzrCommandError(str(e) + "\n"
3155
'To commit to master branch, run update and then commit.\n'
3156
'You can also pass --local to commit to continue working '
3431
e.extra_help = (gettext("\n"
3432
'To commit to master branch, run update and then commit.\n'
3433
'You can also pass --local to commit to continue working '
3160
3438
class cmd_check(Command):
3161
"""Validate working tree structure, branch consistency and repository history.
3439
__doc__ = """Validate working tree structure, branch consistency and repository history.
3163
3441
This command checks various invariants about branch and repository storage
3164
3442
to detect data corruption or bzr bugs.
3230
3508
class cmd_upgrade(Command):
3231
"""Upgrade branch storage to current format.
3233
The check command or bzr developers may sometimes advise you to run
3234
this command. When the default format has changed you may also be warned
3235
during other operations to upgrade.
3509
__doc__ = """Upgrade a repository, branch or working tree to a newer format.
3511
When the default format has changed after a major new release of
3512
Bazaar, you may be informed during certain operations that you
3513
should upgrade. Upgrading to a newer format may improve performance
3514
or make new features available. It may however limit interoperability
3515
with older repositories or with older versions of Bazaar.
3517
If you wish to upgrade to a particular format rather than the
3518
current default, that can be specified using the --format option.
3519
As a consequence, you can use the upgrade command this way to
3520
"downgrade" to an earlier format, though some conversions are
3521
a one way process (e.g. changing from the 1.x default to the
3522
2.x default) so downgrading is not always possible.
3524
A backup.bzr.~#~ directory is created at the start of the conversion
3525
process (where # is a number). By default, this is left there on
3526
completion. If the conversion fails, delete the new .bzr directory
3527
and rename this one back in its place. Use the --clean option to ask
3528
for the backup.bzr directory to be removed on successful conversion.
3529
Alternatively, you can delete it by hand if everything looks good
3532
If the location given is a shared repository, dependent branches
3533
are also converted provided the repository converts successfully.
3534
If the conversion of a branch fails, remaining branches are still
3537
For more information on upgrades, see the Bazaar Upgrade Guide,
3538
http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
3238
_see_also = ['check']
3541
_see_also = ['check', 'reconcile', 'formats']
3239
3542
takes_args = ['url?']
3240
3543
takes_options = [
3241
RegistryOption('format',
3242
help='Upgrade to a specific format. See "bzr help'
3243
' formats" for details.',
3244
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3245
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3246
value_switches=True, title='Branch format'),
3544
RegistryOption('format',
3545
help='Upgrade to a specific format. See "bzr help'
3546
' formats" for details.',
3547
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3548
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3549
value_switches=True, title='Branch format'),
3551
help='Remove the backup.bzr directory if successful.'),
3553
help="Show what would be done, but don't actually do anything."),
3249
def run(self, url='.', format=None):
3556
def run(self, url='.', format=None, clean=False, dry_run=False):
3250
3557
from bzrlib.upgrade import upgrade
3251
upgrade(url, format)
3558
exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3560
if len(exceptions) == 1:
3561
# Compatibility with historical behavior
3254
3567
class cmd_whoami(Command):
3255
"""Show or set bzr user id.
3568
__doc__ = """Show or set bzr user id.
3258
3571
Show the email of the current user::
3273
3587
encoding_type = 'replace'
3275
3589
@display_command
3276
def run(self, email=False, branch=False, name=None):
3590
def run(self, email=False, branch=False, name=None, directory=None):
3277
3591
if name is None:
3278
# use branch if we're inside one; otherwise global config
3280
c = Branch.open_containing('.')[0].get_config()
3281
except errors.NotBranchError:
3282
c = config.GlobalConfig()
3592
if directory is None:
3593
# use branch if we're inside one; otherwise global config
3595
c = Branch.open_containing(u'.')[0].get_config()
3596
except errors.NotBranchError:
3597
c = _mod_config.GlobalConfig()
3599
c = Branch.open(directory).get_config()
3284
3601
self.outf.write(c.user_email() + '\n')
3286
3603
self.outf.write(c.username() + '\n')
3607
raise errors.BzrCommandError(gettext("--email can only be used to display existing "
3289
3610
# display a warning if an email address isn't included in the given name.
3291
config.extract_email_address(name)
3612
_mod_config.extract_email_address(name)
3292
3613
except errors.NoEmailInUsername, e:
3293
3614
warning('"%s" does not seem to contain an email address. '
3294
3615
'This is allowed, but not recommended.', name)
3296
3617
# use global config unless --branch given
3298
c = Branch.open_containing('.')[0].get_config()
3619
if directory is None:
3620
c = Branch.open_containing(u'.')[0].get_config()
3622
c = Branch.open(directory).get_config()
3300
c = config.GlobalConfig()
3624
c = _mod_config.GlobalConfig()
3301
3625
c.set_user_option('email', name)
3304
3628
class cmd_nick(Command):
3305
"""Print or set the branch nickname.
3629
__doc__ = """Print or set the branch nickname.
3307
3631
If unset, the tree root directory name is used as the nickname.
3308
3632
To print the current nickname, execute with no argument.
3366
3691
def remove_alias(self, alias_name):
3367
3692
if alias_name is None:
3368
raise errors.BzrCommandError(
3369
'bzr alias --remove expects an alias to remove.')
3693
raise errors.BzrCommandError(gettext(
3694
'bzr alias --remove expects an alias to remove.'))
3370
3695
# If alias is not found, print something like:
3371
3696
# unalias: foo: not found
3372
c = config.GlobalConfig()
3697
c = _mod_config.GlobalConfig()
3373
3698
c.unset_alias(alias_name)
3375
3700
@display_command
3376
3701
def print_aliases(self):
3377
3702
"""Print out the defined aliases in a similar format to bash."""
3378
aliases = config.GlobalConfig().get_aliases()
3703
aliases = _mod_config.GlobalConfig().get_aliases()
3379
3704
for key, value in sorted(aliases.iteritems()):
3380
3705
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3519
3848
def run(self, testspecs_list=None, verbose=False, one=False,
3520
3849
transport=None, benchmark=None,
3521
lsprof_timed=None, cache_dir=None,
3522
3851
first=False, list_only=False,
3523
3852
randomize=None, exclude=None, strict=False,
3524
3853
load_list=None, debugflag=None, starting_with=None, subunit=False,
3525
parallel=None, lsprof_tests=False):
3526
from bzrlib.tests import selftest
3527
import bzrlib.benchmarks as benchmarks
3528
from bzrlib.benchmarks import tree_creator
3530
# Make deprecation warnings visible, unless -Werror is set
3531
symbol_versioning.activate_deprecation_warnings(override=False)
3533
if cache_dir is not None:
3534
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3854
parallel=None, lsprof_tests=False,
3856
from bzrlib import tests
3535
3858
if testspecs_list is not None:
3536
3859
pattern = '|'.join(testspecs_list)
3541
3864
from bzrlib.tests import SubUnitBzrRunner
3542
3865
except ImportError:
3543
raise errors.BzrCommandError("subunit not available. subunit "
3544
"needs to be installed to use --subunit.")
3866
raise errors.BzrCommandError(gettext("subunit not available. subunit "
3867
"needs to be installed to use --subunit."))
3545
3868
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3869
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3870
# stdout, which would corrupt the subunit stream.
3871
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3872
# following code can be deleted when it's sufficiently deployed
3873
# -- vila/mgz 20100514
3874
if (sys.platform == "win32"
3875
and getattr(sys.stdout, 'fileno', None) is not None):
3877
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3547
3879
self.additional_selftest_args.setdefault(
3548
3880
'suite_decorators', []).append(parallel)
3550
test_suite_factory = benchmarks.test_suite
3551
# Unless user explicitly asks for quiet, be verbose in benchmarks
3552
verbose = not is_quiet()
3553
# TODO: should possibly lock the history file...
3554
benchfile = open(".perf_history", "at", buffering=1)
3555
self.add_cleanup(benchfile.close)
3882
raise errors.BzrCommandError(gettext(
3883
"--benchmark is no longer supported from bzr 2.2; "
3884
"use bzr-usertest instead"))
3885
test_suite_factory = None
3887
exclude_pattern = None
3557
test_suite_factory = None
3889
exclude_pattern = '(' + '|'.join(exclude) + ')'
3891
self._disable_fsync()
3559
3892
selftest_kwargs = {"verbose": verbose,
3560
3893
"pattern": pattern,
3561
3894
"stop_on_failure": one,
3563
3896
"test_suite_factory": test_suite_factory,
3564
3897
"lsprof_timed": lsprof_timed,
3565
3898
"lsprof_tests": lsprof_tests,
3566
"bench_history": benchfile,
3567
3899
"matching_tests_first": first,
3568
3900
"list_only": list_only,
3569
3901
"random_seed": randomize,
3570
"exclude_pattern": exclude,
3902
"exclude_pattern": exclude_pattern,
3571
3903
"strict": strict,
3572
3904
"load_list": load_list,
3573
3905
"debug_flags": debugflag,
3574
3906
"starting_with": starting_with
3576
3908
selftest_kwargs.update(self.additional_selftest_args)
3577
result = selftest(**selftest_kwargs)
3910
# Make deprecation warnings visible, unless -Werror is set
3911
cleanup = symbol_versioning.activate_deprecation_warnings(
3914
result = tests.selftest(**selftest_kwargs)
3578
3917
return int(not result)
3919
def _disable_fsync(self):
3920
"""Change the 'os' functionality to not synchronize."""
3921
self._orig_fsync = getattr(os, 'fsync', None)
3922
if self._orig_fsync is not None:
3923
os.fsync = lambda filedes: None
3924
self._orig_fdatasync = getattr(os, 'fdatasync', None)
3925
if self._orig_fdatasync is not None:
3926
os.fdatasync = lambda filedes: None
3581
3929
class cmd_version(Command):
3582
"""Show version of bzr."""
3930
__doc__ = """Show version of bzr."""
3584
3932
encoding_type = 'replace'
3585
3933
takes_options = [
3619
3967
branch1 = Branch.open_containing(branch)[0]
3620
3968
branch2 = Branch.open_containing(other)[0]
3622
self.add_cleanup(branch1.unlock)
3624
self.add_cleanup(branch2.unlock)
3969
self.add_cleanup(branch1.lock_read().unlock)
3970
self.add_cleanup(branch2.lock_read().unlock)
3625
3971
last1 = ensure_null(branch1.last_revision())
3626
3972
last2 = ensure_null(branch2.last_revision())
3628
3974
graph = branch1.repository.get_graph(branch2.repository)
3629
3975
base_rev_id = graph.find_unique_lca(last1, last2)
3631
print 'merge base is revision %s' % base_rev_id
3977
self.outf.write(gettext('merge base is revision %s\n') % base_rev_id)
3634
3980
class cmd_merge(Command):
3635
"""Perform a three-way merge.
3981
__doc__ = """Perform a three-way merge.
3637
3983
The source of the merge can be specified either in the form of a branch,
3638
3984
or in the form of a path to a file containing a merge directive generated
3639
3985
with bzr send. If neither is specified, the default is the upstream branch
3640
or the branch most recently merged using --remember.
3642
When merging a branch, by default the tip will be merged. To pick a different
3643
revision, pass --revision. If you specify two values, the first will be used as
3644
BASE and the second one as OTHER. Merging individual revisions, or a subset of
3645
available revisions, like this is commonly referred to as "cherrypicking".
3647
Revision numbers are always relative to the branch being merged.
3649
By default, bzr will try to merge in all new work from the other
3650
branch, automatically determining an appropriate base. If this
3651
fails, you may need to give an explicit base.
3986
or the branch most recently merged using --remember. The source of the
3987
merge may also be specified in the form of a path to a file in another
3988
branch: in this case, only the modifications to that file are merged into
3989
the current working tree.
3991
When merging from a branch, by default bzr will try to merge in all new
3992
work from the other branch, automatically determining an appropriate base
3993
revision. If this fails, you may need to give an explicit base.
3995
To pick a different ending revision, pass "--revision OTHER". bzr will
3996
try to merge in all new work up to and including revision OTHER.
3998
If you specify two values, "--revision BASE..OTHER", only revisions BASE
3999
through OTHER, excluding BASE but including OTHER, will be merged. If this
4000
causes some revisions to be skipped, i.e. if the destination branch does
4001
not already contain revision BASE, such a merge is commonly referred to as
4002
a "cherrypick". Unlike a normal merge, Bazaar does not currently track
4003
cherrypicks. The changes look like a normal commit, and the history of the
4004
changes from the other branch is not stored in the commit.
4006
Revision numbers are always relative to the source branch.
3653
4008
Merge will do its best to combine the changes in two branches, but there
3654
4009
are some kinds of problems only a human can fix. When it encounters those,
3658
4013
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3660
If there is no default branch set, the first merge will set it. After
3661
that, you can omit the branch to use the default. To change the
3662
default, use --remember. The value will only be saved if the remote
3663
location can be accessed.
4015
If there is no default branch set, the first merge will set it (use
4016
--no-remember to avoid setting it). After that, you can omit the branch
4017
to use the default. To change the default, use --remember. The value will
4018
only be saved if the remote location can be accessed.
3665
4020
The results of the merge are placed into the destination working
3666
4021
directory, where they can be reviewed (with bzr diff), tested, and then
3667
4022
committed to record the result of the merge.
3669
4024
merge refuses to run if there are any uncommitted changes, unless
3670
--force is given. The --force option can also be used to create a
4025
--force is given. If --force is given, then the changes from the source
4026
will be merged with the current working tree, including any uncommitted
4027
changes in the tree. The --force option can also be used to create a
3671
4028
merge revision which has more than two parents.
3673
4030
If one would like to merge changes from the working tree of the other
3775
4132
mergeable = None
3777
4134
if uncommitted:
3778
raise errors.BzrCommandError('Cannot use --uncommitted'
3779
' with bundles or merge directives.')
4135
raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4136
' with bundles or merge directives.'))
3781
4138
if revision is not None:
3782
raise errors.BzrCommandError(
3783
'Cannot use -r with merge directives or bundles')
4139
raise errors.BzrCommandError(gettext(
4140
'Cannot use -r with merge directives or bundles'))
3784
4141
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3785
4142
mergeable, None)
3787
4144
if merger is None and uncommitted:
3788
4145
if revision is not None and len(revision) > 0:
3789
raise errors.BzrCommandError('Cannot use --uncommitted and'
3790
' --revision at the same time.')
4146
raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4147
' --revision at the same time.'))
3791
4148
merger = self.get_merger_from_uncommitted(tree, location, None)
3792
4149
allow_pending = False
3801
4158
self.sanity_check_merger(merger)
3802
4159
if (merger.base_rev_id == merger.other_rev_id and
3803
4160
merger.other_rev_id is not None):
3804
note('Nothing to do.')
4161
# check if location is a nonexistent file (and not a branch) to
4162
# disambiguate the 'Nothing to do'
4163
if merger.interesting_files:
4164
if not merger.other_tree.has_filename(
4165
merger.interesting_files[0]):
4166
note(gettext("merger: ") + str(merger))
4167
raise errors.PathsDoNotExist([location])
4168
note(gettext('Nothing to do.'))
4170
if pull and not preview:
3807
4171
if merger.interesting_files is not None:
3808
raise errors.BzrCommandError('Cannot pull individual files')
4172
raise errors.BzrCommandError(gettext('Cannot pull individual files'))
3809
4173
if (merger.base_rev_id == tree.last_revision()):
3810
4174
result = tree.pull(merger.other_branch, False,
3811
4175
merger.other_rev_id)
3812
4176
result.report(self.outf)
3814
4178
if merger.this_basis is None:
3815
raise errors.BzrCommandError(
4179
raise errors.BzrCommandError(gettext(
3816
4180
"This branch has no commits."
3817
" (perhaps you would prefer 'bzr pull')")
4181
" (perhaps you would prefer 'bzr pull')"))
3819
4183
return self._do_preview(merger)
3820
4184
elif interactive:
3916
4282
if other_revision_id is None:
3917
4283
other_revision_id = _mod_revision.ensure_null(
3918
4284
other_branch.last_revision())
3919
# Remember where we merge from
3920
if ((remember or tree.branch.get_submit_branch() is None) and
3921
user_location is not None):
4285
# Remember where we merge from. We need to remember if:
4286
# - user specify a location (and we don't merge from the parent
4288
# - user ask to remember or there is no previous location set to merge
4289
# from and user didn't ask to *not* remember
4290
if (user_location is not None
4292
or (remember is None
4293
and tree.branch.get_submit_branch() is None)))):
3922
4294
tree.branch.set_submit_branch(other_branch.base)
3923
_merge_tags_if_possible(other_branch, tree.branch)
4295
# Merge tags (but don't set them in the master branch yet, the user
4296
# might revert this merge). Commit will propagate them.
4297
_merge_tags_if_possible(other_branch, tree.branch, ignore_master=True)
3924
4298
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3925
4299
other_revision_id, base_revision_id, other_branch, base_branch)
3926
4300
if other_path != '':
3985
4359
stored_location_type = "parent"
3986
4360
mutter("%s", stored_location)
3987
4361
if stored_location is None:
3988
raise errors.BzrCommandError("No location specified or remembered")
4362
raise errors.BzrCommandError(gettext("No location specified or remembered"))
3989
4363
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3990
note(u"%s remembered %s location %s", verb_string,
3991
stored_location_type, display_url)
4364
note(gettext("{0} remembered {1} location {2}").format(verb_string,
4365
stored_location_type, display_url))
3992
4366
return stored_location
3995
4369
class cmd_remerge(Command):
4370
__doc__ = """Redo a merge.
3998
4372
Use this if you want to try a different merge technique while resolving
3999
4373
conflicts. Some merge techniques are better than others, and remerge
4025
4399
def run(self, file_list=None, merge_type=None, show_base=False,
4026
4400
reprocess=False):
4401
from bzrlib.conflicts import restore
4027
4402
if merge_type is None:
4028
4403
merge_type = _mod_merge.Merge3Merger
4029
tree, file_list = tree_files(file_list)
4031
self.add_cleanup(tree.unlock)
4404
tree, file_list = WorkingTree.open_containing_paths(file_list)
4405
self.add_cleanup(tree.lock_write().unlock)
4032
4406
parents = tree.get_parent_ids()
4033
4407
if len(parents) != 2:
4034
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4408
raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4035
4409
" merges. Not cherrypicking or"
4037
4411
repository = tree.branch.repository
4038
4412
interesting_ids = None
4039
4413
new_conflicts = []
4089
4463
class cmd_revert(Command):
4090
"""Revert files to a previous revision.
4464
__doc__ = """Revert files to a previous revision.
4092
4466
Giving a list of files will revert only those files. Otherwise, all files
4093
4467
will be reverted. If the revision is not specified with '--revision', the
4094
4468
last committed revision is used.
4096
4470
To remove only some changes, without reverting to a prior version, use
4097
merge instead. For example, "merge . --revision -2..-3" will remove the
4098
changes introduced by -2, without affecting the changes introduced by -1.
4099
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
4471
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4472
will remove the changes introduced by the second last commit (-2), without
4473
affecting the changes introduced by the last commit (-1). To remove
4474
certain changes on a hunk-by-hunk basis, see the shelve command.
4101
4476
By default, any files that have been manually changed will be backed up
4102
4477
first. (Files changed only by merge are not backed up.) Backup files have
4267
4644
theirs_only=False,
4268
4645
log_format=None, long=False, short=False, line=False,
4269
4646
show_ids=False, verbose=False, this=False, other=False,
4270
include_merges=False, revision=None, my_revision=None):
4647
include_merged=None, revision=None, my_revision=None,
4649
include_merges=symbol_versioning.DEPRECATED_PARAMETER):
4271
4650
from bzrlib.missing import find_unmerged, iter_log_revisions
4272
4651
def message(s):
4273
4652
if not is_quiet():
4274
4653
self.outf.write(s)
4655
if symbol_versioning.deprecated_passed(include_merges):
4656
ui.ui_factory.show_user_warning(
4657
'deprecated_command_option',
4658
deprecated_name='--include-merges',
4659
recommended_name='--include-merged',
4660
deprecated_in_version='2.5',
4661
command=self.invoked_as)
4662
if include_merged is None:
4663
include_merged = include_merges
4665
raise errors.BzrCommandError(gettext(
4666
'{0} and {1} are mutually exclusive').format(
4667
'--include-merges', '--include-merged'))
4668
if include_merged is None:
4669
include_merged = False
4277
4671
mine_only = this
4286
4680
elif theirs_only:
4287
4681
restrict = 'remote'
4289
local_branch = Branch.open_containing(u".")[0]
4683
local_branch = Branch.open_containing(directory)[0]
4684
self.add_cleanup(local_branch.lock_read().unlock)
4290
4686
parent = local_branch.get_parent()
4291
4687
if other_branch is None:
4292
4688
other_branch = parent
4293
4689
if other_branch is None:
4294
raise errors.BzrCommandError("No peer location known"
4690
raise errors.BzrCommandError(gettext("No peer location known"
4296
4692
display_url = urlutils.unescape_for_display(parent,
4297
4693
self.outf.encoding)
4298
message("Using saved parent location: "
4299
+ display_url + "\n")
4694
message(gettext("Using saved parent location: {0}\n").format(
4301
4697
remote_branch = Branch.open(other_branch)
4302
4698
if remote_branch.base == local_branch.base:
4303
4699
remote_branch = local_branch
4701
self.add_cleanup(remote_branch.lock_read().unlock)
4305
local_branch.lock_read()
4306
self.add_cleanup(local_branch.unlock)
4307
4703
local_revid_range = _revision_range_to_revid_range(
4308
4704
_get_revision_range(my_revision, local_branch,
4311
remote_branch.lock_read()
4312
self.add_cleanup(remote_branch.unlock)
4313
4707
remote_revid_range = _revision_range_to_revid_range(
4314
4708
_get_revision_range(revision,
4315
4709
remote_branch, self.name()))
4355
4753
if mine_only and not local_extra:
4356
4754
# We checked local, and found nothing extra
4357
message('This branch is up to date.\n')
4755
message(gettext('This branch has no new revisions.\n'))
4358
4756
elif theirs_only and not remote_extra:
4359
4757
# We checked remote, and found nothing extra
4360
message('Other branch is up to date.\n')
4758
message(gettext('Other branch has no new revisions.\n'))
4361
4759
elif not (mine_only or theirs_only or local_extra or
4363
4761
# We checked both branches, and neither one had extra
4365
message("Branches are up to date.\n")
4763
message(gettext("Branches are up to date.\n"))
4366
4764
self.cleanup_now()
4367
4765
if not status_code and parent is None and other_branch is not None:
4368
local_branch.lock_write()
4369
self.add_cleanup(local_branch.unlock)
4766
self.add_cleanup(local_branch.lock_write().unlock)
4370
4767
# handle race conditions - a parent might be set while we run.
4371
4768
if local_branch.get_parent() is None:
4372
4769
local_branch.set_parent(remote_branch.base)
4376
4773
class cmd_pack(Command):
4377
"""Compress the data within a repository."""
4774
__doc__ = """Compress the data within a repository.
4776
This operation compresses the data within a bazaar repository. As
4777
bazaar supports automatic packing of repository, this operation is
4778
normally not required to be done manually.
4780
During the pack operation, bazaar takes a backup of existing repository
4781
data, i.e. pack files. This backup is eventually removed by bazaar
4782
automatically when it is safe to do so. To save disk space by removing
4783
the backed up pack files, the --clean-obsolete-packs option may be
4786
Warning: If you use --clean-obsolete-packs and your machine crashes
4787
during or immediately after repacking, you may be left with a state
4788
where the deletion has been written to disk but the new packs have not
4789
been. In this case the repository may be unusable.
4379
4792
_see_also = ['repositories']
4380
4793
takes_args = ['branch_or_repo?']
4795
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4382
def run(self, branch_or_repo='.'):
4798
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4383
4799
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4385
4801
branch = dir.open_branch()
4386
4802
repository = branch.repository
4387
4803
except errors.NotBranchError:
4388
4804
repository = dir.open_repository()
4805
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4392
4808
class cmd_plugins(Command):
4393
"""List the installed plugins.
4809
__doc__ = """List the installed plugins.
4395
4811
This command displays the list of installed plugins including
4396
4812
version of plugin and a short description of each.
4413
4829
@display_command
4414
4830
def run(self, verbose=False):
4415
import bzrlib.plugin
4416
from inspect import getdoc
4418
for name, plugin in bzrlib.plugin.plugins().items():
4419
version = plugin.__version__
4420
if version == 'unknown':
4422
name_ver = '%s %s' % (name, version)
4423
d = getdoc(plugin.module)
4425
doc = d.split('\n')[0]
4427
doc = '(no description)'
4428
result.append((name_ver, doc, plugin.path()))
4429
for name_ver, doc, path in sorted(result):
4831
from bzrlib import plugin
4832
# Don't give writelines a generator as some codecs don't like that
4833
self.outf.writelines(
4834
list(plugin.describe_plugins(show_paths=verbose)))
4437
4837
class cmd_testament(Command):
4438
"""Show testament (signing-form) of a revision."""
4838
__doc__ = """Show testament (signing-form) of a revision."""
4439
4839
takes_options = [
4441
4841
Option('long', help='Produce long-format testament.'),
4484
4883
Option('long', help='Show commit date in annotations.'),
4488
4888
encoding_type = 'exact'
4490
4890
@display_command
4491
4891
def run(self, filename, all=False, long=False, revision=None,
4493
from bzrlib.annotate import annotate_file, annotate_file_tree
4892
show_ids=False, directory=None):
4893
from bzrlib.annotate import (
4494
4896
wt, branch, relpath = \
4495
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4897
_open_directory_or_containing_tree_or_branch(filename, directory)
4496
4898
if wt is not None:
4498
self.add_cleanup(wt.unlock)
4899
self.add_cleanup(wt.lock_read().unlock)
4501
self.add_cleanup(branch.unlock)
4901
self.add_cleanup(branch.lock_read().unlock)
4502
4902
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4504
self.add_cleanup(tree.unlock)
4903
self.add_cleanup(tree.lock_read().unlock)
4904
if wt is not None and revision is None:
4506
4905
file_id = wt.path2id(relpath)
4508
4907
file_id = tree.path2id(relpath)
4509
4908
if file_id is None:
4510
4909
raise errors.NotVersionedError(filename)
4511
file_version = tree.inventory[file_id].revision
4512
4910
if wt is not None and revision is None:
4513
4911
# If there is a tree and we're not annotating historical
4514
4912
# versions, annotate the working tree's content.
4515
4913
annotate_file_tree(wt, file_id, self.outf, long, all,
4516
4914
show_ids=show_ids)
4518
annotate_file(branch, file_version, file_id, long, all, self.outf,
4916
annotate_file_tree(tree, file_id, self.outf, long, all,
4917
show_ids=show_ids, branch=branch)
4522
4920
class cmd_re_sign(Command):
4523
"""Create a digital signature for an existing revision."""
4921
__doc__ = """Create a digital signature for an existing revision."""
4524
4922
# TODO be able to replace existing ones.
4526
4924
hidden = True # is this right ?
4527
4925
takes_args = ['revision_id*']
4528
takes_options = ['revision']
4926
takes_options = ['directory', 'revision']
4530
def run(self, revision_id_list=None, revision=None):
4928
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4531
4929
if revision_id_list is not None and revision is not None:
4532
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4930
raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
4533
4931
if revision_id_list is None and revision is None:
4534
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4535
b = WorkingTree.open_containing(u'.')[0].branch
4537
self.add_cleanup(b.unlock)
4932
raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
4933
b = WorkingTree.open_containing(directory)[0].branch
4934
self.add_cleanup(b.lock_write().unlock)
4538
4935
return self._run(b, revision_id_list, revision)
4540
4937
def _run(self, b, revision_id_list, revision):
4599
4997
_see_also = ['checkouts', 'unbind']
4600
4998
takes_args = ['location?']
4999
takes_options = ['directory']
4603
def run(self, location=None):
4604
b, relpath = Branch.open_containing(u'.')
5001
def run(self, location=None, directory=u'.'):
5002
b, relpath = Branch.open_containing(directory)
4605
5003
if location is None:
4607
5005
location = b.get_old_bound_location()
4608
5006
except errors.UpgradeRequired:
4609
raise errors.BzrCommandError('No location supplied. '
4610
'This format does not remember old locations.')
5007
raise errors.BzrCommandError(gettext('No location supplied. '
5008
'This format does not remember old locations.'))
4612
5010
if location is None:
4613
5011
if b.get_bound_location() is not None:
4614
raise errors.BzrCommandError('Branch is already bound')
5012
raise errors.BzrCommandError(gettext('Branch is already bound'))
4616
raise errors.BzrCommandError('No location supplied '
4617
'and no previous location known')
5014
raise errors.BzrCommandError(gettext('No location supplied '
5015
'and no previous location known'))
4618
5016
b_other = Branch.open(location)
4620
5018
b.bind(b_other)
4621
5019
except errors.DivergedBranches:
4622
raise errors.BzrCommandError('These branches have diverged.'
4623
' Try merging, and then bind again.')
5020
raise errors.BzrCommandError(gettext('These branches have diverged.'
5021
' Try merging, and then bind again.'))
4624
5022
if b.get_config().has_explicit_nickname():
4625
5023
b.nick = b_other.nick
4628
5026
class cmd_unbind(Command):
4629
"""Convert the current checkout into a regular branch.
5027
__doc__ = """Convert the current checkout into a regular branch.
4631
5029
After unbinding, the local branch is considered independent and subsequent
4632
5030
commits will be local only.
4689
5088
b = control.open_branch()
4691
5090
if tree is not None:
4693
self.add_cleanup(tree.unlock)
5091
self.add_cleanup(tree.lock_write().unlock)
4696
self.add_cleanup(b.unlock)
4697
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
5093
self.add_cleanup(b.lock_write().unlock)
5094
return self._run(b, tree, dry_run, verbose, revision, force,
4699
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
5097
def _run(self, b, tree, dry_run, verbose, revision, force, local,
4700
5099
from bzrlib.log import log_formatter, show_log
4701
5100
from bzrlib.uncommit import uncommit
4733
5131
end_revision=last_revno)
4736
ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
5134
self.outf.write(gettext('Dry-run, pretending to remove'
5135
' the above revisions.\n'))
4738
ui.ui_factory.note('The above revision(s) will be removed.')
5137
self.outf.write(gettext('The above revision(s) will be removed.\n'))
4741
if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4742
ui.ui_factory.note('Canceled')
5140
if not ui.ui_factory.confirm_action(
5141
gettext(u'Uncommit these revisions'),
5142
'bzrlib.builtins.uncommit',
5144
self.outf.write(gettext('Canceled\n'))
4745
5147
mutter('Uncommitting from {%s} to {%s}',
4746
5148
last_rev_id, rev_id)
4747
5149
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4748
revno=revno, local=local)
4749
ui.ui_factory.note('You can restore the old tip by running:\n'
4750
' bzr pull . -r revid:%s' % last_rev_id)
5150
revno=revno, local=local, keep_tags=keep_tags)
5151
self.outf.write(gettext('You can restore the old tip by running:\n'
5152
' bzr pull . -r revid:%s\n') % last_rev_id)
4753
5155
class cmd_break_lock(Command):
4754
"""Break a dead lock on a repository, branch or working directory.
5156
__doc__ = """Break a dead lock.
5158
This command breaks a lock on a repository, branch, working directory or
4756
5161
CAUTION: Locks should only be broken when you are sure that the process
4757
5162
holding the lock has been stopped.
4764
5169
bzr break-lock bzr+ssh://example.com/bzr/foo
5170
bzr break-lock --conf ~/.bazaar
4766
5173
takes_args = ['location?']
5176
help='LOCATION is the directory where the config lock is.'),
5178
help='Do not ask for confirmation before breaking the lock.'),
4768
def run(self, location=None, show=False):
5181
def run(self, location=None, config=False, force=False):
4769
5182
if location is None:
4770
5183
location = u'.'
4771
control, relpath = bzrdir.BzrDir.open_containing(location)
4773
control.break_lock()
4774
except NotImplementedError:
5185
ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
5187
{'bzrlib.lockdir.break': True})
5189
conf = _mod_config.LockableConfig(file_name=location)
5192
control, relpath = bzrdir.BzrDir.open_containing(location)
5194
control.break_lock()
5195
except NotImplementedError:
4778
5199
class cmd_wait_until_signalled(Command):
4779
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
5200
__doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4781
5202
This just prints a line to signal when it is ready, then blocks on stdin.
4843
5263
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4844
5264
protocol=None):
4845
from bzrlib.transport import get_transport, transport_server_registry
5265
from bzrlib import transport
4846
5266
if directory is None:
4847
5267
directory = os.getcwd()
4848
5268
if protocol is None:
4849
protocol = transport_server_registry.get()
5269
protocol = transport.transport_server_registry.get()
4850
5270
host, port = self.get_host_and_port(port)
4851
5271
url = urlutils.local_path_to_url(directory)
4852
5272
if not allow_writes:
4853
5273
url = 'readonly+' + url
4854
transport = get_transport(url)
4855
protocol(transport, host, port, inet)
5274
t = transport.get_transport(url)
5275
protocol(t, host, port, inet)
4858
5278
class cmd_join(Command):
4859
"""Combine a tree into its containing tree.
5279
__doc__ = """Combine a tree into its containing tree.
4861
5281
This command requires the target tree to be in a rich-root format.
4891
5311
except errors.BadReferenceTarget, e:
4892
5312
# XXX: Would be better to just raise a nicely printable
4893
5313
# exception from the real origin. Also below. mbp 20070306
4894
raise errors.BzrCommandError("Cannot join %s. %s" %
5314
raise errors.BzrCommandError(
5315
gettext("Cannot join {0}. {1}").format(tree, e.reason))
4898
5318
containing_tree.subsume(sub_tree)
4899
5319
except errors.BadSubsumeSource, e:
4900
raise errors.BzrCommandError("Cannot join %s. %s" %
5320
raise errors.BzrCommandError(
5321
gettext("Cannot join {0}. {1}").format(tree, e.reason))
4904
5324
class cmd_split(Command):
4905
"""Split a subdirectory of a tree into a separate tree.
5325
__doc__ = """Split a subdirectory of a tree into a separate tree.
4907
5327
This command will produce a target tree in a format that supports
4908
5328
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4969
5390
encoding_type = 'exact'
4971
5392
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4972
sign=False, revision=None, mail_to=None, message=None):
5393
sign=False, revision=None, mail_to=None, message=None,
4973
5395
from bzrlib.revision import ensure_null, NULL_REVISION
4974
5396
include_patch, include_bundle = {
4975
5397
'plain': (False, False),
4976
5398
'diff': (True, False),
4977
5399
'bundle': (True, True),
4979
branch = Branch.open('.')
5401
branch = Branch.open(directory)
4980
5402
stored_submit_branch = branch.get_submit_branch()
4981
5403
if submit_branch is None:
4982
5404
submit_branch = stored_submit_branch
5232
5660
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5233
5661
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5663
If no tag name is specified it will be determined through the
5664
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5665
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5236
5669
_see_also = ['commit', 'tags']
5237
takes_args = ['tag_name']
5670
takes_args = ['tag_name?']
5238
5671
takes_options = [
5239
5672
Option('delete',
5240
5673
help='Delete this tag rather than placing it.',
5243
help='Branch in which to place the tag.',
5675
custom_help('directory',
5676
help='Branch in which to place the tag.'),
5247
5677
Option('force',
5248
5678
help='Replace existing tags.',
5253
def run(self, tag_name,
5683
def run(self, tag_name=None,
5259
5689
branch, relpath = Branch.open_containing(directory)
5261
self.add_cleanup(branch.unlock)
5690
self.add_cleanup(branch.lock_write().unlock)
5692
if tag_name is None:
5693
raise errors.BzrCommandError(gettext("No tag specified to delete."))
5263
5694
branch.tags.delete_tag(tag_name)
5264
self.outf.write('Deleted tag %s.\n' % tag_name)
5695
note(gettext('Deleted tag %s.') % tag_name)
5267
5698
if len(revision) != 1:
5268
raise errors.BzrCommandError(
5699
raise errors.BzrCommandError(gettext(
5269
5700
"Tags can only be placed on a single revision, "
5271
5702
revision_id = revision[0].as_revision_id(branch)
5273
5704
revision_id = branch.last_revision()
5274
if (not force) and branch.tags.has_tag(tag_name):
5705
if tag_name is None:
5706
tag_name = branch.automatic_tag_name(revision_id)
5707
if tag_name is None:
5708
raise errors.BzrCommandError(gettext(
5709
"Please specify a tag name."))
5711
existing_target = branch.tags.lookup_tag(tag_name)
5712
except errors.NoSuchTag:
5713
existing_target = None
5714
if not force and existing_target not in (None, revision_id):
5275
5715
raise errors.TagAlreadyExists(tag_name)
5276
branch.tags.set_tag(tag_name, revision_id)
5277
self.outf.write('Created tag %s.\n' % tag_name)
5716
if existing_target == revision_id:
5717
note(gettext('Tag %s already exists for that revision.') % tag_name)
5719
branch.tags.set_tag(tag_name, revision_id)
5720
if existing_target is None:
5721
note(gettext('Created tag %s.') % tag_name)
5723
note(gettext('Updated tag %s.') % tag_name)
5280
5726
class cmd_tags(Command):
5727
__doc__ = """List tags.
5283
5729
This command shows a table of tag names and the revisions they reference.
5286
5732
_see_also = ['tag']
5287
5733
takes_options = [
5289
help='Branch whose tags should be displayed.',
5293
RegistryOption.from_kwargs('sort',
5734
custom_help('directory',
5735
help='Branch whose tags should be displayed.'),
5736
RegistryOption('sort',
5294
5737
'Sort tags by different criteria.', title='Sorting',
5295
alpha='Sort tags lexicographically (default).',
5296
time='Sort tags chronologically.',
5738
lazy_registry=('bzrlib.tag', 'tag_sort_methods')
5302
5744
@display_command
5745
def run(self, directory='.', sort=None, show_ids=False, revision=None):
5746
from bzrlib.tag import tag_sort_methods
5309
5747
branch, relpath = Branch.open_containing(directory)
5311
5749
tags = branch.tags.get_tag_dict().items()
5316
self.add_cleanup(branch.unlock)
5753
self.add_cleanup(branch.lock_read().unlock)
5318
graph = branch.repository.get_graph()
5319
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5320
revid1, revid2 = rev1.rev_id, rev2.rev_id
5321
# only show revisions between revid1 and revid2 (inclusive)
5322
tags = [(tag, revid) for tag, revid in tags if
5323
graph.is_between(revid, revid1, revid2)]
5326
elif sort == 'time':
5328
for tag, revid in tags:
5330
revobj = branch.repository.get_revision(revid)
5331
except errors.NoSuchRevision:
5332
timestamp = sys.maxint # place them at the end
5334
timestamp = revobj.timestamp
5335
timestamps[revid] = timestamp
5336
tags.sort(key=lambda x: timestamps[x[1]])
5755
# Restrict to the specified range
5756
tags = self._tags_for_range(branch, revision)
5758
sort = tag_sort_methods.get()
5337
5760
if not show_ids:
5338
5761
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5339
5762
for index, (tag, revid) in enumerate(tags):
5350
5774
for tag, revspec in tags:
5351
5775
self.outf.write('%-20s %s\n' % (tag, revspec))
5777
def _tags_for_range(self, branch, revision):
5779
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5780
revid1, revid2 = rev1.rev_id, rev2.rev_id
5781
# _get_revision_range will always set revid2 if it's not specified.
5782
# If revid1 is None, it means we want to start from the branch
5783
# origin which is always a valid ancestor. If revid1 == revid2, the
5784
# ancestry check is useless.
5785
if revid1 and revid1 != revid2:
5786
# FIXME: We really want to use the same graph than
5787
# branch.iter_merge_sorted_revisions below, but this is not
5788
# easily available -- vila 2011-09-23
5789
if branch.repository.get_graph().is_ancestor(revid2, revid1):
5790
# We don't want to output anything in this case...
5792
# only show revisions between revid1 and revid2 (inclusive)
5793
tagged_revids = branch.tags.get_reverse_tag_dict()
5795
for r in branch.iter_merge_sorted_revisions(
5796
start_revision_id=revid2, stop_revision_id=revid1,
5797
stop_rule='include'):
5798
revid_tags = tagged_revids.get(r[0], None)
5800
found.extend([(tag, r[0]) for tag in revid_tags])
5354
5804
class cmd_reconfigure(Command):
5355
"""Reconfigure the type of a bzr directory.
5805
__doc__ = """Reconfigure the type of a bzr directory.
5357
5807
A target configuration must be specified.
5369
5819
takes_args = ['location?']
5370
5820
takes_options = [
5371
5821
RegistryOption.from_kwargs(
5373
title='Target type',
5374
help='The type to reconfigure the directory to.',
5824
help='The relation between branch and tree.',
5375
5825
value_switches=True, enum_switch=False,
5376
5826
branch='Reconfigure to be an unbound branch with no working tree.',
5377
5827
tree='Reconfigure to be an unbound branch with a working tree.',
5378
5828
checkout='Reconfigure to be a bound branch with a working tree.',
5379
5829
lightweight_checkout='Reconfigure to be a lightweight'
5380
5830
' checkout (with no local history).',
5832
RegistryOption.from_kwargs(
5834
title='Repository type',
5835
help='Location fo the repository.',
5836
value_switches=True, enum_switch=False,
5381
5837
standalone='Reconfigure to be a standalone branch '
5382
5838
'(i.e. stop using shared repository).',
5383
5839
use_shared='Reconfigure to use a shared repository.',
5841
RegistryOption.from_kwargs(
5843
title='Trees in Repository',
5844
help='Whether new branches in the repository have trees.',
5845
value_switches=True, enum_switch=False,
5384
5846
with_trees='Reconfigure repository to create '
5385
5847
'working trees on branches by default.',
5386
5848
with_no_trees='Reconfigure repository to not create '
5403
def run(self, location=None, target_type=None, bind_to=None, force=False,
5865
def run(self, location=None, bind_to=None, force=False,
5866
tree_type=None, repository_type=None, repository_trees=None,
5867
stacked_on=None, unstacked=None):
5406
5868
directory = bzrdir.BzrDir.open(location)
5407
5869
if stacked_on and unstacked:
5408
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5870
raise errors.BzrCommandError(gettext("Can't use both --stacked-on and --unstacked"))
5409
5871
elif stacked_on is not None:
5410
5872
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5411
5873
elif unstacked:
5413
5875
# At the moment you can use --stacked-on and a different
5414
5876
# reconfiguration shape at the same time; there seems no good reason
5416
if target_type is None:
5878
if (tree_type is None and
5879
repository_type is None and
5880
repository_trees is None):
5417
5881
if stacked_on or unstacked:
5420
raise errors.BzrCommandError('No target configuration '
5422
elif target_type == 'branch':
5884
raise errors.BzrCommandError(gettext('No target configuration '
5886
reconfiguration = None
5887
if tree_type == 'branch':
5423
5888
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5424
elif target_type == 'tree':
5889
elif tree_type == 'tree':
5425
5890
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5426
elif target_type == 'checkout':
5891
elif tree_type == 'checkout':
5427
5892
reconfiguration = reconfigure.Reconfigure.to_checkout(
5428
5893
directory, bind_to)
5429
elif target_type == 'lightweight-checkout':
5894
elif tree_type == 'lightweight-checkout':
5430
5895
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5431
5896
directory, bind_to)
5432
elif target_type == 'use-shared':
5898
reconfiguration.apply(force)
5899
reconfiguration = None
5900
if repository_type == 'use-shared':
5433
5901
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5434
elif target_type == 'standalone':
5902
elif repository_type == 'standalone':
5435
5903
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5436
elif target_type == 'with-trees':
5905
reconfiguration.apply(force)
5906
reconfiguration = None
5907
if repository_trees == 'with-trees':
5437
5908
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5438
5909
directory, True)
5439
elif target_type == 'with-no-trees':
5910
elif repository_trees == 'with-no-trees':
5440
5911
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5441
5912
directory, False)
5442
reconfiguration.apply(force)
5914
reconfiguration.apply(force)
5915
reconfiguration = None
5445
5918
class cmd_switch(Command):
5446
"""Set the branch of a checkout and update.
5919
__doc__ = """Set the branch of a checkout and update.
5448
5921
For lightweight checkouts, this changes the branch being referenced.
5449
5922
For heavyweight checkouts, this checks that there are no local commits
5477
5951
def run(self, to_location=None, force=False, create_branch=False,
5952
revision=None, directory=u'.'):
5479
5953
from bzrlib import switch
5954
tree_location = directory
5481
5955
revision = _get_one_revision('switch', revision)
5482
5956
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5483
5957
if to_location is None:
5484
5958
if revision is None:
5485
raise errors.BzrCommandError('You must supply either a'
5486
' revision or a location')
5959
raise errors.BzrCommandError(gettext('You must supply either a'
5960
' revision or a location'))
5961
to_location = tree_location
5489
5963
branch = control_dir.open_branch()
5490
5964
had_explicit_nick = branch.get_config().has_explicit_nickname()
5628
tree, file_list = tree_files(file_list, apply_view=False)
6102
tree, file_list = WorkingTree.open_containing_paths(file_list,
5629
6104
current_view, view_dict = tree.views.get_view_info()
5630
6105
if name is None:
5631
6106
name = current_view
5634
raise errors.BzrCommandError(
5635
"Both --delete and a file list specified")
6109
raise errors.BzrCommandError(gettext(
6110
"Both --delete and a file list specified"))
5637
raise errors.BzrCommandError(
5638
"Both --delete and --switch specified")
6112
raise errors.BzrCommandError(gettext(
6113
"Both --delete and --switch specified"))
5640
6115
tree.views.set_view_info(None, {})
5641
self.outf.write("Deleted all views.\n")
6116
self.outf.write(gettext("Deleted all views.\n"))
5642
6117
elif name is None:
5643
raise errors.BzrCommandError("No current view to delete")
6118
raise errors.BzrCommandError(gettext("No current view to delete"))
5645
6120
tree.views.delete_view(name)
5646
self.outf.write("Deleted '%s' view.\n" % name)
6121
self.outf.write(gettext("Deleted '%s' view.\n") % name)
5649
raise errors.BzrCommandError(
5650
"Both --switch and a file list specified")
6124
raise errors.BzrCommandError(gettext(
6125
"Both --switch and a file list specified"))
5652
raise errors.BzrCommandError(
5653
"Both --switch and --all specified")
6127
raise errors.BzrCommandError(gettext(
6128
"Both --switch and --all specified"))
5654
6129
elif switch == 'off':
5655
6130
if current_view is None:
5656
raise errors.BzrCommandError("No current view to disable")
6131
raise errors.BzrCommandError(gettext("No current view to disable"))
5657
6132
tree.views.set_view_info(None, view_dict)
5658
self.outf.write("Disabled '%s' view.\n" % (current_view))
6133
self.outf.write(gettext("Disabled '%s' view.\n") % (current_view))
5660
6135
tree.views.set_view_info(switch, view_dict)
5661
6136
view_str = views.view_display_str(tree.views.lookup_view())
5662
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
6137
self.outf.write(gettext("Using '{0}' view: {1}\n").format(switch, view_str))
5665
self.outf.write('Views defined:\n')
6140
self.outf.write(gettext('Views defined:\n'))
5666
6141
for view in sorted(view_dict):
5667
6142
if view == current_view:
5671
6146
view_str = views.view_display_str(view_dict[view])
5672
6147
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5674
self.outf.write('No views defined.\n')
6149
self.outf.write(gettext('No views defined.\n'))
5675
6150
elif file_list:
5676
6151
if name is None:
5677
6152
# No name given and no current view set
5679
6154
elif name == 'off':
5680
raise errors.BzrCommandError(
5681
"Cannot change the 'off' pseudo view")
6155
raise errors.BzrCommandError(gettext(
6156
"Cannot change the 'off' pseudo view"))
5682
6157
tree.views.set_view(name, sorted(file_list))
5683
6158
view_str = views.view_display_str(tree.views.lookup_view())
5684
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
6159
self.outf.write(gettext("Using '{0}' view: {1}\n").format(name, view_str))
5686
6161
# list the files
5687
6162
if name is None:
5688
6163
# No name given and no current view set
5689
self.outf.write('No current view.\n')
6164
self.outf.write(gettext('No current view.\n'))
5691
6166
view_str = views.view_display_str(tree.views.lookup_view(name))
5692
self.outf.write("'%s' view is: %s\n" % (name, view_str))
6167
self.outf.write(gettext("'{0}' view is: {1}\n").format(name, view_str))
5695
6170
class cmd_hooks(Command):
6171
__doc__ = """Show hooks."""
5709
6184
self.outf.write(" %s\n" %
5710
6185
(some_hooks.get_hook_name(hook),))
5712
self.outf.write(" <no hooks installed>\n")
6187
self.outf.write(gettext(" <no hooks installed>\n"))
6190
class cmd_remove_branch(Command):
6191
__doc__ = """Remove a branch.
6193
This will remove the branch from the specified location but
6194
will keep any working tree or repository in place.
6198
Remove the branch at repo/trunk::
6200
bzr remove-branch repo/trunk
6204
takes_args = ["location?"]
6206
aliases = ["rmbranch"]
6208
def run(self, location=None):
6209
if location is None:
6211
branch = Branch.open_containing(location)[0]
6212
branch.bzrdir.destroy_branch()
5715
6215
class cmd_shelve(Command):
5716
"""Temporarily set aside some changes from the current tree.
6216
__doc__ = """Temporarily set aside some changes from the current tree.
5718
6218
Shelve allows you to temporarily put changes you've made "on the shelf",
5719
6219
ie. out of the way, until a later time when you can bring them back from
5751
6264
Option('destroy',
5752
6265
help='Destroy removed changes instead of shelving them.'),
5754
_see_also = ['unshelve']
6267
_see_also = ['unshelve', 'configuration']
5756
6269
def run(self, revision=None, all=False, file_list=None, message=None,
5757
writer=None, list=False, destroy=False):
6270
writer=None, list=False, destroy=False, directory=None):
5759
return self.run_for_list()
6272
return self.run_for_list(directory=directory)
5760
6273
from bzrlib.shelf_ui import Shelver
5761
6274
if writer is None:
5762
6275
writer = bzrlib.option.diff_writer_registry.get()
5764
6277
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5765
file_list, message, destroy=destroy)
6278
file_list, message, destroy=destroy, directory=directory)
5843
6359
' deleting them.'),
5844
6360
Option('force', help='Do not prompt before deleting.')]
5845
6361
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6362
force=False, directory=u'.'):
5847
6363
from bzrlib.clean_tree import clean_tree
5848
6364
if not (unknown or ignored or detritus):
5852
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5853
dry_run=dry_run, no_prompt=force)
6368
clean_tree(directory, unknown=unknown, ignored=ignored,
6369
detritus=detritus, dry_run=dry_run, no_prompt=force)
5856
6372
class cmd_reference(Command):
5857
"""list, view and set branch locations for nested trees.
6373
__doc__ = """list, view and set branch locations for nested trees.
5859
6375
If no arguments are provided, lists the branch locations for nested trees.
5860
6376
If one argument is provided, display the branch location for that tree.
5900
6416
self.outf.write('%s %s\n' % (path, location))
5903
# these get imported and then picked up by the scan for cmd_*
5904
# TODO: Some more consistent way to split command definitions across files;
5905
# we do need to load at least some information about them to know of
5906
# aliases. ideally we would avoid loading the implementation until the
5907
# details were needed.
5908
from bzrlib.cmd_version_info import cmd_version_info
5909
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5910
from bzrlib.bundle.commands import (
5913
from bzrlib.foreign import cmd_dpush
5914
from bzrlib.sign_my_commits import cmd_sign_my_commits
6419
class cmd_export_pot(Command):
6420
__doc__ = """Export command helps and error messages in po format."""
6425
from bzrlib.export_pot import export_pot
6426
export_pot(self.outf)
6429
def _register_lazy_builtins():
6430
# register lazy builtins from other modules; called at startup and should
6431
# be only called once.
6432
for (name, aliases, module_name) in [
6433
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6434
('cmd_config', [], 'bzrlib.config'),
6435
('cmd_dpush', [], 'bzrlib.foreign'),
6436
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6437
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6438
('cmd_conflicts', [], 'bzrlib.conflicts'),
6439
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6440
('cmd_verify_signatures', [],
6441
'bzrlib.commit_signature_commands'),
6442
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6444
builtin_command_registry.register_lazy(name, aliases, module_name)