65
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
68
def tree_files(file_list, default_branch=u'.', canonicalize=True):
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
70
return internal_tree_files(file_list, default_branch, canonicalize)
81
return internal_tree_files(file_list, default_branch, canonicalize,
71
83
except errors.FileInWrongBranch, e:
72
84
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
85
(e.path, file_list[0]))
88
def tree_files_for_add(file_list):
90
Return a tree and list of absolute paths from a file list.
92
Similar to tree_files, but add handles files a bit differently, so it a
93
custom implementation. In particular, MutableTreeTree.smart_add expects
94
absolute paths, which it immediately converts to relative paths.
96
# FIXME Would be nice to just return the relative paths like
97
# internal_tree_files does, but there are a large number of unit tests
98
# that assume the current interface to mutabletree.smart_add
100
tree, relpath = WorkingTree.open_containing(file_list[0])
101
if tree.supports_views():
102
view_files = tree.views.lookup_view()
104
for filename in file_list:
105
if not osutils.is_inside_any(view_files, filename):
106
raise errors.FileOutsideView(filename, view_files)
107
file_list = file_list[:]
108
file_list[0] = tree.abspath(relpath)
110
tree = WorkingTree.open_containing(u'.')[0]
111
if tree.supports_views():
112
view_files = tree.views.lookup_view()
114
file_list = view_files
115
view_str = views.view_display_str(view_files)
116
note("Ignoring files outside view. View is %s" % view_str)
117
return tree, file_list
76
120
def _get_one_revision(command_name, revisions):
77
121
if revisions is None:
108
162
The filenames given are not required to exist.
110
:param file_list: Filenames to convert.
164
:param file_list: Filenames to convert.
112
166
:param default_branch: Fallback tree path to use if file_list is empty or
169
:param apply_view: if True and a view is set, apply it or check that
170
specified files are within it
115
172
:return: workingtree, [relative_paths]
117
174
if file_list is None or len(file_list) == 0:
118
return WorkingTree.open_containing(default_branch)[0], file_list
175
tree = WorkingTree.open_containing(default_branch)[0]
176
if tree.supports_views() and apply_view:
177
view_files = tree.views.lookup_view()
179
file_list = view_files
180
view_str = views.view_display_str(view_files)
181
note("Ignoring files outside view. View is %s" % view_str)
182
return tree, file_list
119
183
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
120
return tree, safe_relpath_files(tree, file_list, canonicalize)
123
def safe_relpath_files(tree, file_list, canonicalize=True):
184
return tree, safe_relpath_files(tree, file_list, canonicalize,
185
apply_view=apply_view)
188
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
124
189
"""Convert file_list into a list of relpaths in tree.
126
191
:param tree: A tree to operate on.
127
192
:param file_list: A list of user provided paths or None.
193
:param apply_view: if True and a view is set, apply it or check that
194
specified files are within it
128
195
:return: A list of relative paths.
129
196
:raises errors.PathNotChild: When a provided path is in a different tree
132
199
if file_list is None:
201
if tree.supports_views() and apply_view:
202
view_files = tree.views.lookup_view()
135
206
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
136
207
# doesn't - fix that up here before we enter the loop.
244
342
class cmd_cat_revision(Command):
245
"""Write out metadata for a revision.
343
__doc__ = """Write out metadata for a revision.
247
345
The revision to print can either be specified by a specific
248
346
revision identifier, or you can use --revision.
252
350
takes_args = ['revision_id?']
253
takes_options = ['revision']
351
takes_options = ['directory', 'revision']
254
352
# cat-revision is more for frontends so should be exact
255
353
encoding = 'strict'
355
def print_revision(self, revisions, revid):
356
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
357
record = stream.next()
358
if record.storage_kind == 'absent':
359
raise errors.NoSuchRevision(revisions, revid)
360
revtext = record.get_bytes_as('fulltext')
361
self.outf.write(revtext.decode('utf-8'))
258
def run(self, revision_id=None, revision=None):
364
def run(self, revision_id=None, revision=None, directory=u'.'):
259
365
if revision_id is not None and revision is not None:
260
366
raise errors.BzrCommandError('You can only supply one of'
261
367
' revision_id or --revision')
262
368
if revision_id is None and revision is None:
263
369
raise errors.BzrCommandError('You must supply either'
264
370
' --revision or a revision_id')
265
b = WorkingTree.open_containing(u'.')[0].branch
267
# TODO: jam 20060112 should cat-revision always output utf-8?
268
if revision_id is not None:
269
revision_id = osutils.safe_revision_id(revision_id, warn=False)
271
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
272
except errors.NoSuchRevision:
273
msg = "The repository %s contains no revision %s." % (b.repository.base,
275
raise errors.BzrCommandError(msg)
276
elif revision is not None:
279
raise errors.BzrCommandError('You cannot specify a NULL'
281
rev_id = rev.as_revision_id(b)
282
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
371
b = WorkingTree.open_containing(directory)[0].branch
373
revisions = b.repository.revisions
374
if revisions is None:
375
raise errors.BzrCommandError('Repository %r does not support '
376
'access to raw revision texts')
378
b.repository.lock_read()
380
# TODO: jam 20060112 should cat-revision always output utf-8?
381
if revision_id is not None:
382
revision_id = osutils.safe_revision_id(revision_id, warn=False)
384
self.print_revision(revisions, revision_id)
385
except errors.NoSuchRevision:
386
msg = "The repository %s contains no revision %s." % (
387
b.repository.base, revision_id)
388
raise errors.BzrCommandError(msg)
389
elif revision is not None:
392
raise errors.BzrCommandError(
393
'You cannot specify a NULL revision.')
394
rev_id = rev.as_revision_id(b)
395
self.print_revision(revisions, rev_id)
397
b.repository.unlock()
285
400
class cmd_dump_btree(Command):
286
"""Dump the contents of a btree index file to stdout.
401
__doc__ = """Dump the contents of a btree index file to stdout.
288
403
PATH is a btree index file, it can be any URL. This includes things like
289
404
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
365
487
To re-create the working tree, use "bzr checkout".
367
489
_see_also = ['checkout', 'working-trees']
368
takes_args = ['location?']
490
takes_args = ['location*']
369
491
takes_options = [
371
493
help='Remove the working tree even if it has '
372
'uncommitted changes.'),
494
'uncommitted or shelved changes.'),
375
def run(self, location='.', force=False):
376
d = bzrdir.BzrDir.open(location)
379
working = d.open_workingtree()
380
except errors.NoWorkingTree:
381
raise errors.BzrCommandError("No working tree to remove")
382
except errors.NotLocalUrl:
383
raise errors.BzrCommandError("You cannot remove the working tree of a "
386
changes = working.changes_from(working.basis_tree())
387
if changes.has_changed():
388
raise errors.UncommittedChanges(working)
390
working_path = working.bzrdir.root_transport.base
391
branch_path = working.branch.bzrdir.root_transport.base
392
if working_path != branch_path:
393
raise errors.BzrCommandError("You cannot remove the working tree from "
394
"a lightweight checkout")
396
d.destroy_workingtree()
497
def run(self, location_list, force=False):
498
if not location_list:
501
for location in location_list:
502
d = bzrdir.BzrDir.open(location)
505
working = d.open_workingtree()
506
except errors.NoWorkingTree:
507
raise errors.BzrCommandError("No working tree to remove")
508
except errors.NotLocalUrl:
509
raise errors.BzrCommandError("You cannot remove the working tree"
512
if (working.has_changes()):
513
raise errors.UncommittedChanges(working)
514
if working.get_shelf_manager().last_shelf() is not None:
515
raise errors.ShelvedChanges(working)
517
if working.user_url != working.branch.user_url:
518
raise errors.BzrCommandError("You cannot remove the working tree"
519
" from a lightweight checkout")
521
d.destroy_workingtree()
399
524
class cmd_revno(Command):
400
"""Show current revision number.
525
__doc__ = """Show current revision number.
402
527
This is equal to the number of revisions on this branch.
405
530
_see_also = ['info']
406
531
takes_args = ['location?']
533
Option('tree', help='Show revno of working tree'),
409
def run(self, location=u'.'):
410
self.outf.write(str(Branch.open_containing(location)[0].revno()))
411
self.outf.write('\n')
537
def run(self, tree=False, location=u'.'):
540
wt = WorkingTree.open_containing(location)[0]
541
self.add_cleanup(wt.lock_read().unlock)
542
except (errors.NoWorkingTree, errors.NotLocalUrl):
543
raise errors.NoWorkingTree(location)
544
revid = wt.last_revision()
546
revno_t = wt.branch.revision_id_to_dotted_revno(revid)
547
except errors.NoSuchRevision:
549
revno = ".".join(str(n) for n in revno_t)
551
b = Branch.open_containing(location)[0]
552
self.add_cleanup(b.lock_read().unlock)
555
self.outf.write(str(revno) + '\n')
414
558
class cmd_revision_info(Command):
415
"""Show revision number and revision id for a given revision identifier.
559
__doc__ = """Show revision number and revision id for a given revision identifier.
418
562
takes_args = ['revision_info*']
419
563
takes_options = [
565
custom_help('directory',
422
566
help='Branch to examine, '
423
'rather than the one containing the working directory.',
567
'rather than the one containing the working directory.'),
568
Option('tree', help='Show revno of working tree'),
430
def run(self, revision=None, directory=u'.', revision_info_list=[]):
572
def run(self, revision=None, directory=u'.', tree=False,
573
revision_info_list=[]):
576
wt = WorkingTree.open_containing(directory)[0]
578
self.add_cleanup(wt.lock_read().unlock)
579
except (errors.NoWorkingTree, errors.NotLocalUrl):
581
b = Branch.open_containing(directory)[0]
582
self.add_cleanup(b.lock_read().unlock)
433
584
if revision is not None:
434
revs.extend(revision)
585
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
435
586
if revision_info_list is not None:
436
for rev in revision_info_list:
437
revs.append(RevisionSpec.from_string(rev))
439
b = Branch.open_containing(directory)[0]
442
revs.append(RevisionSpec.from_string('-1'))
445
revision_id = rev.as_revision_id(b)
587
for rev_str in revision_info_list:
588
rev_spec = RevisionSpec.from_string(rev_str)
589
revision_ids.append(rev_spec.as_revision_id(b))
590
# No arguments supplied, default to the last revision
591
if len(revision_ids) == 0:
594
raise errors.NoWorkingTree(directory)
595
revision_ids.append(wt.last_revision())
597
revision_ids.append(b.last_revision())
601
for revision_id in revision_ids:
447
revno = '%4d' % (b.revision_id_to_revno(revision_id))
603
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
604
revno = '.'.join(str(i) for i in dotted_revno)
448
605
except errors.NoSuchRevision:
449
dotted_map = b.get_revision_id_to_revno_map()
450
revno = '.'.join(str(i) for i in dotted_map[revision_id])
451
print '%s %s' % (revno, revision_id)
607
maxlen = max(maxlen, len(revno))
608
revinfos.append([revno, revision_id])
612
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
454
615
class cmd_add(Command):
455
"""Add specified files or directories.
616
__doc__ = """Add specified files or directories.
457
618
In non-recursive mode, all the named items are added, regardless
458
619
of whether they were previously ignored. A warning is given if
668
817
takes_args = ['names*']
669
818
takes_options = [Option("after", help="Move only the bzr identifier"
670
819
" of the file, because the file has already been moved."),
820
Option('auto', help='Automatically guess renames.'),
821
Option('dry-run', help='Avoid making changes when guessing renames.'),
672
823
aliases = ['move', 'rename']
673
824
encoding_type = 'replace'
675
def run(self, names_list, after=False):
826
def run(self, names_list, after=False, auto=False, dry_run=False):
828
return self.run_auto(names_list, after, dry_run)
830
raise errors.BzrCommandError('--dry-run requires --auto.')
676
831
if names_list is None:
679
833
if len(names_list) < 2:
680
834
raise errors.BzrCommandError("missing file argument")
681
835
tree, rel_names = tree_files(names_list, canonicalize=False)
684
self._run(tree, names_list, rel_names, after)
836
self.add_cleanup(tree.lock_tree_write().unlock)
837
self._run(tree, names_list, rel_names, after)
839
def run_auto(self, names_list, after, dry_run):
840
if names_list is not None and len(names_list) > 1:
841
raise errors.BzrCommandError('Only one path may be specified to'
844
raise errors.BzrCommandError('--after cannot be specified with'
846
work_tree, file_list = tree_files(names_list, default_branch='.')
847
self.add_cleanup(work_tree.lock_tree_write().unlock)
848
rename_map.RenameMap.guess_renames(work_tree, dry_run)
688
850
def _run(self, tree, names_list, rel_names, after):
689
851
into_existing = osutils.isdir(names_list[-1])
1001
1181
help='Hard-link working tree files where possible.'),
1002
1182
Option('no-tree',
1003
1183
help="Create a branch without a working-tree."),
1185
help="Switch the checkout in the current directory "
1186
"to the new branch."),
1004
1187
Option('stacked',
1005
1188
help='Create a stacked branch referring to the source branch. '
1006
1189
'The new branch will depend on the availability of the source '
1007
1190
'branch for all operations.'),
1008
1191
Option('standalone',
1009
1192
help='Do not use a shared repository, even if available.'),
1193
Option('use-existing-dir',
1194
help='By default branch will fail if the target'
1195
' directory exists, but does not already'
1196
' have a control directory. This flag will'
1197
' allow branch to proceed.'),
1199
help="Bind new branch to from location."),
1011
1201
aliases = ['get', 'clone']
1013
1203
def run(self, from_location, to_location=None, revision=None,
1014
hardlink=False, stacked=False, standalone=False, no_tree=False):
1204
hardlink=False, stacked=False, standalone=False, no_tree=False,
1205
use_existing_dir=False, switch=False, bind=False):
1206
from bzrlib import switch as _mod_switch
1015
1207
from bzrlib.tag import _merge_tags_if_possible
1017
1208
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1019
1210
revision = _get_one_revision('branch', revision)
1211
self.add_cleanup(br_from.lock_read().unlock)
1212
if revision is not None:
1213
revision_id = revision.as_revision_id(br_from)
1215
# FIXME - wt.last_revision, fallback to branch, fall back to
1216
# None or perhaps NULL_REVISION to mean copy nothing
1218
revision_id = br_from.last_revision()
1219
if to_location is None:
1220
to_location = urlutils.derive_to_location(from_location)
1221
to_transport = transport.get_transport(to_location)
1022
if revision is not None:
1023
revision_id = revision.as_revision_id(br_from)
1223
to_transport.mkdir('.')
1224
except errors.FileExists:
1225
if not use_existing_dir:
1226
raise errors.BzrCommandError('Target directory "%s" '
1227
'already exists.' % to_location)
1025
# FIXME - wt.last_revision, fallback to branch, fall back to
1026
# None or perhaps NULL_REVISION to mean copy nothing
1028
revision_id = br_from.last_revision()
1029
if to_location is None:
1030
to_location = urlutils.derive_to_location(from_location)
1031
to_transport = transport.get_transport(to_location)
1033
to_transport.mkdir('.')
1034
except errors.FileExists:
1035
raise errors.BzrCommandError('Target directory "%s" already'
1036
' exists.' % to_location)
1037
except errors.NoSuchFile:
1038
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1041
# preserve whatever source format we have.
1042
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1043
possible_transports=[to_transport],
1044
accelerator_tree=accelerator_tree,
1045
hardlink=hardlink, stacked=stacked,
1046
force_new_repo=standalone,
1047
create_tree_if_local=not no_tree,
1048
source_branch=br_from)
1049
branch = dir.open_branch()
1050
except errors.NoSuchRevision:
1051
to_transport.delete_tree('.')
1052
msg = "The branch %s has no revision %s." % (from_location,
1054
raise errors.BzrCommandError(msg)
1055
_merge_tags_if_possible(br_from, branch)
1056
# If the source branch is stacked, the new branch may
1057
# be stacked whether we asked for that explicitly or not.
1058
# We therefore need a try/except here and not just 'if stacked:'
1060
note('Created new stacked branch referring to %s.' %
1061
branch.get_stacked_on_url())
1062
except (errors.NotStacked, errors.UnstackableBranchFormat,
1063
errors.UnstackableRepositoryFormat), e:
1064
note('Branched %d revision(s).' % branch.revno())
1230
bzrdir.BzrDir.open_from_transport(to_transport)
1231
except errors.NotBranchError:
1234
raise errors.AlreadyBranchError(to_location)
1235
except errors.NoSuchFile:
1236
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1239
# preserve whatever source format we have.
1240
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1241
possible_transports=[to_transport],
1242
accelerator_tree=accelerator_tree,
1243
hardlink=hardlink, stacked=stacked,
1244
force_new_repo=standalone,
1245
create_tree_if_local=not no_tree,
1246
source_branch=br_from)
1247
branch = dir.open_branch()
1248
except errors.NoSuchRevision:
1249
to_transport.delete_tree('.')
1250
msg = "The branch %s has no revision %s." % (from_location,
1252
raise errors.BzrCommandError(msg)
1253
_merge_tags_if_possible(br_from, branch)
1254
# If the source branch is stacked, the new branch may
1255
# be stacked whether we asked for that explicitly or not.
1256
# We therefore need a try/except here and not just 'if stacked:'
1258
note('Created new stacked branch referring to %s.' %
1259
branch.get_stacked_on_url())
1260
except (errors.NotStacked, errors.UnstackableBranchFormat,
1261
errors.UnstackableRepositoryFormat), e:
1262
note('Branched %d revision(s).' % branch.revno())
1264
# Bind to the parent
1265
parent_branch = Branch.open(from_location)
1266
branch.bind(parent_branch)
1267
note('New branch bound to %s' % from_location)
1269
# Switch to the new branch
1270
wt, _ = WorkingTree.open_containing('.')
1271
_mod_switch.switch(wt.bzrdir, branch)
1272
note('Switched to branch: %s',
1273
urlutils.unescape_for_display(branch.base, 'utf-8'))
1069
1276
class cmd_checkout(Command):
1070
"""Create a new checkout of an existing branch.
1277
__doc__ = """Create a new checkout of an existing branch.
1072
1279
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1073
1280
the branch found in '.'. This is useful if you have removed the working tree
1074
1281
or if it was never created - i.e. if you pushed the branch to its current
1075
1282
location using SFTP.
1077
1284
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1078
1285
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1079
1286
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1147
1354
@display_command
1148
1355
def run(self, dir=u'.'):
1149
1356
tree = WorkingTree.open_containing(dir)[0]
1152
new_inv = tree.inventory
1153
old_tree = tree.basis_tree()
1154
old_tree.lock_read()
1156
old_inv = old_tree.inventory
1158
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1159
for f, paths, c, v, p, n, k, e in iterator:
1160
if paths[0] == paths[1]:
1164
renames.append(paths)
1166
for old_name, new_name in renames:
1167
self.outf.write("%s => %s\n" % (old_name, new_name))
1357
self.add_cleanup(tree.lock_read().unlock)
1358
new_inv = tree.inventory
1359
old_tree = tree.basis_tree()
1360
self.add_cleanup(old_tree.lock_read().unlock)
1361
old_inv = old_tree.inventory
1363
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1364
for f, paths, c, v, p, n, k, e in iterator:
1365
if paths[0] == paths[1]:
1369
renames.append(paths)
1371
for old_name, new_name in renames:
1372
self.outf.write("%s => %s\n" % (old_name, new_name))
1174
1375
class cmd_update(Command):
1175
"""Update a tree to have the latest code committed to its branch.
1376
__doc__ = """Update a tree to have the latest code committed to its branch.
1177
1378
This will perform a merge into the working tree, and may generate
1178
conflicts. If you have any local changes, you will still
1379
conflicts. If you have any local changes, you will still
1179
1380
need to commit them after the update for the update to be complete.
1181
If you want to discard your local changes, you can just do a
1382
If you want to discard your local changes, you can just do a
1182
1383
'bzr revert' instead of 'bzr commit' after the update.
1385
If the tree's branch is bound to a master branch, it will also update
1386
the branch from the master.
1185
1389
_see_also = ['pull', 'working-trees', 'status-flags']
1186
1390
takes_args = ['dir?']
1391
takes_options = ['revision']
1187
1392
aliases = ['up']
1189
def run(self, dir='.'):
1394
def run(self, dir='.', revision=None):
1395
if revision is not None and len(revision) != 1:
1396
raise errors.BzrCommandError(
1397
"bzr update --revision takes exactly one revision")
1190
1398
tree = WorkingTree.open_containing(dir)[0]
1399
branch = tree.branch
1191
1400
possible_transports = []
1192
master = tree.branch.get_master_branch(
1401
master = branch.get_master_branch(
1193
1402
possible_transports=possible_transports)
1194
1403
if master is not None:
1404
branch_location = master.base
1195
1405
tree.lock_write()
1407
branch_location = tree.branch.base
1197
1408
tree.lock_tree_write()
1409
self.add_cleanup(tree.unlock)
1410
# get rid of the final '/' and be ready for display
1411
branch_location = urlutils.unescape_for_display(
1412
branch_location.rstrip('/'),
1414
existing_pending_merges = tree.get_parent_ids()[1:]
1418
# may need to fetch data into a heavyweight checkout
1419
# XXX: this may take some time, maybe we should display a
1421
old_tip = branch.update(possible_transports)
1422
if revision is not None:
1423
revision_id = revision[0].as_revision_id(branch)
1425
revision_id = branch.last_revision()
1426
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1427
revno = branch.revision_id_to_dotted_revno(revision_id)
1428
note("Tree is up to date at revision %s of branch %s" %
1429
('.'.join(map(str, revno)), branch_location))
1431
view_info = _get_view_info_for_change_reporter(tree)
1432
change_reporter = delta._ChangeReporter(
1433
unversioned_filter=tree.is_ignored,
1434
view_info=view_info)
1199
existing_pending_merges = tree.get_parent_ids()[1:]
1200
last_rev = _mod_revision.ensure_null(tree.last_revision())
1201
if last_rev == _mod_revision.ensure_null(
1202
tree.branch.last_revision()):
1203
# may be up to date, check master too.
1204
if master is None or last_rev == _mod_revision.ensure_null(
1205
master.last_revision()):
1206
revno = tree.branch.revision_id_to_revno(last_rev)
1207
note("Tree is up to date at revision %d." % (revno,))
1209
1436
conflicts = tree.update(
1210
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1211
possible_transports=possible_transports)
1212
revno = tree.branch.revision_id_to_revno(
1213
_mod_revision.ensure_null(tree.last_revision()))
1214
note('Updated to revision %d.' % (revno,))
1215
if tree.get_parent_ids()[1:] != existing_pending_merges:
1216
note('Your local commits will now show as pending merges with '
1217
"'bzr status', and can be committed with 'bzr commit'.")
1438
possible_transports=possible_transports,
1439
revision=revision_id,
1441
except errors.NoSuchRevision, e:
1442
raise errors.BzrCommandError(
1443
"branch has no revision %s\n"
1444
"bzr update --revision only works"
1445
" for a revision in the branch history"
1447
revno = tree.branch.revision_id_to_dotted_revno(
1448
_mod_revision.ensure_null(tree.last_revision()))
1449
note('Updated to revision %s of branch %s' %
1450
('.'.join(map(str, revno)), branch_location))
1451
parent_ids = tree.get_parent_ids()
1452
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1453
note('Your local commits will now show as pending merges with '
1454
"'bzr status', and can be committed with 'bzr commit'.")
1226
1461
class cmd_info(Command):
1227
"""Show information about a working tree, branch or repository.
1462
__doc__ = """Show information about a working tree, branch or repository.
1229
1464
This command will show all known locations and formats associated to the
1230
tree, branch or repository. Statistical information is included with
1465
tree, branch or repository.
1467
In verbose mode, statistical information is included with each report.
1468
To see extended statistic information, use a verbosity level of 2 or
1469
higher by specifying the verbose option multiple times, e.g. -vv.
1233
1471
Branches and working trees will also report any missing revisions.
1475
Display information on the format and related locations:
1479
Display the above together with extended format information and
1480
basic statistics (like the number of files in the working tree and
1481
number of revisions in the branch and repository):
1485
Display the above together with number of committers to the branch:
1235
1489
_see_also = ['revno', 'working-trees', 'repositories']
1236
1490
takes_args = ['location?']
1277
1531
if file_list is not None:
1278
1532
file_list = [f for f in file_list]
1282
# Heuristics should probably all move into tree.remove_smart or
1285
added = tree.changes_from(tree.basis_tree(),
1286
specific_files=file_list).added
1287
file_list = sorted([f[0] for f in added], reverse=True)
1288
if len(file_list) == 0:
1289
raise errors.BzrCommandError('No matching files.')
1290
elif file_list is None:
1291
# missing files show up in iter_changes(basis) as
1292
# versioned-with-no-kind.
1294
for change in tree.iter_changes(tree.basis_tree()):
1295
# Find paths in the working tree that have no kind:
1296
if change[1][1] is not None and change[6][1] is None:
1297
missing.append(change[1][1])
1298
file_list = sorted(missing, reverse=True)
1299
file_deletion_strategy = 'keep'
1300
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1301
keep_files=file_deletion_strategy=='keep',
1302
force=file_deletion_strategy=='force')
1534
self.add_cleanup(tree.lock_write().unlock)
1535
# Heuristics should probably all move into tree.remove_smart or
1538
added = tree.changes_from(tree.basis_tree(),
1539
specific_files=file_list).added
1540
file_list = sorted([f[0] for f in added], reverse=True)
1541
if len(file_list) == 0:
1542
raise errors.BzrCommandError('No matching files.')
1543
elif file_list is None:
1544
# missing files show up in iter_changes(basis) as
1545
# versioned-with-no-kind.
1547
for change in tree.iter_changes(tree.basis_tree()):
1548
# Find paths in the working tree that have no kind:
1549
if change[1][1] is not None and change[6][1] is None:
1550
missing.append(change[1][1])
1551
file_list = sorted(missing, reverse=True)
1552
file_deletion_strategy = 'keep'
1553
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1554
keep_files=file_deletion_strategy=='keep',
1555
force=file_deletion_strategy=='force')
1307
1558
class cmd_file_id(Command):
1308
"""Print file_id of a particular file or directory.
1559
__doc__ = """Print file_id of a particular file or directory.
1310
1561
The file_id is assigned when the file is first added and remains the
1311
1562
same through all revisions where the file exists, even when it is
1705
1992
# level of effort but possibly much less IO. (Or possibly not,
1706
1993
# if the directories are very large...)
1707
1994
_see_also = ['status', 'ls']
1708
takes_options = ['show-ids']
1995
takes_options = ['directory', 'show-ids']
1710
1997
@display_command
1711
def run(self, show_ids=False):
1712
tree = WorkingTree.open_containing(u'.')[0]
1715
old = tree.basis_tree()
1718
for path, ie in old.inventory.iter_entries():
1719
if not tree.has_id(ie.file_id):
1720
self.outf.write(path)
1722
self.outf.write(' ')
1723
self.outf.write(ie.file_id)
1724
self.outf.write('\n')
1998
def run(self, show_ids=False, directory=u'.'):
1999
tree = WorkingTree.open_containing(directory)[0]
2000
self.add_cleanup(tree.lock_read().unlock)
2001
old = tree.basis_tree()
2002
self.add_cleanup(old.lock_read().unlock)
2003
for path, ie in old.inventory.iter_entries():
2004
if not tree.has_id(ie.file_id):
2005
self.outf.write(path)
2007
self.outf.write(' ')
2008
self.outf.write(ie.file_id)
2009
self.outf.write('\n')
1731
2012
class cmd_modified(Command):
1732
"""List files modified in working tree.
2013
__doc__ = """List files modified in working tree.
1736
2017
_see_also = ['status', 'ls']
1739
help='Write an ascii NUL (\\0) separator '
1740
'between files rather than a newline.')
2018
takes_options = ['directory', 'null']
1743
2020
@display_command
1744
def run(self, null=False):
1745
tree = WorkingTree.open_containing(u'.')[0]
2021
def run(self, null=False, directory=u'.'):
2022
tree = WorkingTree.open_containing(directory)[0]
1746
2023
td = tree.changes_from(tree.basis_tree())
1747
2024
for path, id, kind, text_modified, meta_modified in td.modified:
1850
2117
The following options can be used to control what information is
1853
2120
-l N display a maximum of N revisions
1854
2121
-n N display N levels of revisions (0 for all, 1 for collapsed)
1855
2122
-v display a status summary (delta) for each revision
1856
2123
-p display a diff (patch) for each revision
1857
2124
--show-ids display revision-ids (and file-ids), not just revnos
1859
2126
Note that the default number of levels to display is a function of the
1860
log format. If the -n option is not used, ``short`` and ``line`` show
1861
just the top level (mainline) while ``long`` shows all levels of merged
2127
log format. If the -n option is not used, the standard log formats show
2128
just the top level (mainline).
1864
2130
Status summaries are shown using status flags like A, M, etc. To see
1865
2131
the changes explained using words like ``added`` and ``modified``
1866
2132
instead, use the -vv option.
1868
2134
:Ordering control:
1870
2136
To display revisions from oldest to newest, use the --forward option.
1871
2137
In most cases, using this option will have little impact on the total
1872
2138
time taken to produce a log, though --forward does not incrementally
1873
2139
display revisions like --reverse does when it can.
1875
2141
:Revision filtering:
1877
2143
The -r option can be used to specify what revision or range of revisions
1878
2144
to filter against. The various forms are shown below::
1880
2146
-rX display revision X
1881
2147
-rX.. display revision X and later
1882
2148
-r..Y display up to and including revision Y
1883
2149
-rX..Y display from X to Y inclusive
1885
2151
See ``bzr help revisionspec`` for details on how to specify X and Y.
1886
2152
Some common examples are given below::
1888
2154
-r-1 show just the tip
1889
2155
-r-10.. show the last 10 mainline revisions
1890
2156
-rsubmit:.. show what's new on this branch
1891
2157
-rancestor:path.. show changes since the common ancestor of this
1892
2158
branch and the one at location path
1893
2159
-rdate:yesterday.. show changes since yesterday
1895
2161
When logging a range of revisions using -rX..Y, log starts at
1896
2162
revision Y and searches back in history through the primary
1897
2163
("left-hand") parents until it finds X. When logging just the
1900
2166
a nested merge revision and the log will be truncated accordingly.
1902
2168
:Path filtering:
1904
If a parameter is given and it's not a branch, the log will be filtered
1905
to show only those revisions that changed the nominated file or
2170
If parameters are given and the first one is not a branch, the log
2171
will be filtered to show only those revisions that changed the
2172
nominated files or directories.
1908
2174
Filenames are interpreted within their historical context. To log a
1909
2175
deleted file, specify a revision range so that the file existed at
1910
2176
the end or start of the range.
1912
2178
Historical context is also important when interpreting pathnames of
1913
2179
renamed files/directories. Consider the following example:
1915
2181
* revision 1: add tutorial.txt
1916
2182
* revision 2: modify tutorial.txt
1917
2183
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
1921
2187
* ``bzr log guide.txt`` will log the file added in revision 1
1923
2189
* ``bzr log tutorial.txt`` will log the new file added in revision 3
1925
2191
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
1926
2192
the original file in revision 2.
1928
2194
* ``bzr log -r2 -p guide.txt`` will display an error message as there
1929
2195
was no file called guide.txt in revision 2.
1931
2197
Renames are always followed by log. By design, there is no need to
1932
2198
explicitly ask for this (and no way to stop logging a file back
1933
2199
until it was last renamed).
1935
Note: If the path is a directory, only revisions that directly changed
1936
that directory object are currently shown. This is considered a bug.
1937
(Support for filtering against multiple files and for files within a
1938
directory is under development.)
1940
2201
:Other filtering:
1942
2203
The --message option can be used for finding revisions that match a
1943
2204
regular expression in a commit message.
1945
2206
:Tips & tricks:
1947
2208
GUI tools and IDEs are often better at exploring history than command
1948
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
1949
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
1950
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
1952
Web interfaces are often better at exploring history than command line
1953
tools, particularly for branches on servers. You may prefer Loggerhead
1954
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2209
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2210
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2211
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2212
<http://wiki.bazaar.canonical.com/IDEIntegration>.
1956
2214
You may find it useful to add the aliases below to ``bazaar.conf``::
1960
top = log -r-10.. --short --forward
1961
show = log -v -p -n1 --long
2218
top = log -l10 --line
1963
2221
``bzr tip`` will then show the latest revision while ``bzr top``
1964
2222
will show the last 10 mainline revisions. To see the details of a
1965
2223
particular revision X, ``bzr show -rX``.
1967
As many GUI tools and Web interfaces do, you may prefer viewing
1968
history collapsed initially. If you are interested in looking deeper
1969
into a particular merge X, use ``bzr log -n0 -rX``. If you like
1970
working this way, you may wish to either:
1972
* change your default log format to short (or line)
1973
* add this alias: log = log -n1
2225
If you are interested in looking deeper into a particular merge X,
2226
use ``bzr log -n0 -rX``.
1975
2228
``bzr log -v`` on a branch with lots of history is currently
1976
2229
very slow. A fix for this issue is currently under development.
1977
2230
With or without that fix, it is recommended that a revision range
1978
2231
be given when using the -v option.
1980
2233
bzr has a generic full-text matching plugin, bzr-search, that can be
1981
2234
used to find revisions matching user names, commit messages, etc.
1982
2235
Among other features, this plugin can find all revisions containing
1983
2236
a list of words but not others.
1985
2238
When exploring non-mainline history on large projects with deep
1986
2239
history, the performance of log can be greatly improved by installing
1987
the revnocache plugin. This plugin buffers historical information
2240
the historycache plugin. This plugin buffers historical information
1988
2241
trading disk space for faster speed.
1990
takes_args = ['location?']
2243
takes_args = ['file*']
1991
2244
_see_also = ['log-formats', 'revisionspec']
1992
2245
takes_options = [
1993
2246
Option('forward',
2072
2360
dir, relpath = bzrdir.BzrDir.open_containing(location)
2073
2361
b = dir.open_branch()
2362
self.add_cleanup(b.lock_read().unlock)
2077
2363
rev1, rev2 = _get_revision_range(revision, b, self.name())
2078
if log_format is None:
2079
log_format = log.log_formatter_registry.get_default(b)
2081
lf = log_format(show_ids=show_ids, to_file=self.outf,
2082
show_timezone=timezone,
2083
delta_format=get_verbosity_level(),
2090
direction=direction,
2091
start_revision=rev1,
2095
show_diff=show_diff)
2365
# Decide on the type of delta & diff filtering to use
2366
# TODO: add an --all-files option to make this configurable & consistent
2374
diff_type = 'partial'
2378
# Build the log formatter
2379
if log_format is None:
2380
log_format = log.log_formatter_registry.get_default(b)
2381
# Make a non-encoding output to include the diffs - bug 328007
2382
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2383
lf = log_format(show_ids=show_ids, to_file=self.outf,
2384
to_exact_file=unencoded_output,
2385
show_timezone=timezone,
2386
delta_format=get_verbosity_level(),
2388
show_advice=levels is None,
2389
author_list_handler=authors)
2391
# Choose the algorithm for doing the logging. It's annoying
2392
# having multiple code paths like this but necessary until
2393
# the underlying repository format is faster at generating
2394
# deltas or can provide everything we need from the indices.
2395
# The default algorithm - match-using-deltas - works for
2396
# multiple files and directories and is faster for small
2397
# amounts of history (200 revisions say). However, it's too
2398
# slow for logging a single file in a repository with deep
2399
# history, i.e. > 10K revisions. In the spirit of "do no
2400
# evil when adding features", we continue to use the
2401
# original algorithm - per-file-graph - for the "single
2402
# file that isn't a directory without showing a delta" case.
2403
partial_history = revision and b.repository._format.supports_chks
2404
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2405
or delta_type or partial_history)
2407
# Build the LogRequest and execute it
2408
if len(file_ids) == 0:
2410
rqst = make_log_request_dict(
2411
direction=direction, specific_fileids=file_ids,
2412
start_revision=rev1, end_revision=rev2, limit=limit,
2413
message_search=message, delta_type=delta_type,
2414
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2415
exclude_common_ancestry=exclude_common_ancestry,
2417
Logger(b, rqst).show(lf)
2100
2420
def _get_revision_range(revisionspec_list, branch, command_name):
2101
2421
"""Take the input of a revision option and turn it into a revision range.
2103
2423
It returns RevisionInfo objects which can be used to obtain the rev_id's
2104
of the desired revisons. It does some user input validations.
2424
of the desired revisions. It does some user input validations.
2106
2426
if revisionspec_list is None:
2164
2488
@display_command
2165
2489
def run(self, filename):
2166
2490
tree, relpath = WorkingTree.open_containing(filename)
2491
file_id = tree.path2id(relpath)
2167
2492
b = tree.branch
2168
file_id = tree.path2id(relpath)
2169
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2493
self.add_cleanup(b.lock_read().unlock)
2494
touching_revs = log.find_touching_revisions(b, file_id)
2495
for revno, revision_id, what in touching_revs:
2170
2496
self.outf.write("%6d %s\n" % (revno, what))
2173
2499
class cmd_ls(Command):
2174
"""List files in a tree.
2500
__doc__ = """List files in a tree.
2177
2503
_see_also = ['status', 'cat']
2178
2504
takes_args = ['path?']
2179
# TODO: Take a revision or remote path and list that tree instead.
2180
2505
takes_options = [
2183
Option('non-recursive',
2184
help='Don\'t recurse into subdirectories.'),
2508
Option('recursive', short_name='R',
2509
help='Recurse into subdirectories.'),
2185
2510
Option('from-root',
2186
2511
help='Print paths relative to the root of the branch.'),
2187
Option('unknown', help='Print unknown files.'),
2512
Option('unknown', short_name='u',
2513
help='Print unknown files.'),
2188
2514
Option('versioned', help='Print versioned files.',
2189
2515
short_name='V'),
2190
Option('ignored', help='Print ignored files.'),
2192
help='Write an ascii NUL (\\0) separator '
2193
'between files rather than a newline.'),
2516
Option('ignored', short_name='i',
2517
help='Print ignored files.'),
2518
Option('kind', short_name='k',
2195
2519
help='List entries of a particular kind: file, directory, symlink.',
2199
2525
@display_command
2200
2526
def run(self, revision=None, verbose=False,
2201
non_recursive=False, from_root=False,
2527
recursive=False, from_root=False,
2202
2528
unknown=False, versioned=False, ignored=False,
2203
null=False, kind=None, show_ids=False, path=None):
2529
null=False, kind=None, show_ids=False, path=None, directory=None):
2205
2531
if kind and kind not in ('file', 'directory', 'symlink'):
2206
2532
raise errors.BzrCommandError('invalid kind specified')
2214
2540
if path is None:
2219
2544
raise errors.BzrCommandError('cannot specify both --from-root'
2223
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2547
tree, branch, relpath = \
2548
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2550
# Calculate the prefix to use
2554
prefix = relpath + '/'
2555
elif fs_path != '.' and not fs_path.endswith('/'):
2556
prefix = fs_path + '/'
2229
2558
if revision is not None or tree is None:
2230
2559
tree = _get_one_revision_tree('ls', revision, branch=branch)
2234
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2235
if fp.startswith(relpath):
2236
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2237
if non_recursive and '/' in fp:
2239
if not all and not selection[fc]:
2241
if kind is not None and fkind != kind:
2243
kindch = entry.kind_character()
2244
outstring = fp + kindch
2246
outstring = '%-8s %s' % (fc, outstring)
2247
if show_ids and fid is not None:
2248
outstring = "%-50s %s" % (outstring, fid)
2249
self.outf.write(outstring + '\n')
2251
self.outf.write(fp + '\0')
2254
self.outf.write(fid)
2255
self.outf.write('\0')
2263
self.outf.write('%-50s %s\n' % (outstring, my_id))
2265
self.outf.write(outstring + '\n')
2562
if isinstance(tree, WorkingTree) and tree.supports_views():
2563
view_files = tree.views.lookup_view()
2566
view_str = views.view_display_str(view_files)
2567
note("Ignoring files outside view. View is %s" % view_str)
2569
self.add_cleanup(tree.lock_read().unlock)
2570
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2571
from_dir=relpath, recursive=recursive):
2572
# Apply additional masking
2573
if not all and not selection[fc]:
2575
if kind is not None and fkind != kind:
2580
fullpath = osutils.pathjoin(relpath, fp)
2583
views.check_path_in_view(tree, fullpath)
2584
except errors.FileOutsideView:
2589
fp = osutils.pathjoin(prefix, fp)
2590
kindch = entry.kind_character()
2591
outstring = fp + kindch
2592
ui.ui_factory.clear_term()
2594
outstring = '%-8s %s' % (fc, outstring)
2595
if show_ids and fid is not None:
2596
outstring = "%-50s %s" % (outstring, fid)
2597
self.outf.write(outstring + '\n')
2599
self.outf.write(fp + '\0')
2602
self.outf.write(fid)
2603
self.outf.write('\0')
2611
self.outf.write('%-50s %s\n' % (outstring, my_id))
2613
self.outf.write(outstring + '\n')
2270
2616
class cmd_unknowns(Command):
2271
"""List unknown files.
2617
__doc__ = """List unknown files.
2275
2621
_see_also = ['ls']
2622
takes_options = ['directory']
2277
2624
@display_command
2279
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2625
def run(self, directory=u'.'):
2626
for f in WorkingTree.open_containing(directory)[0].unknowns():
2280
2627
self.outf.write(osutils.quotefn(f) + '\n')
2283
2630
class cmd_ignore(Command):
2284
"""Ignore specified files or patterns.
2631
__doc__ = """Ignore specified files or patterns.
2286
2633
See ``bzr help patterns`` for details on the syntax of patterns.
2635
If a .bzrignore file does not exist, the ignore command
2636
will create one and add the specified files or patterns to the newly
2637
created file. The ignore command will also automatically add the
2638
.bzrignore file to be versioned. Creating a .bzrignore file without
2639
the use of the ignore command will require an explicit add command.
2288
2641
To remove patterns from the ignore list, edit the .bzrignore file.
2289
2642
After adding, editing or deleting that file either indirectly by
2290
2643
using this command or directly by using an editor, be sure to commit
2293
Note: ignore patterns containing shell wildcards must be quoted from
2646
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2647
the global ignore file can be found in the application data directory as
2648
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2649
Global ignores are not touched by this command. The global ignore file
2650
can be edited directly using an editor.
2652
Patterns prefixed with '!' are exceptions to ignore patterns and take
2653
precedence over regular ignores. Such exceptions are used to specify
2654
files that should be versioned which would otherwise be ignored.
2656
Patterns prefixed with '!!' act as regular ignore patterns, but have
2657
precedence over the '!' exception patterns.
2659
Note: ignore patterns containing shell wildcards must be quoted from
2294
2660
the shell on Unix.
2313
2683
Ignore everything but the "debian" toplevel directory::
2315
2685
bzr ignore "RE:(?!debian/).*"
2687
Ignore everything except the "local" toplevel directory,
2688
but always ignore "*~" autosave files, even under local/::
2691
bzr ignore "!./local"
2318
2695
_see_also = ['status', 'ignored', 'patterns']
2319
2696
takes_args = ['name_pattern*']
2321
Option('old-default-rules',
2322
help='Write out the ignore rules bzr < 0.9 always used.')
2697
takes_options = ['directory',
2698
Option('default-rules',
2699
help='Display the default ignore rules that bzr uses.')
2325
def run(self, name_pattern_list=None, old_default_rules=None):
2702
def run(self, name_pattern_list=None, default_rules=None,
2326
2704
from bzrlib import ignores
2327
if old_default_rules is not None:
2328
# dump the rules and exit
2329
for pattern in ignores.OLD_DEFAULTS:
2705
if default_rules is not None:
2706
# dump the default rules and exit
2707
for pattern in ignores.USER_DEFAULTS:
2708
self.outf.write("%s\n" % pattern)
2332
2710
if not name_pattern_list:
2333
2711
raise errors.BzrCommandError("ignore requires at least one "
2334
"NAME_PATTERN or --old-default-rules")
2335
name_pattern_list = [globbing.normalize_pattern(p)
2712
"NAME_PATTERN or --default-rules.")
2713
name_pattern_list = [globbing.normalize_pattern(p)
2336
2714
for p in name_pattern_list]
2337
2715
for name_pattern in name_pattern_list:
2338
if (name_pattern[0] == '/' or
2716
if (name_pattern[0] == '/' or
2339
2717
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2340
2718
raise errors.BzrCommandError(
2341
2719
"NAME_PATTERN should not be an absolute path")
2342
tree, relpath = WorkingTree.open_containing(u'.')
2720
tree, relpath = WorkingTree.open_containing(directory)
2343
2721
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2344
2722
ignored = globbing.Globster(name_pattern_list)
2457
2842
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2459
export(rev_tree, dest, format, root, subdir)
2844
export(rev_tree, dest, format, root, subdir, filtered=filters,
2845
per_file_timestamps=per_file_timestamps)
2460
2846
except errors.NoSuchExportFormat, e:
2461
2847
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2464
2850
class cmd_cat(Command):
2465
"""Write the contents of a file as of a given revision to standard output.
2851
__doc__ = """Write the contents of a file as of a given revision to standard output.
2467
2853
If no revision is nominated, the last revision is used.
2469
2855
Note: Take care to redirect standard output when using this command on a
2473
2859
_see_also = ['ls']
2860
takes_options = ['directory',
2475
2861
Option('name-from-revision', help='The path name in the old tree.'),
2862
Option('filters', help='Apply content filters to display the '
2863
'convenience form.'),
2478
2866
takes_args = ['filename']
2479
2867
encoding_type = 'exact'
2481
2869
@display_command
2482
def run(self, filename, revision=None, name_from_revision=False):
2870
def run(self, filename, revision=None, name_from_revision=False,
2871
filters=False, directory=None):
2483
2872
if revision is not None and len(revision) != 1:
2484
2873
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2485
2874
" one revision specifier")
2486
2875
tree, branch, relpath = \
2487
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2490
return self._run(tree, branch, relpath, filename, revision,
2876
_open_directory_or_containing_tree_or_branch(filename, directory)
2877
self.add_cleanup(branch.lock_read().unlock)
2878
return self._run(tree, branch, relpath, filename, revision,
2879
name_from_revision, filters)
2495
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2881
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2496
2883
if tree is None:
2497
2884
tree = b.basis_tree()
2498
2885
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2886
self.add_cleanup(rev_tree.lock_read().unlock)
2500
cur_file_id = tree.path2id(relpath)
2501
2888
old_file_id = rev_tree.path2id(relpath)
2503
2890
if name_from_revision:
2891
# Try in revision if requested
2504
2892
if old_file_id is None:
2505
2893
raise errors.BzrCommandError(
2506
2894
"%r is not present in revision %s" % (
2507
2895
filename, rev_tree.get_revision_id()))
2509
2897
content = rev_tree.get_file_text(old_file_id)
2510
elif cur_file_id is not None:
2511
content = rev_tree.get_file_text(cur_file_id)
2512
elif old_file_id is not None:
2513
content = rev_tree.get_file_text(old_file_id)
2515
raise errors.BzrCommandError(
2516
"%r is not present in revision %s" % (
2517
filename, rev_tree.get_revision_id()))
2518
self.outf.write(content)
2899
cur_file_id = tree.path2id(relpath)
2901
if cur_file_id is not None:
2902
# Then try with the actual file id
2904
content = rev_tree.get_file_text(cur_file_id)
2906
except errors.NoSuchId:
2907
# The actual file id didn't exist at that time
2909
if not found and old_file_id is not None:
2910
# Finally try with the old file id
2911
content = rev_tree.get_file_text(old_file_id)
2914
# Can't be found anywhere
2915
raise errors.BzrCommandError(
2916
"%r is not present in revision %s" % (
2917
filename, rev_tree.get_revision_id()))
2919
from bzrlib.filters import (
2920
ContentFilterContext,
2921
filtered_output_bytes,
2923
filters = rev_tree._content_filter_stack(relpath)
2924
chunks = content.splitlines(True)
2925
content = filtered_output_bytes(chunks, filters,
2926
ContentFilterContext(relpath, rev_tree))
2928
self.outf.writelines(content)
2931
self.outf.write(content)
2521
2934
class cmd_local_time_offset(Command):
2522
"""Show the offset in seconds from GMT to local time."""
2935
__doc__ = """Show the offset in seconds from GMT to local time."""
2524
2937
@display_command
2526
print osutils.local_time_offset()
2939
self.outf.write("%s\n" % osutils.local_time_offset())
2530
2943
class cmd_commit(Command):
2531
"""Commit changes into a new revision.
2533
If no arguments are given, the entire tree is committed.
2535
If selected files are specified, only changes to those files are
2536
committed. If a directory is specified then the directory and everything
2537
within it is committed.
2539
When excludes are given, they take precedence over selected files.
2540
For example, too commit only changes within foo, but not changes within
2543
bzr commit foo -x foo/bar
2545
If author of the change is not the same person as the committer, you can
2546
specify the author's name using the --author option. The name should be
2547
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2549
A selected-file commit may fail in some cases where the committed
2550
tree would be invalid. Consider::
2555
bzr commit foo -m "committing foo"
2556
bzr mv foo/bar foo/baz
2559
bzr commit foo/bar -m "committing bar but not baz"
2561
In the example above, the last commit will fail by design. This gives
2562
the user the opportunity to decide whether they want to commit the
2563
rename at the same time, separately first, or not at all. (As a general
2564
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2566
Note: A selected-file commit after a merge is not yet supported.
2944
__doc__ = """Commit changes into a new revision.
2946
An explanatory message needs to be given for each commit. This is
2947
often done by using the --message option (getting the message from the
2948
command line) or by using the --file option (getting the message from
2949
a file). If neither of these options is given, an editor is opened for
2950
the user to enter the message. To see the changed files in the
2951
boilerplate text loaded into the editor, use the --show-diff option.
2953
By default, the entire tree is committed and the person doing the
2954
commit is assumed to be the author. These defaults can be overridden
2959
If selected files are specified, only changes to those files are
2960
committed. If a directory is specified then the directory and
2961
everything within it is committed.
2963
When excludes are given, they take precedence over selected files.
2964
For example, to commit only changes within foo, but not changes
2967
bzr commit foo -x foo/bar
2969
A selective commit after a merge is not yet supported.
2973
If the author of the change is not the same person as the committer,
2974
you can specify the author's name using the --author option. The
2975
name should be in the same format as a committer-id, e.g.
2976
"John Doe <jdoe@example.com>". If there is more than one author of
2977
the change you can specify the option multiple times, once for each
2982
A common mistake is to forget to add a new file or directory before
2983
running the commit command. The --strict option checks for unknown
2984
files and aborts the commit if any are found. More advanced pre-commit
2985
checks can be implemented by defining hooks. See ``bzr help hooks``
2990
If you accidentially commit the wrong changes or make a spelling
2991
mistake in the commit message say, you can use the uncommit command
2992
to undo it. See ``bzr help uncommit`` for details.
2994
Hooks can also be configured to run after a commit. This allows you
2995
to trigger updates to external systems like bug trackers. The --fixes
2996
option can be used to record the association between a revision and
2997
one or more bugs. See ``bzr help bugs`` for details.
2999
A selective commit may fail in some cases where the committed
3000
tree would be invalid. Consider::
3005
bzr commit foo -m "committing foo"
3006
bzr mv foo/bar foo/baz
3009
bzr commit foo/bar -m "committing bar but not baz"
3011
In the example above, the last commit will fail by design. This gives
3012
the user the opportunity to decide whether they want to commit the
3013
rename at the same time, separately first, or not at all. (As a general
3014
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2568
3016
# TODO: Run hooks on tree to-be-committed, and after commit.
2603
3055
"the master branch until a normal commit "
2604
3056
"is performed."
2607
help='When no message is supplied, show the diff along'
2608
' with the status summary in the message editor.'),
3058
Option('show-diff', short_name='p',
3059
help='When no message is supplied, show the diff along'
3060
' with the status summary in the message editor.'),
2610
3062
aliases = ['ci', 'checkin']
2612
def _get_bug_fix_properties(self, fixes, branch):
3064
def _iter_bug_fix_urls(self, fixes, branch):
2614
3065
# Configure the properties for bug fixing attributes.
2615
3066
for fixed_bug in fixes:
2616
3067
tokens = fixed_bug.split(':')
2617
3068
if len(tokens) != 2:
2618
3069
raise errors.BzrCommandError(
2619
"Invalid bug %s. Must be in the form of 'tag:id'. "
2620
"Commit refused." % fixed_bug)
3070
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3071
"See \"bzr help bugs\" for more information on this "
3072
"feature.\nCommit refused." % fixed_bug)
2621
3073
tag, bug_id = tokens
2623
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
3075
yield bugtracker.get_bug_url(tag, branch, bug_id)
2624
3076
except errors.UnknownBugTrackerAbbreviation:
2625
3077
raise errors.BzrCommandError(
2626
3078
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2627
except errors.MalformedBugIdentifier:
3079
except errors.MalformedBugIdentifier, e:
2628
3080
raise errors.BzrCommandError(
2629
"Invalid bug identifier for %s. Commit refused."
2631
properties.append('%s fixed' % bug_url)
2632
return '\n'.join(properties)
3081
"%s\nCommit refused." % (str(e),))
2634
3083
def run(self, message=None, file=None, verbose=False, selected_list=None,
2635
3084
unchanged=False, strict=False, local=False, fixes=None,
2636
author=None, show_diff=False, exclude=None):
3085
author=None, show_diff=False, exclude=None, commit_time=None):
2637
3086
from bzrlib.errors import (
2638
3087
PointlessCommit,
2639
3088
ConflictsInTree,
2663
3120
if fixes is None:
2665
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
3122
bug_property = bugtracker.encode_fixes_bug_urls(
3123
self._iter_bug_fix_urls(fixes, tree.branch))
2666
3124
if bug_property:
2667
3125
properties['bugs'] = bug_property
2669
3127
if local and not tree.branch.get_bound_location():
2670
3128
raise errors.LocalRequiresBoundBranch()
3130
if message is not None:
3132
file_exists = osutils.lexists(message)
3133
except UnicodeError:
3134
# The commit message contains unicode characters that can't be
3135
# represented in the filesystem encoding, so that can't be a
3140
'The commit message is a file name: "%(f)s".\n'
3141
'(use --file "%(f)s" to take commit message from that file)'
3143
ui.ui_factory.show_warning(warning_msg)
3145
message = message.replace('\r\n', '\n')
3146
message = message.replace('\r', '\n')
3148
raise errors.BzrCommandError(
3149
"please specify either --message or --file")
2672
3151
def get_message(commit_obj):
2673
3152
"""Callback to get commit message"""
2674
my_message = message
2675
if my_message is None and not file:
2676
t = make_commit_message_template_encoded(tree,
3154
f = codecs.open(file, 'rt', osutils.get_user_encoding())
3156
my_message = f.read()
3159
elif message is not None:
3160
my_message = message
3162
# No message supplied: make one up.
3163
# text is the status of the tree
3164
text = make_commit_message_template_encoded(tree,
2677
3165
selected_list, diff=show_diff,
2678
3166
output_encoding=osutils.get_user_encoding())
3167
# start_message is the template generated from hooks
3168
# XXX: Warning - looks like hooks return unicode,
3169
# make_commit_message_template_encoded returns user encoding.
3170
# We probably want to be using edit_commit_message instead to
2679
3172
start_message = generate_commit_message_template(commit_obj)
2680
my_message = edit_commit_message_encoded(t,
3173
my_message = edit_commit_message_encoded(text,
2681
3174
start_message=start_message)
2682
3175
if my_message is None:
2683
3176
raise errors.BzrCommandError("please specify a commit"
2684
3177
" message with either --message or --file")
2685
elif my_message and file:
2686
raise errors.BzrCommandError(
2687
"please specify either --message or --file")
2689
my_message = codecs.open(file, 'rt',
2690
osutils.get_user_encoding()).read()
2691
3178
if my_message == "":
2692
3179
raise errors.BzrCommandError("empty commit message specified")
2693
3180
return my_message
3182
# The API permits a commit with a filter of [] to mean 'select nothing'
3183
# but the command line should not do that.
3184
if not selected_list:
3185
selected_list = None
2696
3187
tree.commit(message_callback=get_message,
2697
3188
specific_files=selected_list,
2698
3189
allow_pointless=unchanged, strict=strict, local=local,
2699
3190
reporter=None, verbose=verbose, revprops=properties,
3191
authors=author, timestamp=commit_stamp,
2701
3193
exclude=safe_relpath_files(tree, exclude))
2702
3194
except PointlessCommit:
2703
# FIXME: This should really happen before the file is read in;
2704
# perhaps prepare the commit; get the message; then actually commit
2705
raise errors.BzrCommandError("no changes to commit."
2706
" use --unchanged to commit anyhow")
3195
raise errors.BzrCommandError("No changes to commit."
3196
" Use --unchanged to commit anyhow.")
2707
3197
except ConflictsInTree:
2708
3198
raise errors.BzrCommandError('Conflicts detected in working '
2709
3199
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3063
3581
lsprof_timed=None, cache_dir=None,
3064
3582
first=False, list_only=False,
3065
3583
randomize=None, exclude=None, strict=False,
3066
load_list=None, debugflag=None, starting_with=None):
3067
from bzrlib.tests import selftest
3068
import bzrlib.benchmarks as benchmarks
3069
from bzrlib.benchmarks import tree_creator
3584
load_list=None, debugflag=None, starting_with=None, subunit=False,
3585
parallel=None, lsprof_tests=False):
3586
from bzrlib import (
3071
3591
# Make deprecation warnings visible, unless -Werror is set
3072
3592
symbol_versioning.activate_deprecation_warnings(override=False)
3074
3594
if cache_dir is not None:
3075
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3077
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
3078
print ' %s (%s python%s)' % (
3080
bzrlib.version_string,
3081
bzrlib._format_version_tuple(sys.version_info),
3595
benchmarks.tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(
3084
3597
if testspecs_list is not None:
3085
3598
pattern = '|'.join(testspecs_list)
3603
from bzrlib.tests import SubUnitBzrRunner
3605
raise errors.BzrCommandError("subunit not available. subunit "
3606
"needs to be installed to use --subunit.")
3607
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3608
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3609
# stdout, which would corrupt the subunit stream.
3610
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3611
# following code can be deleted when it's sufficiently deployed
3612
# -- vila/mgz 20100514
3613
if (sys.platform == "win32"
3614
and getattr(sys.stdout, 'fileno', None) is not None):
3616
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3618
self.additional_selftest_args.setdefault(
3619
'suite_decorators', []).append(parallel)
3089
3621
test_suite_factory = benchmarks.test_suite
3090
3622
# Unless user explicitly asks for quiet, be verbose in benchmarks
3091
3623
verbose = not is_quiet()
3092
3624
# TODO: should possibly lock the history file...
3093
3625
benchfile = open(".perf_history", "at", buffering=1)
3626
self.add_cleanup(benchfile.close)
3095
3628
test_suite_factory = None
3096
3629
benchfile = None
3098
selftest_kwargs = {"verbose": verbose,
3100
"stop_on_failure": one,
3101
"transport": transport,
3102
"test_suite_factory": test_suite_factory,
3103
"lsprof_timed": lsprof_timed,
3104
"bench_history": benchfile,
3105
"matching_tests_first": first,
3106
"list_only": list_only,
3107
"random_seed": randomize,
3108
"exclude_pattern": exclude,
3110
"load_list": load_list,
3111
"debug_flags": debugflag,
3112
"starting_with": starting_with
3114
selftest_kwargs.update(self.additional_selftest_args)
3115
result = selftest(**selftest_kwargs)
3117
if benchfile is not None:
3120
note('tests passed')
3122
note('tests failed')
3630
selftest_kwargs = {"verbose": verbose,
3632
"stop_on_failure": one,
3633
"transport": transport,
3634
"test_suite_factory": test_suite_factory,
3635
"lsprof_timed": lsprof_timed,
3636
"lsprof_tests": lsprof_tests,
3637
"bench_history": benchfile,
3638
"matching_tests_first": first,
3639
"list_only": list_only,
3640
"random_seed": randomize,
3641
"exclude_pattern": exclude,
3643
"load_list": load_list,
3644
"debug_flags": debugflag,
3645
"starting_with": starting_with
3647
selftest_kwargs.update(self.additional_selftest_args)
3648
result = tests.selftest(**selftest_kwargs)
3123
3649
return int(not result)
3126
3652
class cmd_version(Command):
3127
"""Show version of bzr."""
3653
__doc__ = """Show version of bzr."""
3129
3655
encoding_type = 'replace'
3130
3656
takes_options = [
3143
3669
class cmd_rocks(Command):
3144
"""Statement of optimism."""
3670
__doc__ = """Statement of optimism."""
3148
3674
@display_command
3150
print "It sure does!"
3676
self.outf.write("It sure does!\n")
3153
3679
class cmd_find_merge_base(Command):
3154
"""Find and print a base revision for merging two branches."""
3680
__doc__ = """Find and print a base revision for merging two branches."""
3155
3681
# TODO: Options to specify revisions on either side, as if
3156
3682
# merging only part of the history.
3157
3683
takes_args = ['branch', 'other']
3160
3686
@display_command
3161
3687
def run(self, branch, other):
3162
3688
from bzrlib.revision import ensure_null
3164
3690
branch1 = Branch.open_containing(branch)[0]
3165
3691
branch2 = Branch.open_containing(other)[0]
3170
last1 = ensure_null(branch1.last_revision())
3171
last2 = ensure_null(branch2.last_revision())
3173
graph = branch1.repository.get_graph(branch2.repository)
3174
base_rev_id = graph.find_unique_lca(last1, last2)
3176
print 'merge base is revision %s' % base_rev_id
3692
self.add_cleanup(branch1.lock_read().unlock)
3693
self.add_cleanup(branch2.lock_read().unlock)
3694
last1 = ensure_null(branch1.last_revision())
3695
last2 = ensure_null(branch2.last_revision())
3697
graph = branch1.repository.get_graph(branch2.repository)
3698
base_rev_id = graph.find_unique_lca(last1, last2)
3700
self.outf.write('merge base is revision %s\n' % base_rev_id)
3183
3703
class cmd_merge(Command):
3184
"""Perform a three-way merge.
3704
__doc__ = """Perform a three-way merge.
3186
3706
The source of the merge can be specified either in the form of a branch,
3187
3707
or in the form of a path to a file containing a merge directive generated
3188
3708
with bzr send. If neither is specified, the default is the upstream branch
3279
3815
allow_pending = True
3280
3816
verified = 'inapplicable'
3281
3817
tree = WorkingTree.open_containing(directory)[0]
3820
basis_tree = tree.revision_tree(tree.last_revision())
3821
except errors.NoSuchRevision:
3822
basis_tree = tree.basis_tree()
3824
# die as quickly as possible if there are uncommitted changes
3826
if tree.has_changes():
3827
raise errors.UncommittedChanges(tree)
3829
view_info = _get_view_info_for_change_reporter(tree)
3282
3830
change_reporter = delta._ChangeReporter(
3283
unversioned_filter=tree.is_ignored)
3286
pb = ui.ui_factory.nested_progress_bar()
3287
cleanups.append(pb.finished)
3289
cleanups.append(tree.unlock)
3290
if location is not None:
3292
mergeable = bundle.read_mergeable_from_url(location,
3293
possible_transports=possible_transports)
3294
except errors.NotABundle:
3298
raise errors.BzrCommandError('Cannot use --uncommitted'
3299
' with bundles or merge directives.')
3301
if revision is not None:
3302
raise errors.BzrCommandError(
3303
'Cannot use -r with merge directives or bundles')
3304
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3307
if merger is None and uncommitted:
3308
if revision is not None and len(revision) > 0:
3309
raise errors.BzrCommandError('Cannot use --uncommitted and'
3310
' --revision at the same time.')
3311
location = self._select_branch_location(tree, location)[0]
3312
other_tree, other_path = WorkingTree.open_containing(location)
3313
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3315
allow_pending = False
3316
if other_path != '':
3317
merger.interesting_files = [other_path]
3320
merger, allow_pending = self._get_merger_from_branch(tree,
3321
location, revision, remember, possible_transports, pb)
3323
merger.merge_type = merge_type
3324
merger.reprocess = reprocess
3325
merger.show_base = show_base
3326
self.sanity_check_merger(merger)
3327
if (merger.base_rev_id == merger.other_rev_id and
3328
merger.other_rev_id is not None):
3329
note('Nothing to do.')
3831
unversioned_filter=tree.is_ignored, view_info=view_info)
3832
pb = ui.ui_factory.nested_progress_bar()
3833
self.add_cleanup(pb.finished)
3834
self.add_cleanup(tree.lock_write().unlock)
3835
if location is not None:
3837
mergeable = bundle.read_mergeable_from_url(location,
3838
possible_transports=possible_transports)
3839
except errors.NotABundle:
3843
raise errors.BzrCommandError('Cannot use --uncommitted'
3844
' with bundles or merge directives.')
3846
if revision is not None:
3847
raise errors.BzrCommandError(
3848
'Cannot use -r with merge directives or bundles')
3849
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3852
if merger is None and uncommitted:
3853
if revision is not None and len(revision) > 0:
3854
raise errors.BzrCommandError('Cannot use --uncommitted and'
3855
' --revision at the same time.')
3856
merger = self.get_merger_from_uncommitted(tree, location, None)
3857
allow_pending = False
3860
merger, allow_pending = self._get_merger_from_branch(tree,
3861
location, revision, remember, possible_transports, None)
3863
merger.merge_type = merge_type
3864
merger.reprocess = reprocess
3865
merger.show_base = show_base
3866
self.sanity_check_merger(merger)
3867
if (merger.base_rev_id == merger.other_rev_id and
3868
merger.other_rev_id is not None):
3869
note('Nothing to do.')
3872
if merger.interesting_files is not None:
3873
raise errors.BzrCommandError('Cannot pull individual files')
3874
if (merger.base_rev_id == tree.last_revision()):
3875
result = tree.pull(merger.other_branch, False,
3876
merger.other_rev_id)
3877
result.report(self.outf)
3332
if merger.interesting_files is not None:
3333
raise errors.BzrCommandError('Cannot pull individual files')
3334
if (merger.base_rev_id == tree.last_revision()):
3335
result = tree.pull(merger.other_branch, False,
3336
merger.other_rev_id)
3337
result.report(self.outf)
3339
merger.check_basis(not force)
3341
return self._do_preview(merger)
3343
return self._do_merge(merger, change_reporter, allow_pending,
3346
for cleanup in reversed(cleanups):
3879
if merger.this_basis is None:
3880
raise errors.BzrCommandError(
3881
"This branch has no commits."
3882
" (perhaps you would prefer 'bzr pull')")
3884
return self._do_preview(merger)
3886
return self._do_interactive(merger)
3888
return self._do_merge(merger, change_reporter, allow_pending,
3891
def _get_preview(self, merger):
3892
tree_merger = merger.make_merger()
3893
tt = tree_merger.make_preview_transform()
3894
self.add_cleanup(tt.finalize)
3895
result_tree = tt.get_preview_tree()
3349
3898
def _do_preview(self, merger):
3350
3899
from bzrlib.diff import show_diff_trees
3351
tree_merger = merger.make_merger()
3352
tt = tree_merger.make_preview_transform()
3354
result_tree = tt.get_preview_tree()
3355
show_diff_trees(merger.this_tree, result_tree, self.outf,
3356
old_label='', new_label='')
3900
result_tree = self._get_preview(merger)
3901
path_encoding = osutils.get_diff_header_encoding()
3902
show_diff_trees(merger.this_tree, result_tree, self.outf,
3903
old_label='', new_label='',
3904
path_encoding=path_encoding)
3360
3906
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3361
3907
merger.change_reporter = change_reporter
3514
4092
def run(self, file_list=None, merge_type=None, show_base=False,
3515
4093
reprocess=False):
4094
from bzrlib.conflicts import restore
3516
4095
if merge_type is None:
3517
4096
merge_type = _mod_merge.Merge3Merger
3518
4097
tree, file_list = tree_files(file_list)
4098
self.add_cleanup(tree.lock_write().unlock)
4099
parents = tree.get_parent_ids()
4100
if len(parents) != 2:
4101
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4102
" merges. Not cherrypicking or"
4104
repository = tree.branch.repository
4105
interesting_ids = None
4107
conflicts = tree.conflicts()
4108
if file_list is not None:
4109
interesting_ids = set()
4110
for filename in file_list:
4111
file_id = tree.path2id(filename)
4113
raise errors.NotVersionedError(filename)
4114
interesting_ids.add(file_id)
4115
if tree.kind(file_id) != "directory":
4118
for name, ie in tree.inventory.iter_entries(file_id):
4119
interesting_ids.add(ie.file_id)
4120
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4122
# Remerge only supports resolving contents conflicts
4123
allowed_conflicts = ('text conflict', 'contents conflict')
4124
restore_files = [c.path for c in conflicts
4125
if c.typestring in allowed_conflicts]
4126
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4127
tree.set_conflicts(ConflictList(new_conflicts))
4128
if file_list is not None:
4129
restore_files = file_list
4130
for filename in restore_files:
4132
restore(tree.abspath(filename))
4133
except errors.NotConflicted:
4135
# Disable pending merges, because the file texts we are remerging
4136
# have not had those merges performed. If we use the wrong parents
4137
# list, we imply that the working tree text has seen and rejected
4138
# all the changes from the other tree, when in fact those changes
4139
# have not yet been seen.
4140
tree.set_parent_ids(parents[:1])
3521
parents = tree.get_parent_ids()
3522
if len(parents) != 2:
3523
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3524
" merges. Not cherrypicking or"
3526
repository = tree.branch.repository
3527
interesting_ids = None
3529
conflicts = tree.conflicts()
3530
if file_list is not None:
3531
interesting_ids = set()
3532
for filename in file_list:
3533
file_id = tree.path2id(filename)
3535
raise errors.NotVersionedError(filename)
3536
interesting_ids.add(file_id)
3537
if tree.kind(file_id) != "directory":
3540
for name, ie in tree.inventory.iter_entries(file_id):
3541
interesting_ids.add(ie.file_id)
3542
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3544
# Remerge only supports resolving contents conflicts
3545
allowed_conflicts = ('text conflict', 'contents conflict')
3546
restore_files = [c.path for c in conflicts
3547
if c.typestring in allowed_conflicts]
3548
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3549
tree.set_conflicts(ConflictList(new_conflicts))
3550
if file_list is not None:
3551
restore_files = file_list
3552
for filename in restore_files:
3554
restore(tree.abspath(filename))
3555
except errors.NotConflicted:
3557
# Disable pending merges, because the file texts we are remerging
3558
# have not had those merges performed. If we use the wrong parents
3559
# list, we imply that the working tree text has seen and rejected
3560
# all the changes from the other tree, when in fact those changes
3561
# have not yet been seen.
3562
pb = ui.ui_factory.nested_progress_bar()
3563
tree.set_parent_ids(parents[:1])
3565
merger = _mod_merge.Merger.from_revision_ids(pb,
3567
merger.interesting_ids = interesting_ids
3568
merger.merge_type = merge_type
3569
merger.show_base = show_base
3570
merger.reprocess = reprocess
3571
conflicts = merger.do_merge()
3573
tree.set_parent_ids(parents)
4142
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4143
merger.interesting_ids = interesting_ids
4144
merger.merge_type = merge_type
4145
merger.show_base = show_base
4146
merger.reprocess = reprocess
4147
conflicts = merger.do_merge()
4149
tree.set_parent_ids(parents)
3577
4150
if conflicts > 0:
3601
4174
name. If you name a directory, all the contents of that directory will be
3604
Any files that have been newly added since that revision will be deleted,
3605
with a backup kept if appropriate. Directories containing unknown files
3606
will not be deleted.
4177
If you have newly added files since the target revision, they will be
4178
removed. If the files to be removed have been changed, backups will be
4179
created as above. Directories containing unknown files will not be
3608
The working tree contains a list of pending merged revisions, which will
3609
be included as parents in the next commit. Normally, revert clears that
3610
list as well as reverting the files. If any files are specified, revert
3611
leaves the pending merge list alone and reverts only the files. Use "bzr
3612
revert ." in the tree root to revert all files but keep the merge record,
3613
and "bzr revert --forget-merges" to clear the pending merge list without
4182
The working tree contains a list of revisions that have been merged but
4183
not yet committed. These revisions will be included as additional parents
4184
of the next commit. Normally, using revert clears that list as well as
4185
reverting the files. If any files are specified, revert leaves the list
4186
of uncommitted merges alone and reverts only the files. Use ``bzr revert
4187
.`` in the tree root to revert all files but keep the recorded merges,
4188
and ``bzr revert --forget-merges`` to clear the pending merge list without
3614
4189
reverting any files.
4191
Using "bzr revert --forget-merges", it is possible to apply all of the
4192
changes from a branch in a single revision. To do this, perform the merge
4193
as desired. Then doing revert with the "--forget-merges" option will keep
4194
the content of the tree as it was, but it will clear the list of pending
4195
merges. The next commit will then contain all of the changes that are
4196
present in the other branch, but without any other parent revisions.
4197
Because this technique forgets where these changes originated, it may
4198
cause additional conflicts on later merges involving the same source and
3617
4202
_see_also = ['cat', 'export']
3793
4382
_get_revision_range(revision,
3794
4383
remote_branch, self.name()))
3796
local_branch.lock_read()
3798
remote_branch.lock_read()
3800
local_extra, remote_extra = find_unmerged(
3801
local_branch, remote_branch, restrict,
3802
backward=not reverse,
3803
include_merges=include_merges,
3804
local_revid_range=local_revid_range,
3805
remote_revid_range=remote_revid_range)
3807
if log_format is None:
3808
registry = log.log_formatter_registry
3809
log_format = registry.get_default(local_branch)
3810
lf = log_format(to_file=self.outf,
3812
show_timezone='original')
3815
if local_extra and not theirs_only:
3816
message("You have %d extra revision(s):\n" %
3818
for revision in iter_log_revisions(local_extra,
3819
local_branch.repository,
3821
lf.log_revision(revision)
3822
printed_local = True
3825
printed_local = False
3827
if remote_extra and not mine_only:
3828
if printed_local is True:
3830
message("You are missing %d revision(s):\n" %
3832
for revision in iter_log_revisions(remote_extra,
3833
remote_branch.repository,
3835
lf.log_revision(revision)
3838
if mine_only and not local_extra:
3839
# We checked local, and found nothing extra
3840
message('This branch is up to date.\n')
3841
elif theirs_only and not remote_extra:
3842
# We checked remote, and found nothing extra
3843
message('Other branch is up to date.\n')
3844
elif not (mine_only or theirs_only or local_extra or
3846
# We checked both branches, and neither one had extra
3848
message("Branches are up to date.\n")
3850
remote_branch.unlock()
3852
local_branch.unlock()
4385
local_extra, remote_extra = find_unmerged(
4386
local_branch, remote_branch, restrict,
4387
backward=not reverse,
4388
include_merges=include_merges,
4389
local_revid_range=local_revid_range,
4390
remote_revid_range=remote_revid_range)
4392
if log_format is None:
4393
registry = log.log_formatter_registry
4394
log_format = registry.get_default(local_branch)
4395
lf = log_format(to_file=self.outf,
4397
show_timezone='original')
4400
if local_extra and not theirs_only:
4401
message("You have %d extra revision(s):\n" %
4403
for revision in iter_log_revisions(local_extra,
4404
local_branch.repository,
4406
lf.log_revision(revision)
4407
printed_local = True
4410
printed_local = False
4412
if remote_extra and not mine_only:
4413
if printed_local is True:
4415
message("You are missing %d revision(s):\n" %
4417
for revision in iter_log_revisions(remote_extra,
4418
remote_branch.repository,
4420
lf.log_revision(revision)
4423
if mine_only and not local_extra:
4424
# We checked local, and found nothing extra
4425
message('This branch is up to date.\n')
4426
elif theirs_only and not remote_extra:
4427
# We checked remote, and found nothing extra
4428
message('Other branch is up to date.\n')
4429
elif not (mine_only or theirs_only or local_extra or
4431
# We checked both branches, and neither one had extra
4433
message("Branches are up to date.\n")
3853
4435
if not status_code and parent is None and other_branch is not None:
3854
local_branch.lock_write()
3856
# handle race conditions - a parent might be set while we run.
3857
if local_branch.get_parent() is None:
3858
local_branch.set_parent(remote_branch.base)
3860
local_branch.unlock()
4436
self.add_cleanup(local_branch.lock_write().unlock)
4437
# handle race conditions - a parent might be set while we run.
4438
if local_branch.get_parent() is None:
4439
local_branch.set_parent(remote_branch.base)
3861
4440
return status_code
3864
4443
class cmd_pack(Command):
3865
"""Compress the data within a repository."""
4444
__doc__ = """Compress the data within a repository.
4446
This operation compresses the data within a bazaar repository. As
4447
bazaar supports automatic packing of repository, this operation is
4448
normally not required to be done manually.
4450
During the pack operation, bazaar takes a backup of existing repository
4451
data, i.e. pack files. This backup is eventually removed by bazaar
4452
automatically when it is safe to do so. To save disk space by removing
4453
the backed up pack files, the --clean-obsolete-packs option may be
4456
Warning: If you use --clean-obsolete-packs and your machine crashes
4457
during or immediately after repacking, you may be left with a state
4458
where the deletion has been written to disk but the new packs have not
4459
been. In this case the repository may be unusable.
3867
4462
_see_also = ['repositories']
3868
4463
takes_args = ['branch_or_repo?']
4465
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
3870
def run(self, branch_or_repo='.'):
4468
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
3871
4469
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3873
4471
branch = dir.open_branch()
3874
4472
repository = branch.repository
3875
4473
except errors.NotBranchError:
3876
4474
repository = dir.open_repository()
4475
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
3880
4478
class cmd_plugins(Command):
3881
"""List the installed plugins.
4479
__doc__ = """List the installed plugins.
3883
4481
This command displays the list of installed plugins including
3884
4482
version of plugin and a short description of each.
3974
4569
Option('long', help='Show commit date in annotations.'),
3978
4574
encoding_type = 'exact'
3980
4576
@display_command
3981
4577
def run(self, filename, all=False, long=False, revision=None,
4578
show_ids=False, directory=None):
3983
4579
from bzrlib.annotate import annotate_file, annotate_file_tree
3984
4580
wt, branch, relpath = \
3985
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3991
tree = _get_one_revision_tree('annotate', revision, branch=branch)
3993
file_id = wt.path2id(relpath)
3995
file_id = tree.path2id(relpath)
3997
raise errors.NotVersionedError(filename)
3998
file_version = tree.inventory[file_id].revision
3999
if wt is not None and revision is None:
4000
# If there is a tree and we're not annotating historical
4001
# versions, annotate the working tree's content.
4002
annotate_file_tree(wt, file_id, self.outf, long, all,
4005
annotate_file(branch, file_version, file_id, long, all, self.outf,
4581
_open_directory_or_containing_tree_or_branch(filename, directory)
4583
self.add_cleanup(wt.lock_read().unlock)
4585
self.add_cleanup(branch.lock_read().unlock)
4586
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4587
self.add_cleanup(tree.lock_read().unlock)
4589
file_id = wt.path2id(relpath)
4591
file_id = tree.path2id(relpath)
4593
raise errors.NotVersionedError(filename)
4594
file_version = tree.inventory[file_id].revision
4595
if wt is not None and revision is None:
4596
# If there is a tree and we're not annotating historical
4597
# versions, annotate the working tree's content.
4598
annotate_file_tree(wt, file_id, self.outf, long, all,
4601
annotate_file(branch, file_version, file_id, long, all, self.outf,
4014
4605
class cmd_re_sign(Command):
4015
"""Create a digital signature for an existing revision."""
4606
__doc__ = """Create a digital signature for an existing revision."""
4016
4607
# TODO be able to replace existing ones.
4018
4609
hidden = True # is this right ?
4019
4610
takes_args = ['revision_id*']
4020
takes_options = ['revision']
4022
def run(self, revision_id_list=None, revision=None):
4611
takes_options = ['directory', 'revision']
4613
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4023
4614
if revision_id_list is not None and revision is not None:
4024
4615
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4025
4616
if revision_id_list is None and revision is None:
4026
4617
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4027
b = WorkingTree.open_containing(u'.')[0].branch
4030
return self._run(b, revision_id_list, revision)
4618
b = WorkingTree.open_containing(directory)[0].branch
4619
self.add_cleanup(b.lock_write().unlock)
4620
return self._run(b, revision_id_list, revision)
4034
4622
def _run(self, b, revision_id_list, revision):
4035
4623
import bzrlib.gpg as gpg
4287
4873
class cmd_serve(Command):
4288
"""Run the bzr server."""
4874
__doc__ = """Run the bzr server."""
4290
4876
aliases = ['server']
4292
4878
takes_options = [
4294
4880
help='Serve on stdin/out for use from inetd or sshd.'),
4881
RegistryOption('protocol',
4882
help="Protocol to serve.",
4883
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4884
value_switches=True),
4296
4886
help='Listen for connections on nominated port of the form '
4297
4887
'[hostname:]portnumber. Passing 0 as the port number will '
4298
'result in a dynamically allocated port. The default port is '
4888
'result in a dynamically allocated port. The default port '
4889
'depends on the protocol.',
4302
help='Serve contents of this directory.',
4891
custom_help('directory',
4892
help='Serve contents of this directory.'),
4304
4893
Option('allow-writes',
4305
4894
help='By default the server is a readonly server. Supplying '
4306
4895
'--allow-writes enables write access to the contents of '
4307
'the served directory and below.'
4896
'the served directory and below. Note that ``bzr serve`` '
4897
'does not perform authentication, so unless some form of '
4898
'external authentication is arranged supplying this '
4899
'option leads to global uncontrolled write access to your '
4311
def run_smart_server(self, smart_server):
4312
"""Run 'smart_server' forever, with no UI output at all."""
4313
# For the duration of this server, no UI output is permitted. note
4314
# that this may cause problems with blackbox tests. This should be
4315
# changed with care though, as we dont want to use bandwidth sending
4316
# progress over stderr to smart server clients!
4317
from bzrlib import lockdir
4318
old_factory = ui.ui_factory
4319
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4321
ui.ui_factory = ui.SilentUIFactory()
4322
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4323
smart_server.serve()
4325
ui.ui_factory = old_factory
4326
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4328
4904
def get_host_and_port(self, port):
4329
4905
"""Return the host and port to run the smart server on.
4331
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4332
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4907
If 'port' is None, None will be returned for the host and port.
4334
4909
If 'port' has a colon in it, the string before the colon will be
4335
4910
interpreted as the host.
4338
4913
:return: A tuple of (host, port), where 'host' is a host name or IP,
4339
4914
and port is an integer TCP/IP port.
4341
from bzrlib.smart import medium
4342
host = medium.BZR_DEFAULT_INTERFACE
4344
port = medium.BZR_DEFAULT_PORT
4917
if port is not None:
4346
4918
if ':' in port:
4347
4919
host, port = port.split(':')
4348
4920
port = int(port)
4349
4921
return host, port
4351
def get_smart_server(self, transport, inet, port):
4352
"""Construct a smart server.
4354
:param transport: The base transport from which branches will be
4356
:param inet: If True, serve over stdin and stdout. Used for running
4358
:param port: The port to listen on. By default, it's `
4359
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4361
:return: A smart server.
4363
from bzrlib.smart import medium, server
4365
smart_server = medium.SmartServerPipeStreamMedium(
4366
sys.stdin, sys.stdout, transport)
4368
host, port = self.get_host_and_port(port)
4369
smart_server = server.SmartTCPServer(
4370
transport, host=host, port=port)
4371
note('listening on port: %s' % smart_server.port)
4374
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4375
from bzrlib.transport import get_transport
4376
from bzrlib.transport.chroot import ChrootServer
4923
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4925
from bzrlib import transport
4377
4926
if directory is None:
4378
4927
directory = os.getcwd()
4928
if protocol is None:
4929
protocol = transport.transport_server_registry.get()
4930
host, port = self.get_host_and_port(port)
4379
4931
url = urlutils.local_path_to_url(directory)
4380
4932
if not allow_writes:
4381
4933
url = 'readonly+' + url
4382
chroot_server = ChrootServer(get_transport(url))
4383
chroot_server.setUp()
4384
t = get_transport(chroot_server.get_url())
4385
smart_server = self.get_smart_server(t, inet, port)
4386
self.run_smart_server(smart_server)
4934
t = transport.get_transport(url)
4935
protocol(t, host, port, inet)
4389
4938
class cmd_join(Command):
4390
"""Combine a subtree into its containing tree.
4392
This command is for experimental use only. It requires the target tree
4393
to be in dirstate-with-subtree format, which cannot be converted into
4939
__doc__ = """Combine a tree into its containing tree.
4941
This command requires the target tree to be in a rich-root format.
4396
4943
The TREE argument should be an independent tree, inside another tree, but
4397
4944
not part of it. (Such trees can be produced by "bzr split", but also by
4579
5121
directly from the merge directive, without retrieving data from a
4582
If --no-bundle is specified, then public_branch is needed (and must be
4583
up-to-date), so that the receiver can perform the merge using the
4584
public_branch. The public_branch is always included if known, so that
4585
people can check it later.
4587
The submit branch defaults to the parent, but can be overridden. Both
4588
submit branch and public branch will be remembered if supplied.
4590
If a public_branch is known for the submit_branch, that public submit
4591
branch is used in the merge instructions. This means that a local mirror
4592
can be used as your actual submit branch, once you have set public_branch
5124
`bzr send` creates a compact data set that, when applied using bzr
5125
merge, has the same effect as merging from the source branch.
5127
By default the merge directive is self-contained and can be applied to any
5128
branch containing submit_branch in its ancestory without needing access to
5131
If --no-bundle is specified, then Bazaar doesn't send the contents of the
5132
revisions, but only a structured request to merge from the
5133
public_location. In that case the public_branch is needed and it must be
5134
up-to-date and accessible to the recipient. The public_branch is always
5135
included if known, so that people can check it later.
5137
The submit branch defaults to the parent of the source branch, but can be
5138
overridden. Both submit branch and public branch will be remembered in
5139
branch.conf the first time they are used for a particular branch. The
5140
source branch defaults to that containing the working directory, but can
5141
be changed using --from.
5143
In order to calculate those changes, bzr must analyse the submit branch.
5144
Therefore it is most efficient for the submit branch to be a local mirror.
5145
If a public location is known for the submit_branch, that location is used
5146
in the merge directive.
5148
The default behaviour is to send the merge directive by mail, unless -o is
5149
given, in which case it is sent to a file.
4595
5151
Mail is sent using your preferred mail program. This should be transparent
4596
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5152
on Windows (it uses MAPI). On Unix, it requires the xdg-email utility.
4597
5153
If the preferred client can't be found (or used), your editor will be used.
4599
5155
To use a specific mail program, set the mail_client configuration option.
4600
5156
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4601
specific clients are "claws", "evolution", "kmail", "mutt", and
4602
"thunderbird"; generic options are "default", "editor", "emacsclient",
4603
"mapi", and "xdg-email". Plugins may also add supported clients.
5157
specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5158
Mail.app), "mutt", and "thunderbird"; generic options are "default",
5159
"editor", "emacsclient", "mapi", and "xdg-email". Plugins may also add
4605
5162
If mail is being sent, a to address is required. This can be supplied
4606
5163
either on the commandline, by setting the submit_to configuration
4607
option in the branch itself or the child_submit_to configuration option
5164
option in the branch itself or the child_submit_to configuration option
4608
5165
in the submit branch.
4610
5167
Two formats are currently supported: "4" uses revision bundle format 4 and
4635
5197
short_name='f',
4637
5199
Option('output', short_name='o',
4638
help='Write merge directive to this file; '
5200
help='Write merge directive to this file or directory; '
4639
5201
'use - for stdout.',
5204
help='Refuse to send if there are uncommitted changes in'
5205
' the working tree, --no-strict disables the check.'),
4641
5206
Option('mail-to', help='Mail the request to this address.',
4645
RegistryOption.from_kwargs('format',
4646
'Use the specified output format.',
4647
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4648
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5210
Option('body', help='Body for the email.', type=unicode),
5211
RegistryOption('format',
5212
help='Use the specified output format.',
5213
lazy_registry=('bzrlib.send', 'format_registry')),
4651
5216
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4652
5217
no_patch=False, revision=None, remember=False, output=None,
4653
format='4', mail_to=None, message=None, **kwargs):
4654
return self._run(submit_branch, revision, public_branch, remember,
4655
format, no_bundle, no_patch, output,
4656
kwargs.get('from', '.'), mail_to, message)
4658
def _run(self, submit_branch, revision, public_branch, remember, format,
4659
no_bundle, no_patch, output, from_, mail_to, message):
4660
from bzrlib.revision import NULL_REVISION
4661
branch = Branch.open_containing(from_)[0]
4663
outfile = cStringIO.StringIO()
4667
outfile = open(output, 'wb')
4668
# we may need to write data into branch's repository to calculate
4673
config = branch.get_config()
4675
mail_to = config.get_user_option('submit_to')
4676
mail_client = config.get_mail_client()
4677
if remember and submit_branch is None:
4678
raise errors.BzrCommandError(
4679
'--remember requires a branch to be specified.')
4680
stored_submit_branch = branch.get_submit_branch()
4681
remembered_submit_branch = None
4682
if submit_branch is None:
4683
submit_branch = stored_submit_branch
4684
remembered_submit_branch = "submit"
4686
if stored_submit_branch is None or remember:
4687
branch.set_submit_branch(submit_branch)
4688
if submit_branch is None:
4689
submit_branch = branch.get_parent()
4690
remembered_submit_branch = "parent"
4691
if submit_branch is None:
4692
raise errors.BzrCommandError('No submit branch known or'
4694
if remembered_submit_branch is not None:
4695
note('Using saved %s location "%s" to determine what '
4696
'changes to submit.', remembered_submit_branch,
4700
submit_config = Branch.open(submit_branch).get_config()
4701
mail_to = submit_config.get_user_option("child_submit_to")
4703
stored_public_branch = branch.get_public_branch()
4704
if public_branch is None:
4705
public_branch = stored_public_branch
4706
elif stored_public_branch is None or remember:
4707
branch.set_public_branch(public_branch)
4708
if no_bundle and public_branch is None:
4709
raise errors.BzrCommandError('No public branch specified or'
4711
base_revision_id = None
4713
if revision is not None:
4714
if len(revision) > 2:
4715
raise errors.BzrCommandError('bzr send takes '
4716
'at most two one revision identifiers')
4717
revision_id = revision[-1].as_revision_id(branch)
4718
if len(revision) == 2:
4719
base_revision_id = revision[0].as_revision_id(branch)
4720
if revision_id is None:
4721
revision_id = branch.last_revision()
4722
if revision_id == NULL_REVISION:
4723
raise errors.BzrCommandError('No revisions to submit.')
4725
directive = merge_directive.MergeDirective2.from_objects(
4726
branch.repository, revision_id, time.time(),
4727
osutils.local_time_offset(), submit_branch,
4728
public_branch=public_branch, include_patch=not no_patch,
4729
include_bundle=not no_bundle, message=message,
4730
base_revision_id=base_revision_id)
4731
elif format == '0.9':
4734
patch_type = 'bundle'
4736
raise errors.BzrCommandError('Format 0.9 does not'
4737
' permit bundle with no patch')
4743
directive = merge_directive.MergeDirective.from_objects(
4744
branch.repository, revision_id, time.time(),
4745
osutils.local_time_offset(), submit_branch,
4746
public_branch=public_branch, patch_type=patch_type,
4749
outfile.writelines(directive.to_lines())
4751
subject = '[MERGE] '
4752
if message is not None:
4755
revision = branch.repository.get_revision(revision_id)
4756
subject += revision.get_summary()
4757
basename = directive.get_disk_name(branch)
4758
mail_client.compose_merge_request(mail_to, subject,
4759
outfile.getvalue(), basename)
5218
format=None, mail_to=None, message=None, body=None,
5219
strict=None, **kwargs):
5220
from bzrlib.send import send
5221
return send(submit_branch, revision, public_branch, remember,
5222
format, no_bundle, no_patch, output,
5223
kwargs.get('from', '.'), mail_to, message, body,
4766
5228
class cmd_bundle_revisions(cmd_send):
4768
"""Create a merge-directive for submitting changes.
5229
__doc__ = """Create a merge-directive for submitting changes.
4770
5231
A merge directive provides many things needed for requesting merges:
4843
5308
Tags are stored in the branch. Tags are copied from one branch to another
4844
5309
along when you branch, push, pull or merge.
4846
It is an error to give a tag name that already exists unless you pass
5311
It is an error to give a tag name that already exists unless you pass
4847
5312
--force, in which case the tag is moved to point to the new revision.
4849
5314
To rename a tag (change the name but keep it on the same revsion), run ``bzr
4850
5315
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5317
If no tag name is specified it will be determined through the
5318
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5319
upstream releases by reading configure.ac. See ``bzr help hooks`` for
4853
5323
_see_also = ['commit', 'tags']
4854
takes_args = ['tag_name']
5324
takes_args = ['tag_name?']
4855
5325
takes_options = [
4856
5326
Option('delete',
4857
5327
help='Delete this tag rather than placing it.',
4860
help='Branch in which to place the tag.',
5329
custom_help('directory',
5330
help='Branch in which to place the tag.'),
4864
5331
Option('force',
4865
5332
help='Replace existing tags.',
4870
def run(self, tag_name,
5337
def run(self, tag_name=None,
4876
5343
branch, relpath = Branch.open_containing(directory)
4880
branch.tags.delete_tag(tag_name)
4881
self.outf.write('Deleted tag %s.\n' % tag_name)
5344
self.add_cleanup(branch.lock_write().unlock)
5346
if tag_name is None:
5347
raise errors.BzrCommandError("No tag specified to delete.")
5348
branch.tags.delete_tag(tag_name)
5349
self.outf.write('Deleted tag %s.\n' % tag_name)
5352
if len(revision) != 1:
5353
raise errors.BzrCommandError(
5354
"Tags can only be placed on a single revision, "
5356
revision_id = revision[0].as_revision_id(branch)
4884
if len(revision) != 1:
4885
raise errors.BzrCommandError(
4886
"Tags can only be placed on a single revision, "
4888
revision_id = revision[0].as_revision_id(branch)
4890
revision_id = branch.last_revision()
4891
if (not force) and branch.tags.has_tag(tag_name):
4892
raise errors.TagAlreadyExists(tag_name)
4893
branch.tags.set_tag(tag_name, revision_id)
4894
self.outf.write('Created tag %s.\n' % tag_name)
5358
revision_id = branch.last_revision()
5359
if tag_name is None:
5360
tag_name = branch.automatic_tag_name(revision_id)
5361
if tag_name is None:
5362
raise errors.BzrCommandError(
5363
"Please specify a tag name.")
5364
if (not force) and branch.tags.has_tag(tag_name):
5365
raise errors.TagAlreadyExists(tag_name)
5366
branch.tags.set_tag(tag_name, revision_id)
5367
self.outf.write('Created tag %s.\n' % tag_name)
4899
5370
class cmd_tags(Command):
5371
__doc__ = """List tags.
4902
5373
This command shows a table of tag names and the revisions they reference.
4905
5376
_see_also = ['tag']
4906
5377
takes_options = [
4908
help='Branch whose tags should be displayed.',
5378
custom_help('directory',
5379
help='Branch whose tags should be displayed.'),
4912
5380
RegistryOption.from_kwargs('sort',
4913
5381
'Sort tags by different criteria.', title='Sorting',
4914
5382
alpha='Sort tags lexicographically (default).',
5051
5547
/path/to/newbranch.
5053
5549
Bound branches use the nickname of its master branch unless it is set
5054
locally, in which case switching will update the the local nickname to be
5550
locally, in which case switching will update the local nickname to be
5055
5551
that of the master.
5058
takes_args = ['to_location']
5059
takes_options = [Option('force',
5060
help='Switch even if local commits will be lost.')
5554
takes_args = ['to_location?']
5555
takes_options = ['directory',
5557
help='Switch even if local commits will be lost.'),
5559
Option('create-branch', short_name='b',
5560
help='Create the target branch from this one before'
5561
' switching to it.'),
5063
def run(self, to_location, force=False):
5564
def run(self, to_location=None, force=False, create_branch=False,
5565
revision=None, directory=u'.'):
5064
5566
from bzrlib import switch
5567
tree_location = directory
5568
revision = _get_one_revision('switch', revision)
5066
5569
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5067
branch = control_dir.open_branch()
5570
if to_location is None:
5571
if revision is None:
5572
raise errors.BzrCommandError('You must supply either a'
5573
' revision or a location')
5574
to_location = tree_location
5069
to_branch = Branch.open(to_location)
5576
branch = control_dir.open_branch()
5577
had_explicit_nick = branch.get_config().has_explicit_nickname()
5070
5578
except errors.NotBranchError:
5071
this_branch = control_dir.open_branch()
5072
# This may be a heavy checkout, where we want the master branch
5073
this_url = this_branch.get_bound_location()
5074
# If not, use a local sibling
5075
if this_url is None:
5076
this_url = this_branch.base
5077
to_branch = Branch.open(
5078
urlutils.join(this_url, '..', to_location))
5079
switch.switch(control_dir, to_branch, force)
5080
if branch.get_config().has_explicit_nickname():
5580
had_explicit_nick = False
5583
raise errors.BzrCommandError('cannot create branch without'
5585
to_location = directory_service.directories.dereference(
5587
if '/' not in to_location and '\\' not in to_location:
5588
# This path is meant to be relative to the existing branch
5589
this_url = self._get_branch_location(control_dir)
5590
to_location = urlutils.join(this_url, '..', to_location)
5591
to_branch = branch.bzrdir.sprout(to_location,
5592
possible_transports=[branch.bzrdir.root_transport],
5593
source_branch=branch).open_branch()
5596
to_branch = Branch.open(to_location)
5597
except errors.NotBranchError:
5598
this_url = self._get_branch_location(control_dir)
5599
to_branch = Branch.open(
5600
urlutils.join(this_url, '..', to_location))
5601
if revision is not None:
5602
revision = revision.as_revision_id(to_branch)
5603
switch.switch(control_dir, to_branch, force, revision_id=revision)
5604
if had_explicit_nick:
5081
5605
branch = control_dir.open_branch() #get the new branch!
5082
5606
branch.nick = to_branch.nick
5083
5607
note('Switched to branch: %s',
5084
5608
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5610
def _get_branch_location(self, control_dir):
5611
"""Return location of branch for this control dir."""
5613
this_branch = control_dir.open_branch()
5614
# This may be a heavy checkout, where we want the master branch
5615
master_location = this_branch.get_bound_location()
5616
if master_location is not None:
5617
return master_location
5618
# If not, use a local sibling
5619
return this_branch.base
5620
except errors.NotBranchError:
5621
format = control_dir.find_branch_format()
5622
if getattr(format, 'get_reference', None) is not None:
5623
return format.get_reference(control_dir)
5625
return control_dir.root_transport.base
5628
class cmd_view(Command):
5629
__doc__ = """Manage filtered views.
5631
Views provide a mask over the tree so that users can focus on
5632
a subset of a tree when doing their work. After creating a view,
5633
commands that support a list of files - status, diff, commit, etc -
5634
effectively have that list of files implicitly given each time.
5635
An explicit list of files can still be given but those files
5636
must be within the current view.
5638
In most cases, a view has a short life-span: it is created to make
5639
a selected change and is deleted once that change is committed.
5640
At other times, you may wish to create one or more named views
5641
and switch between them.
5643
To disable the current view without deleting it, you can switch to
5644
the pseudo view called ``off``. This can be useful when you need
5645
to see the whole tree for an operation or two (e.g. merge) but
5646
want to switch back to your view after that.
5649
To define the current view::
5651
bzr view file1 dir1 ...
5653
To list the current view::
5657
To delete the current view::
5661
To disable the current view without deleting it::
5663
bzr view --switch off
5665
To define a named view and switch to it::
5667
bzr view --name view-name file1 dir1 ...
5669
To list a named view::
5671
bzr view --name view-name
5673
To delete a named view::
5675
bzr view --name view-name --delete
5677
To switch to a named view::
5679
bzr view --switch view-name
5681
To list all views defined::
5685
To delete all views::
5687
bzr view --delete --all
5691
takes_args = ['file*']
5694
help='Apply list or delete action to all views.',
5697
help='Delete the view.',
5700
help='Name of the view to define, list or delete.',
5704
help='Name of the view to switch to.',
5709
def run(self, file_list,
5715
tree, file_list = tree_files(file_list, apply_view=False)
5716
current_view, view_dict = tree.views.get_view_info()
5721
raise errors.BzrCommandError(
5722
"Both --delete and a file list specified")
5724
raise errors.BzrCommandError(
5725
"Both --delete and --switch specified")
5727
tree.views.set_view_info(None, {})
5728
self.outf.write("Deleted all views.\n")
5730
raise errors.BzrCommandError("No current view to delete")
5732
tree.views.delete_view(name)
5733
self.outf.write("Deleted '%s' view.\n" % name)
5736
raise errors.BzrCommandError(
5737
"Both --switch and a file list specified")
5739
raise errors.BzrCommandError(
5740
"Both --switch and --all specified")
5741
elif switch == 'off':
5742
if current_view is None:
5743
raise errors.BzrCommandError("No current view to disable")
5744
tree.views.set_view_info(None, view_dict)
5745
self.outf.write("Disabled '%s' view.\n" % (current_view))
5747
tree.views.set_view_info(switch, view_dict)
5748
view_str = views.view_display_str(tree.views.lookup_view())
5749
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5752
self.outf.write('Views defined:\n')
5753
for view in sorted(view_dict):
5754
if view == current_view:
5758
view_str = views.view_display_str(view_dict[view])
5759
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5761
self.outf.write('No views defined.\n')
5764
# No name given and no current view set
5767
raise errors.BzrCommandError(
5768
"Cannot change the 'off' pseudo view")
5769
tree.views.set_view(name, sorted(file_list))
5770
view_str = views.view_display_str(tree.views.lookup_view())
5771
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5775
# No name given and no current view set
5776
self.outf.write('No current view.\n')
5778
view_str = views.view_display_str(tree.views.lookup_view(name))
5779
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5087
5782
class cmd_hooks(Command):
5088
"""Show a branch's currently registered hooks.
5783
__doc__ = """Show hooks."""
5788
for hook_key in sorted(hooks.known_hooks.keys()):
5789
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5790
self.outf.write("%s:\n" % type(some_hooks).__name__)
5791
for hook_name, hook_point in sorted(some_hooks.items()):
5792
self.outf.write(" %s:\n" % (hook_name,))
5793
found_hooks = list(hook_point)
5795
for hook in found_hooks:
5796
self.outf.write(" %s\n" %
5797
(some_hooks.get_hook_name(hook),))
5799
self.outf.write(" <no hooks installed>\n")
5802
class cmd_remove_branch(Command):
5803
__doc__ = """Remove a branch.
5805
This will remove the branch from the specified location but
5806
will keep any working tree or repository in place.
5810
Remove the branch at repo/trunk::
5812
bzr remove-branch repo/trunk
5092
takes_args = ['path?']
5094
def run(self, path=None):
5097
branch_hooks = Branch.open(path).hooks
5098
for hook_type in branch_hooks:
5099
hooks = branch_hooks[hook_type]
5100
self.outf.write("%s:\n" % (hook_type,))
5103
self.outf.write(" %s\n" %
5104
(branch_hooks.get_hook_name(hook),))
5106
self.outf.write(" <no hooks installed>\n")
5816
takes_args = ["location?"]
5818
aliases = ["rmbranch"]
5820
def run(self, location=None):
5821
if location is None:
5823
branch = Branch.open_containing(location)[0]
5824
branch.bzrdir.destroy_branch()
5109
5827
class cmd_shelve(Command):
5110
"""Temporarily set aside some changes from the current tree.
5828
__doc__ = """Temporarily set aside some changes from the current tree.
5112
5830
Shelve allows you to temporarily put changes you've made "on the shelf",
5113
5831
ie. out of the way, until a later time when you can bring them back from
5142
5861
value_switches=True, enum_switch=False),
5144
5863
Option('list', help='List shelved changes.'),
5865
help='Destroy removed changes instead of shelving them.'),
5146
5867
_see_also = ['unshelve']
5148
5869
def run(self, revision=None, all=False, file_list=None, message=None,
5149
writer=None, list=False):
5870
writer=None, list=False, destroy=False, directory=u'.'):
5151
5872
return self.run_for_list()
5152
5873
from bzrlib.shelf_ui import Shelver
5153
5874
if writer is None:
5154
5875
writer = bzrlib.option.diff_writer_registry.get()
5156
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5877
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5878
file_list, message, destroy=destroy, directory=directory)
5158
5883
except errors.UserAbort:
5161
5886
def run_for_list(self):
5162
5887
tree = WorkingTree.open_containing('.')[0]
5165
manager = tree.get_shelf_manager()
5166
shelves = manager.active_shelves()
5167
if len(shelves) == 0:
5168
note('No shelved changes.')
5170
for shelf_id in reversed(shelves):
5171
message = manager.get_metadata(shelf_id).get('message')
5173
message = '<no message>'
5174
self.outf.write('%3d: %s\n' % (shelf_id, message))
5888
self.add_cleanup(tree.lock_read().unlock)
5889
manager = tree.get_shelf_manager()
5890
shelves = manager.active_shelves()
5891
if len(shelves) == 0:
5892
note('No shelved changes.')
5894
for shelf_id in reversed(shelves):
5895
message = manager.get_metadata(shelf_id).get('message')
5897
message = '<no message>'
5898
self.outf.write('%3d: %s\n' % (shelf_id, message))
5180
5902
class cmd_unshelve(Command):
5181
"""Restore shelved changes.
5903
__doc__ = """Restore shelved changes.
5183
5905
By default, the most recently shelved changes are restored. However if you
5184
5906
specify a shelf by id those changes will be restored instead. This works
5188
5910
takes_args = ['shelf_id?']
5189
5911
takes_options = [
5190
5913
RegistryOption.from_kwargs(
5191
5914
'action', help="The action to perform.",
5192
5915
enum_switch=False, value_switches=True,
5193
5916
apply="Apply changes and remove from the shelf.",
5194
5917
dry_run="Show changes, but do not apply or remove them.",
5195
delete_only="Delete changes without applying them."
5918
preview="Instead of unshelving the changes, show the diff that "
5919
"would result from unshelving.",
5920
delete_only="Delete changes without applying them.",
5921
keep="Apply changes but don't delete them.",
5198
5924
_see_also = ['shelve']
5200
def run(self, shelf_id=None, action='apply'):
5926
def run(self, shelf_id=None, action='apply', directory=u'.'):
5201
5927
from bzrlib.shelf_ui import Unshelver
5202
Unshelver.from_args(shelf_id, action).run()
5205
def _create_prefix(cur_transport):
5206
needed = [cur_transport]
5207
# Recurse upwards until we can create a directory successfully
5209
new_transport = cur_transport.clone('..')
5210
if new_transport.base == cur_transport.base:
5211
raise errors.BzrCommandError(
5212
"Failed to create path prefix for %s."
5213
% cur_transport.base)
5928
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5215
new_transport.mkdir('.')
5216
except errors.NoSuchFile:
5217
needed.append(new_transport)
5218
cur_transport = new_transport
5932
unshelver.tree.unlock()
5935
class cmd_clean_tree(Command):
5936
__doc__ = """Remove unwanted files from working tree.
5938
By default, only unknown files, not ignored files, are deleted. Versioned
5939
files are never deleted.
5941
Another class is 'detritus', which includes files emitted by bzr during
5942
normal operations and selftests. (The value of these files decreases with
5945
If no options are specified, unknown files are deleted. Otherwise, option
5946
flags are respected, and may be combined.
5948
To check what clean-tree will do, use --dry-run.
5950
takes_options = ['directory',
5951
Option('ignored', help='Delete all ignored files.'),
5952
Option('detritus', help='Delete conflict files, merge'
5953
' backups, and failed selftest dirs.'),
5955
help='Delete files unknown to bzr (default).'),
5956
Option('dry-run', help='Show files to delete instead of'
5958
Option('force', help='Do not prompt before deleting.')]
5959
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5960
force=False, directory=u'.'):
5961
from bzrlib.clean_tree import clean_tree
5962
if not (unknown or ignored or detritus):
5966
clean_tree(directory, unknown=unknown, ignored=ignored,
5967
detritus=detritus, dry_run=dry_run, no_prompt=force)
5970
class cmd_reference(Command):
5971
__doc__ = """list, view and set branch locations for nested trees.
5973
If no arguments are provided, lists the branch locations for nested trees.
5974
If one argument is provided, display the branch location for that tree.
5975
If two arguments are provided, set the branch location for that tree.
5980
takes_args = ['path?', 'location?']
5982
def run(self, path=None, location=None):
5984
if path is not None:
5986
tree, branch, relpath =(
5987
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5988
if path is not None:
5991
tree = branch.basis_tree()
5993
info = branch._get_all_reference_info().iteritems()
5994
self._display_reference_info(tree, branch, info)
5221
# Now we only need to create child directories
5223
cur_transport = needed.pop()
5224
cur_transport.ensure_base()
5227
# these get imported and then picked up by the scan for cmd_*
5228
# TODO: Some more consistent way to split command definitions across files;
5229
# we do need to load at least some information about them to know of
5230
# aliases. ideally we would avoid loading the implementation until the
5231
# details were needed.
5232
from bzrlib.cmd_version_info import cmd_version_info
5233
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5234
from bzrlib.bundle.commands import (
5237
from bzrlib.sign_my_commits import cmd_sign_my_commits
5238
from bzrlib.weave_commands import cmd_versionedfile_list, \
5239
cmd_weave_plan_merge, cmd_weave_merge_text
5996
file_id = tree.path2id(path)
5998
raise errors.NotVersionedError(path)
5999
if location is None:
6000
info = [(file_id, branch.get_reference_info(file_id))]
6001
self._display_reference_info(tree, branch, info)
6003
branch.set_reference_info(file_id, path, location)
6005
def _display_reference_info(self, tree, branch, info):
6007
for file_id, (path, location) in info:
6009
path = tree.id2path(file_id)
6010
except errors.NoSuchId:
6012
ref_list.append((path, location))
6013
for path, location in sorted(ref_list):
6014
self.outf.write('%s %s\n' % (path, location))
6017
def _register_lazy_builtins():
6018
# register lazy builtins from other modules; called at startup and should
6019
# be only called once.
6020
for (name, aliases, module_name) in [
6021
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6022
('cmd_dpush', [], 'bzrlib.foreign'),
6023
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6024
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6025
('cmd_conflicts', [], 'bzrlib.conflicts'),
6026
('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6028
builtin_command_registry.register_lazy(name, aliases, module_name)