1
# Copyright (C) 2004, 2005, 2006, 2007, 2008 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""builtin bzr commands"""
21
from bzrlib.lazy_import import lazy_import
22
lazy_import(globals(), """
43
revision as _mod_revision,
50
from bzrlib.branch import Branch
51
from bzrlib.conflicts import ConflictList
52
from bzrlib.revisionspec import RevisionSpec
53
from bzrlib.smtp_connection import SMTPConnection
54
from bzrlib.workingtree import WorkingTree
57
from bzrlib.commands import Command, display_command
58
from bzrlib.option import (
65
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
68
def tree_files(file_list, default_branch=u'.', canonicalize=True):
70
return internal_tree_files(file_list, default_branch, canonicalize)
71
except errors.FileInWrongBranch, e:
72
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
(e.path, file_list[0]))
76
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
81
rev_tree = tree.basis_tree()
83
rev_tree = branch.basis_tree()
85
if len(revisions) != 1:
86
raise errors.BzrCommandError(
87
'bzr %s --revision takes exactly one revision identifier' % (
89
rev_tree = revisions[0].as_tree(branch)
93
# XXX: Bad function name; should possibly also be a class method of
94
# WorkingTree rather than a function.
95
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True):
96
"""Convert command-line paths to a WorkingTree and relative paths.
98
This is typically used for command-line processors that take one or
99
more filenames, and infer the workingtree that contains them.
101
The filenames given are not required to exist.
103
:param file_list: Filenames to convert.
105
:param default_branch: Fallback tree path to use if file_list is empty or
108
:return: workingtree, [relative_paths]
110
if file_list is None or len(file_list) == 0:
111
return WorkingTree.open_containing(default_branch)[0], file_list
112
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
113
return tree, safe_relpath_files(tree, file_list, canonicalize)
116
def safe_relpath_files(tree, file_list, canonicalize=True):
117
"""Convert file_list into a list of relpaths in tree.
119
:param tree: A tree to operate on.
120
:param file_list: A list of user provided paths or None.
121
:return: A list of relative paths.
122
:raises errors.PathNotChild: When a provided path is in a different tree
125
if file_list is None:
128
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
129
# doesn't - fix that up here before we enter the loop.
131
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
134
for filename in file_list:
136
new_list.append(fixer(osutils.dereference_path(filename)))
137
except errors.PathNotChild:
138
raise errors.FileInWrongBranch(tree.branch, filename)
142
# TODO: Make sure no commands unconditionally use the working directory as a
143
# branch. If a filename argument is used, the first of them should be used to
144
# specify the branch. (Perhaps this can be factored out into some kind of
145
# Argument class, representing a file in a branch, where the first occurrence
148
class cmd_status(Command):
149
"""Display status summary.
151
This reports on versioned and unknown files, reporting them
152
grouped by state. Possible states are:
155
Versioned in the working copy but not in the previous revision.
158
Versioned in the previous revision but removed or deleted
162
Path of this file changed from the previous revision;
163
the text may also have changed. This includes files whose
164
parent directory was renamed.
167
Text has changed since the previous revision.
170
File kind has been changed (e.g. from file to directory).
173
Not versioned and not matching an ignore pattern.
175
To see ignored files use 'bzr ignored'. For details on the
176
changes to file texts, use 'bzr diff'.
178
Note that --short or -S gives status flags for each item, similar
179
to Subversion's status command. To get output similar to svn -q,
182
If no arguments are specified, the status of the entire working
183
directory is shown. Otherwise, only the status of the specified
184
files or directories is reported. If a directory is given, status
185
is reported for everything inside that directory.
187
Before merges are committed, the pending merge tip revisions are
188
shown. To see all pending merge revisions, use the -v option.
189
To skip the display of pending merge information altogether, use
190
the no-pending option or specify a file/directory.
192
If a revision argument is given, the status is calculated against
193
that revision, or between two revisions if two are provided.
196
# TODO: --no-recurse, --recurse options
198
takes_args = ['file*']
199
takes_options = ['show-ids', 'revision', 'change', 'verbose',
200
Option('short', help='Use short status indicators.',
202
Option('versioned', help='Only show versioned files.',
204
Option('no-pending', help='Don\'t show pending merges.',
207
aliases = ['st', 'stat']
209
encoding_type = 'replace'
210
_see_also = ['diff', 'revert', 'status-flags']
213
def run(self, show_ids=False, file_list=None, revision=None, short=False,
214
versioned=False, no_pending=False, verbose=False):
215
from bzrlib.status import show_tree_status
217
if revision and len(revision) > 2:
218
raise errors.BzrCommandError('bzr status --revision takes exactly'
219
' one or two revision specifiers')
221
tree, relfile_list = tree_files(file_list)
222
# Avoid asking for specific files when that is not needed.
223
if relfile_list == ['']:
225
# Don't disable pending merges for full trees other than '.'.
226
if file_list == ['.']:
228
# A specific path within a tree was given.
229
elif relfile_list is not None:
231
show_tree_status(tree, show_ids=show_ids,
232
specific_files=relfile_list, revision=revision,
233
to_file=self.outf, short=short, versioned=versioned,
234
show_pending=(not no_pending), verbose=verbose)
237
class cmd_cat_revision(Command):
238
"""Write out metadata for a revision.
240
The revision to print can either be specified by a specific
241
revision identifier, or you can use --revision.
245
takes_args = ['revision_id?']
246
takes_options = ['revision']
247
# cat-revision is more for frontends so should be exact
251
def run(self, revision_id=None, revision=None):
252
if revision_id is not None and revision is not None:
253
raise errors.BzrCommandError('You can only supply one of'
254
' revision_id or --revision')
255
if revision_id is None and revision is None:
256
raise errors.BzrCommandError('You must supply either'
257
' --revision or a revision_id')
258
b = WorkingTree.open_containing(u'.')[0].branch
260
# TODO: jam 20060112 should cat-revision always output utf-8?
261
if revision_id is not None:
262
revision_id = osutils.safe_revision_id(revision_id, warn=False)
264
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
265
except errors.NoSuchRevision:
266
msg = "The repository %s contains no revision %s." % (b.repository.base,
268
raise errors.BzrCommandError(msg)
269
elif revision is not None:
272
raise errors.BzrCommandError('You cannot specify a NULL'
274
rev_id = rev.as_revision_id(b)
275
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
278
class cmd_dump_btree(Command):
279
"""Dump the contents of a btree index file to stdout.
281
PATH is a btree index file, it can be any URL. This includes things like
282
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
284
By default, the tuples stored in the index file will be displayed. With
285
--raw, we will uncompress the pages, but otherwise display the raw bytes
289
# TODO: Do we want to dump the internal nodes as well?
290
# TODO: It would be nice to be able to dump the un-parsed information,
291
# rather than only going through iter_all_entries. However, this is
292
# good enough for a start
294
encoding_type = 'exact'
295
takes_args = ['path']
296
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
297
' rather than the parsed tuples.'),
300
def run(self, path, raw=False):
301
dirname, basename = osutils.split(path)
302
t = transport.get_transport(dirname)
304
self._dump_raw_bytes(t, basename)
306
self._dump_entries(t, basename)
308
def _get_index_and_bytes(self, trans, basename):
309
"""Create a BTreeGraphIndex and raw bytes."""
310
bt = btree_index.BTreeGraphIndex(trans, basename, None)
311
bytes = trans.get_bytes(basename)
312
bt._file = cStringIO.StringIO(bytes)
313
bt._size = len(bytes)
316
def _dump_raw_bytes(self, trans, basename):
319
# We need to parse at least the root node.
320
# This is because the first page of every row starts with an
321
# uncompressed header.
322
bt, bytes = self._get_index_and_bytes(trans, basename)
323
for page_idx, page_start in enumerate(xrange(0, len(bytes),
324
btree_index._PAGE_SIZE)):
325
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
326
page_bytes = bytes[page_start:page_end]
328
self.outf.write('Root node:\n')
329
header_end, data = bt._parse_header_from_bytes(page_bytes)
330
self.outf.write(page_bytes[:header_end])
332
self.outf.write('\nPage %d\n' % (page_idx,))
333
decomp_bytes = zlib.decompress(page_bytes)
334
self.outf.write(decomp_bytes)
335
self.outf.write('\n')
337
def _dump_entries(self, trans, basename):
339
st = trans.stat(basename)
340
except errors.TransportNotPossible:
341
# We can't stat, so we'll fake it because we have to do the 'get()'
343
bt, _ = self._get_index_and_bytes(trans, basename)
345
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
346
for node in bt.iter_all_entries():
347
# Node is made up of:
348
# (index, key, value, [references])
349
self.outf.write('%s\n' % (node[1:],))
352
class cmd_remove_tree(Command):
353
"""Remove the working tree from a given branch/checkout.
355
Since a lightweight checkout is little more than a working tree
356
this will refuse to run against one.
358
To re-create the working tree, use "bzr checkout".
360
_see_also = ['checkout', 'working-trees']
361
takes_args = ['location?']
364
help='Remove the working tree even if it has '
365
'uncommitted changes.'),
368
def run(self, location='.', force=False):
369
d = bzrdir.BzrDir.open(location)
372
working = d.open_workingtree()
373
except errors.NoWorkingTree:
374
raise errors.BzrCommandError("No working tree to remove")
375
except errors.NotLocalUrl:
376
raise errors.BzrCommandError("You cannot remove the working tree of a "
379
changes = working.changes_from(working.basis_tree())
380
if changes.has_changed():
381
raise errors.UncommittedChanges(working)
383
working_path = working.bzrdir.root_transport.base
384
branch_path = working.branch.bzrdir.root_transport.base
385
if working_path != branch_path:
386
raise errors.BzrCommandError("You cannot remove the working tree from "
387
"a lightweight checkout")
389
d.destroy_workingtree()
392
class cmd_revno(Command):
393
"""Show current revision number.
395
This is equal to the number of revisions on this branch.
399
takes_args = ['location?']
402
def run(self, location=u'.'):
403
self.outf.write(str(Branch.open_containing(location)[0].revno()))
404
self.outf.write('\n')
407
class cmd_revision_info(Command):
408
"""Show revision number and revision id for a given revision identifier.
411
takes_args = ['revision_info*']
415
help='Branch to examine, '
416
'rather than the one containing the working directory.',
423
def run(self, revision=None, directory=u'.', revision_info_list=[]):
426
if revision is not None:
427
revs.extend(revision)
428
if revision_info_list is not None:
429
for rev in revision_info_list:
430
revs.append(RevisionSpec.from_string(rev))
432
b = Branch.open_containing(directory)[0]
435
revs.append(RevisionSpec.from_string('-1'))
438
revision_id = rev.as_revision_id(b)
440
revno = '%4d' % (b.revision_id_to_revno(revision_id))
441
except errors.NoSuchRevision:
442
dotted_map = b.get_revision_id_to_revno_map()
443
revno = '.'.join(str(i) for i in dotted_map[revision_id])
444
print '%s %s' % (revno, revision_id)
447
class cmd_add(Command):
448
"""Add specified files or directories.
450
In non-recursive mode, all the named items are added, regardless
451
of whether they were previously ignored. A warning is given if
452
any of the named files are already versioned.
454
In recursive mode (the default), files are treated the same way
455
but the behaviour for directories is different. Directories that
456
are already versioned do not give a warning. All directories,
457
whether already versioned or not, are searched for files or
458
subdirectories that are neither versioned or ignored, and these
459
are added. This search proceeds recursively into versioned
460
directories. If no names are given '.' is assumed.
462
Therefore simply saying 'bzr add' will version all files that
463
are currently unknown.
465
Adding a file whose parent directory is not versioned will
466
implicitly add the parent, and so on up to the root. This means
467
you should never need to explicitly add a directory, they'll just
468
get added when you add a file in the directory.
470
--dry-run will show which files would be added, but not actually
473
--file-ids-from will try to use the file ids from the supplied path.
474
It looks up ids trying to find a matching parent directory with the
475
same filename, and then by pure path. This option is rarely needed
476
but can be useful when adding the same logical file into two
477
branches that will be merged later (without showing the two different
478
adds as a conflict). It is also useful when merging another project
479
into a subdirectory of this one.
481
takes_args = ['file*']
484
help="Don't recursively add the contents of directories."),
486
help="Show what would be done, but don't actually do anything."),
488
Option('file-ids-from',
490
help='Lookup file ids from this tree.'),
492
encoding_type = 'replace'
493
_see_also = ['remove']
495
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
500
if file_ids_from is not None:
502
base_tree, base_path = WorkingTree.open_containing(
504
except errors.NoWorkingTree:
505
base_branch, base_path = Branch.open_containing(
507
base_tree = base_branch.basis_tree()
509
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
510
to_file=self.outf, should_print=(not is_quiet()))
512
action = bzrlib.add.AddAction(to_file=self.outf,
513
should_print=(not is_quiet()))
516
base_tree.lock_read()
518
file_list = self._maybe_expand_globs(file_list)
520
tree = WorkingTree.open_containing(file_list[0])[0]
522
tree = WorkingTree.open_containing(u'.')[0]
523
added, ignored = tree.smart_add(file_list, not
524
no_recurse, action=action, save=not dry_run)
526
if base_tree is not None:
530
for glob in sorted(ignored.keys()):
531
for path in ignored[glob]:
532
self.outf.write("ignored %s matching \"%s\"\n"
536
for glob, paths in ignored.items():
537
match_len += len(paths)
538
self.outf.write("ignored %d file(s).\n" % match_len)
539
self.outf.write("If you wish to add some of these files,"
540
" please add them by name.\n")
543
class cmd_mkdir(Command):
544
"""Create a new versioned directory.
546
This is equivalent to creating the directory and then adding it.
549
takes_args = ['dir+']
550
encoding_type = 'replace'
552
def run(self, dir_list):
555
wt, dd = WorkingTree.open_containing(d)
557
self.outf.write('added %s\n' % d)
560
class cmd_relpath(Command):
561
"""Show path of a file relative to root"""
563
takes_args = ['filename']
567
def run(self, filename):
568
# TODO: jam 20050106 Can relpath return a munged path if
569
# sys.stdout encoding cannot represent it?
570
tree, relpath = WorkingTree.open_containing(filename)
571
self.outf.write(relpath)
572
self.outf.write('\n')
575
class cmd_inventory(Command):
576
"""Show inventory of the current working copy or a revision.
578
It is possible to limit the output to a particular entry
579
type using the --kind option. For example: --kind file.
581
It is also possible to restrict the list of files to a specific
582
set. For example: bzr inventory --show-ids this/file
591
help='List entries of a particular kind: file, directory, symlink.',
594
takes_args = ['file*']
597
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
598
if kind and kind not in ['file', 'directory', 'symlink']:
599
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
601
work_tree, file_list = tree_files(file_list)
602
work_tree.lock_read()
604
if revision is not None:
605
if len(revision) > 1:
606
raise errors.BzrCommandError(
607
'bzr inventory --revision takes exactly one revision'
609
tree = revision[0].as_tree(work_tree.branch)
611
extra_trees = [work_tree]
617
if file_list is not None:
618
file_ids = tree.paths2ids(file_list, trees=extra_trees,
619
require_versioned=True)
620
# find_ids_across_trees may include some paths that don't
622
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
623
for file_id in file_ids if file_id in tree)
625
entries = tree.inventory.entries()
628
if tree is not work_tree:
631
for path, entry in entries:
632
if kind and kind != entry.kind:
635
self.outf.write('%-50s %s\n' % (path, entry.file_id))
637
self.outf.write(path)
638
self.outf.write('\n')
641
class cmd_mv(Command):
642
"""Move or rename a file.
645
bzr mv OLDNAME NEWNAME
647
bzr mv SOURCE... DESTINATION
649
If the last argument is a versioned directory, all the other names
650
are moved into it. Otherwise, there must be exactly two arguments
651
and the file is changed to a new name.
653
If OLDNAME does not exist on the filesystem but is versioned and
654
NEWNAME does exist on the filesystem but is not versioned, mv
655
assumes that the file has been manually moved and only updates
656
its internal inventory to reflect that change.
657
The same is valid when moving many SOURCE files to a DESTINATION.
659
Files cannot be moved between branches.
662
takes_args = ['names*']
663
takes_options = [Option("after", help="Move only the bzr identifier"
664
" of the file, because the file has already been moved."),
666
aliases = ['move', 'rename']
667
encoding_type = 'replace'
669
def run(self, names_list, after=False):
670
if names_list is None:
673
if len(names_list) < 2:
674
raise errors.BzrCommandError("missing file argument")
675
tree, rel_names = tree_files(names_list, canonicalize=False)
678
self._run(tree, names_list, rel_names, after)
682
def _run(self, tree, names_list, rel_names, after):
683
into_existing = osutils.isdir(names_list[-1])
684
if into_existing and len(names_list) == 2:
686
# a. case-insensitive filesystem and change case of dir
687
# b. move directory after the fact (if the source used to be
688
# a directory, but now doesn't exist in the working tree
689
# and the target is an existing directory, just rename it)
690
if (not tree.case_sensitive
691
and rel_names[0].lower() == rel_names[1].lower()):
692
into_existing = False
695
# 'fix' the case of a potential 'from'
696
from_id = tree.path2id(
697
tree.get_canonical_inventory_path(rel_names[0]))
698
if (not osutils.lexists(names_list[0]) and
699
from_id and inv.get_file_kind(from_id) == "directory"):
700
into_existing = False
703
# move into existing directory
704
# All entries reference existing inventory items, so fix them up
705
# for cicp file-systems.
706
rel_names = tree.get_canonical_inventory_paths(rel_names)
707
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
708
self.outf.write("%s => %s\n" % pair)
710
if len(names_list) != 2:
711
raise errors.BzrCommandError('to mv multiple files the'
712
' destination must be a versioned'
715
# for cicp file-systems: the src references an existing inventory
717
src = tree.get_canonical_inventory_path(rel_names[0])
718
# Find the canonical version of the destination: In all cases, the
719
# parent of the target must be in the inventory, so we fetch the
720
# canonical version from there (we do not always *use* the
721
# canonicalized tail portion - we may be attempting to rename the
723
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
724
dest_parent = osutils.dirname(canon_dest)
725
spec_tail = osutils.basename(rel_names[1])
726
# For a CICP file-system, we need to avoid creating 2 inventory
727
# entries that differ only by case. So regardless of the case
728
# we *want* to use (ie, specified by the user or the file-system),
729
# we must always choose to use the case of any existing inventory
730
# items. The only exception to this is when we are attempting a
731
# case-only rename (ie, canonical versions of src and dest are
733
dest_id = tree.path2id(canon_dest)
734
if dest_id is None or tree.path2id(src) == dest_id:
735
# No existing item we care about, so work out what case we
736
# are actually going to use.
738
# If 'after' is specified, the tail must refer to a file on disk.
740
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
742
# pathjoin with an empty tail adds a slash, which breaks
744
dest_parent_fq = tree.basedir
746
dest_tail = osutils.canonical_relpath(
748
osutils.pathjoin(dest_parent_fq, spec_tail))
750
# not 'after', so case as specified is used
751
dest_tail = spec_tail
753
# Use the existing item so 'mv' fails with AlreadyVersioned.
754
dest_tail = os.path.basename(canon_dest)
755
dest = osutils.pathjoin(dest_parent, dest_tail)
756
mutter("attempting to move %s => %s", src, dest)
757
tree.rename_one(src, dest, after=after)
758
self.outf.write("%s => %s\n" % (src, dest))
761
class cmd_pull(Command):
762
"""Turn this branch into a mirror of another branch.
764
This command only works on branches that have not diverged. Branches are
765
considered diverged if the destination branch's most recent commit is one
766
that has not been merged (directly or indirectly) into the parent.
768
If branches have diverged, you can use 'bzr merge' to integrate the changes
769
from one into the other. Once one branch has merged, the other should
770
be able to pull it again.
772
If you want to forget your local changes and just update your branch to
773
match the remote one, use pull --overwrite.
775
If there is no default location set, the first pull will set it. After
776
that, you can omit the location to use the default. To change the
777
default, use --remember. The value will only be saved if the remote
778
location can be accessed.
780
Note: The location can be specified either in the form of a branch,
781
or in the form of a path to a file containing a merge directive generated
785
_see_also = ['push', 'update', 'status-flags']
786
takes_options = ['remember', 'overwrite', 'revision',
787
custom_help('verbose',
788
help='Show logs of pulled revisions.'),
790
help='Branch to pull into, '
791
'rather than the one containing the working directory.',
796
takes_args = ['location?']
797
encoding_type = 'replace'
799
def run(self, location=None, remember=False, overwrite=False,
800
revision=None, verbose=False,
802
# FIXME: too much stuff is in the command class
805
if directory is None:
808
tree_to = WorkingTree.open_containing(directory)[0]
809
branch_to = tree_to.branch
810
except errors.NoWorkingTree:
812
branch_to = Branch.open_containing(directory)[0]
814
possible_transports = []
815
if location is not None:
817
mergeable = bundle.read_mergeable_from_url(location,
818
possible_transports=possible_transports)
819
except errors.NotABundle:
822
stored_loc = branch_to.get_parent()
824
if stored_loc is None:
825
raise errors.BzrCommandError("No pull location known or"
828
display_url = urlutils.unescape_for_display(stored_loc,
831
self.outf.write("Using saved parent location: %s\n" % display_url)
832
location = stored_loc
834
if mergeable is not None:
835
if revision is not None:
836
raise errors.BzrCommandError(
837
'Cannot use -r with merge directives or bundles')
838
mergeable.install_revisions(branch_to.repository)
839
base_revision_id, revision_id, verified = \
840
mergeable.get_merge_request(branch_to.repository)
841
branch_from = branch_to
843
branch_from = Branch.open(location,
844
possible_transports=possible_transports)
846
if branch_to.get_parent() is None or remember:
847
branch_to.set_parent(branch_from.base)
849
if revision is not None:
850
if len(revision) == 1:
851
revision_id = revision[0].as_revision_id(branch_from)
853
raise errors.BzrCommandError(
854
'bzr pull --revision takes one value.')
856
branch_to.lock_write()
858
if tree_to is not None:
859
change_reporter = delta._ChangeReporter(
860
unversioned_filter=tree_to.is_ignored)
861
result = tree_to.pull(branch_from, overwrite, revision_id,
863
possible_transports=possible_transports)
865
result = branch_to.pull(branch_from, overwrite, revision_id)
867
result.report(self.outf)
868
if verbose and result.old_revid != result.new_revid:
869
log.show_branch_change(branch_to, self.outf, result.old_revno,
875
class cmd_push(Command):
876
"""Update a mirror of this branch.
878
The target branch will not have its working tree populated because this
879
is both expensive, and is not supported on remote file systems.
881
Some smart servers or protocols *may* put the working tree in place in
884
This command only works on branches that have not diverged. Branches are
885
considered diverged if the destination branch's most recent commit is one
886
that has not been merged (directly or indirectly) by the source branch.
888
If branches have diverged, you can use 'bzr push --overwrite' to replace
889
the other branch completely, discarding its unmerged changes.
891
If you want to ensure you have the different changes in the other branch,
892
do a merge (see bzr help merge) from the other branch, and commit that.
893
After that you will be able to do a push without '--overwrite'.
895
If there is no default push location set, the first push will set it.
896
After that, you can omit the location to use the default. To change the
897
default, use --remember. The value will only be saved if the remote
898
location can be accessed.
901
_see_also = ['pull', 'update', 'working-trees']
902
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
903
Option('create-prefix',
904
help='Create the path leading up to the branch '
905
'if it does not already exist.'),
907
help='Branch to push from, '
908
'rather than the one containing the working directory.',
912
Option('use-existing-dir',
913
help='By default push will fail if the target'
914
' directory exists, but does not already'
915
' have a control directory. This flag will'
916
' allow push to proceed.'),
918
help='Create a stacked branch that references the public location '
919
'of the parent branch.'),
921
help='Create a stacked branch that refers to another branch '
922
'for the commit history. Only the work not present in the '
923
'referenced branch is included in the branch created.',
926
takes_args = ['location?']
927
encoding_type = 'replace'
929
def run(self, location=None, remember=False, overwrite=False,
930
create_prefix=False, verbose=False, revision=None,
931
use_existing_dir=False, directory=None, stacked_on=None,
933
from bzrlib.push import _show_push_branch
935
# Get the source branch and revision_id
936
if directory is None:
938
br_from = Branch.open_containing(directory)[0]
939
if revision is not None:
940
if len(revision) == 1:
941
revision_id = revision[0].in_history(br_from).rev_id
943
raise errors.BzrCommandError(
944
'bzr push --revision takes one value.')
946
revision_id = br_from.last_revision()
948
# Get the stacked_on branch, if any
949
if stacked_on is not None:
950
stacked_on = urlutils.normalize_url(stacked_on)
952
parent_url = br_from.get_parent()
954
parent = Branch.open(parent_url)
955
stacked_on = parent.get_public_branch()
957
# I considered excluding non-http url's here, thus forcing
958
# 'public' branches only, but that only works for some
959
# users, so it's best to just depend on the user spotting an
960
# error by the feedback given to them. RBC 20080227.
961
stacked_on = parent_url
963
raise errors.BzrCommandError(
964
"Could not determine branch to refer to.")
966
# Get the destination location
968
stored_loc = br_from.get_push_location()
969
if stored_loc is None:
970
raise errors.BzrCommandError(
971
"No push location known or specified.")
973
display_url = urlutils.unescape_for_display(stored_loc,
975
self.outf.write("Using saved push location: %s\n" % display_url)
976
location = stored_loc
978
_show_push_branch(br_from, revision_id, location, self.outf,
979
verbose=verbose, overwrite=overwrite, remember=remember,
980
stacked_on=stacked_on, create_prefix=create_prefix,
981
use_existing_dir=use_existing_dir)
984
class cmd_branch(Command):
985
"""Create a new copy of a branch.
987
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
988
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
989
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
990
is derived from the FROM_LOCATION by stripping a leading scheme or drive
991
identifier, if any. For example, "branch lp:foo-bar" will attempt to
994
To retrieve the branch as of a particular revision, supply the --revision
995
parameter, as in "branch foo/bar -r 5".
998
_see_also = ['checkout']
999
takes_args = ['from_location', 'to_location?']
1000
takes_options = ['revision', Option('hardlink',
1001
help='Hard-link working tree files where possible.'),
1003
help='Create a stacked branch referring to the source branch. '
1004
'The new branch will depend on the availability of the source '
1005
'branch for all operations.'),
1006
Option('standalone',
1007
help='Do not use a shared repository, even if available.'),
1009
aliases = ['get', 'clone']
1011
def run(self, from_location, to_location=None, revision=None,
1012
hardlink=False, stacked=False, standalone=False):
1013
from bzrlib.tag import _merge_tags_if_possible
1014
if revision is None:
1016
elif len(revision) > 1:
1017
raise errors.BzrCommandError(
1018
'bzr branch --revision takes exactly 1 revision value')
1020
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1024
if len(revision) == 1 and revision[0] is not None:
1025
revision_id = revision[0].as_revision_id(br_from)
1027
# FIXME - wt.last_revision, fallback to branch, fall back to
1028
# None or perhaps NULL_REVISION to mean copy nothing
1030
revision_id = br_from.last_revision()
1031
if to_location is None:
1032
to_location = urlutils.derive_to_location(from_location)
1033
to_transport = transport.get_transport(to_location)
1035
to_transport.mkdir('.')
1036
except errors.FileExists:
1037
raise errors.BzrCommandError('Target directory "%s" already'
1038
' exists.' % to_location)
1039
except errors.NoSuchFile:
1040
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1043
# preserve whatever source format we have.
1044
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1045
possible_transports=[to_transport],
1046
accelerator_tree=accelerator_tree,
1047
hardlink=hardlink, stacked=stacked,
1048
force_new_repo=standalone,
1049
source_branch=br_from)
1050
branch = dir.open_branch()
1051
except errors.NoSuchRevision:
1052
to_transport.delete_tree('.')
1053
msg = "The branch %s has no revision %s." % (from_location,
1055
raise errors.BzrCommandError(msg)
1056
_merge_tags_if_possible(br_from, branch)
1057
# If the source branch is stacked, the new branch may
1058
# be stacked whether we asked for that explicitly or not.
1059
# We therefore need a try/except here and not just 'if stacked:'
1061
note('Created new stacked branch referring to %s.' %
1062
branch.get_stacked_on_url())
1063
except (errors.NotStacked, errors.UnstackableBranchFormat,
1064
errors.UnstackableRepositoryFormat), e:
1065
note('Branched %d revision(s).' % branch.revno())
1070
class cmd_checkout(Command):
1071
"""Create a new checkout of an existing branch.
1073
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1074
the branch found in '.'. This is useful if you have removed the working tree
1075
or if it was never created - i.e. if you pushed the branch to its current
1076
location using SFTP.
1078
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1079
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1080
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1081
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
1082
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
1085
To retrieve the branch as of a particular revision, supply the --revision
1086
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
1087
out of date [so you cannot commit] but it may be useful (i.e. to examine old
1091
_see_also = ['checkouts', 'branch']
1092
takes_args = ['branch_location?', 'to_location?']
1093
takes_options = ['revision',
1094
Option('lightweight',
1095
help="Perform a lightweight checkout. Lightweight "
1096
"checkouts depend on access to the branch for "
1097
"every operation. Normal checkouts can perform "
1098
"common operations like diff and status without "
1099
"such access, and also support local commits."
1101
Option('files-from', type=str,
1102
help="Get file contents from this tree."),
1104
help='Hard-link working tree files where possible.'
1109
def run(self, branch_location=None, to_location=None, revision=None,
1110
lightweight=False, files_from=None, hardlink=False):
1111
if revision is None:
1113
elif len(revision) > 1:
1114
raise errors.BzrCommandError(
1115
'bzr checkout --revision takes exactly 1 revision value')
1116
if branch_location is None:
1117
branch_location = osutils.getcwd()
1118
to_location = branch_location
1119
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1121
if files_from is not None:
1122
accelerator_tree = WorkingTree.open(files_from)
1123
if len(revision) == 1 and revision[0] is not None:
1124
revision_id = revision[0].as_revision_id(source)
1127
if to_location is None:
1128
to_location = urlutils.derive_to_location(branch_location)
1129
# if the source and to_location are the same,
1130
# and there is no working tree,
1131
# then reconstitute a branch
1132
if (osutils.abspath(to_location) ==
1133
osutils.abspath(branch_location)):
1135
source.bzrdir.open_workingtree()
1136
except errors.NoWorkingTree:
1137
source.bzrdir.create_workingtree(revision_id)
1139
source.create_checkout(to_location, revision_id, lightweight,
1140
accelerator_tree, hardlink)
1143
class cmd_renames(Command):
1144
"""Show list of renamed files.
1146
# TODO: Option to show renames between two historical versions.
1148
# TODO: Only show renames under dir, rather than in the whole branch.
1149
_see_also = ['status']
1150
takes_args = ['dir?']
1153
def run(self, dir=u'.'):
1154
tree = WorkingTree.open_containing(dir)[0]
1157
new_inv = tree.inventory
1158
old_tree = tree.basis_tree()
1159
old_tree.lock_read()
1161
old_inv = old_tree.inventory
1163
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1164
for f, paths, c, v, p, n, k, e in iterator:
1165
if paths[0] == paths[1]:
1169
renames.append(paths)
1171
for old_name, new_name in renames:
1172
self.outf.write("%s => %s\n" % (old_name, new_name))
1179
class cmd_update(Command):
1180
"""Update a tree to have the latest code committed to its branch.
1182
This will perform a merge into the working tree, and may generate
1183
conflicts. If you have any local changes, you will still
1184
need to commit them after the update for the update to be complete.
1186
If you want to discard your local changes, you can just do a
1187
'bzr revert' instead of 'bzr commit' after the update.
1190
_see_also = ['pull', 'working-trees', 'status-flags']
1191
takes_args = ['dir?']
1194
def run(self, dir='.'):
1195
tree = WorkingTree.open_containing(dir)[0]
1196
possible_transports = []
1197
master = tree.branch.get_master_branch(
1198
possible_transports=possible_transports)
1199
if master is not None:
1202
tree.lock_tree_write()
1204
existing_pending_merges = tree.get_parent_ids()[1:]
1205
last_rev = _mod_revision.ensure_null(tree.last_revision())
1206
if last_rev == _mod_revision.ensure_null(
1207
tree.branch.last_revision()):
1208
# may be up to date, check master too.
1209
if master is None or last_rev == _mod_revision.ensure_null(
1210
master.last_revision()):
1211
revno = tree.branch.revision_id_to_revno(last_rev)
1212
note("Tree is up to date at revision %d." % (revno,))
1214
conflicts = tree.update(
1215
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1216
possible_transports=possible_transports)
1217
revno = tree.branch.revision_id_to_revno(
1218
_mod_revision.ensure_null(tree.last_revision()))
1219
note('Updated to revision %d.' % (revno,))
1220
if tree.get_parent_ids()[1:] != existing_pending_merges:
1221
note('Your local commits will now show as pending merges with '
1222
"'bzr status', and can be committed with 'bzr commit'.")
1231
class cmd_info(Command):
1232
"""Show information about a working tree, branch or repository.
1234
This command will show all known locations and formats associated to the
1235
tree, branch or repository. Statistical information is included with
1238
Branches and working trees will also report any missing revisions.
1240
_see_also = ['revno', 'working-trees', 'repositories']
1241
takes_args = ['location?']
1242
takes_options = ['verbose']
1243
encoding_type = 'replace'
1246
def run(self, location=None, verbose=False):
1251
from bzrlib.info import show_bzrdir_info
1252
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1253
verbose=noise_level, outfile=self.outf)
1256
class cmd_remove(Command):
1257
"""Remove files or directories.
1259
This makes bzr stop tracking changes to the specified files. bzr will delete
1260
them if they can easily be recovered using revert. If no options or
1261
parameters are given bzr will scan for files that are being tracked by bzr
1262
but missing in your tree and stop tracking them for you.
1264
takes_args = ['file*']
1265
takes_options = ['verbose',
1266
Option('new', help='Only remove files that have never been committed.'),
1267
RegistryOption.from_kwargs('file-deletion-strategy',
1268
'The file deletion mode to be used.',
1269
title='Deletion Strategy', value_switches=True, enum_switch=False,
1270
safe='Only delete files if they can be'
1271
' safely recovered (default).',
1272
keep="Don't delete any files.",
1273
force='Delete all the specified files, even if they can not be '
1274
'recovered and even if they are non-empty directories.')]
1275
aliases = ['rm', 'del']
1276
encoding_type = 'replace'
1278
def run(self, file_list, verbose=False, new=False,
1279
file_deletion_strategy='safe'):
1280
tree, file_list = tree_files(file_list)
1282
if file_list is not None:
1283
file_list = [f for f in file_list]
1287
# Heuristics should probably all move into tree.remove_smart or
1290
added = tree.changes_from(tree.basis_tree(),
1291
specific_files=file_list).added
1292
file_list = sorted([f[0] for f in added], reverse=True)
1293
if len(file_list) == 0:
1294
raise errors.BzrCommandError('No matching files.')
1295
elif file_list is None:
1296
# missing files show up in iter_changes(basis) as
1297
# versioned-with-no-kind.
1299
for change in tree.iter_changes(tree.basis_tree()):
1300
# Find paths in the working tree that have no kind:
1301
if change[1][1] is not None and change[6][1] is None:
1302
missing.append(change[1][1])
1303
file_list = sorted(missing, reverse=True)
1304
file_deletion_strategy = 'keep'
1305
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1306
keep_files=file_deletion_strategy=='keep',
1307
force=file_deletion_strategy=='force')
1312
class cmd_file_id(Command):
1313
"""Print file_id of a particular file or directory.
1315
The file_id is assigned when the file is first added and remains the
1316
same through all revisions where the file exists, even when it is
1321
_see_also = ['inventory', 'ls']
1322
takes_args = ['filename']
1325
def run(self, filename):
1326
tree, relpath = WorkingTree.open_containing(filename)
1327
i = tree.path2id(relpath)
1329
raise errors.NotVersionedError(filename)
1331
self.outf.write(i + '\n')
1334
class cmd_file_path(Command):
1335
"""Print path of file_ids to a file or directory.
1337
This prints one line for each directory down to the target,
1338
starting at the branch root.
1342
takes_args = ['filename']
1345
def run(self, filename):
1346
tree, relpath = WorkingTree.open_containing(filename)
1347
fid = tree.path2id(relpath)
1349
raise errors.NotVersionedError(filename)
1350
segments = osutils.splitpath(relpath)
1351
for pos in range(1, len(segments) + 1):
1352
path = osutils.joinpath(segments[:pos])
1353
self.outf.write("%s\n" % tree.path2id(path))
1356
class cmd_reconcile(Command):
1357
"""Reconcile bzr metadata in a branch.
1359
This can correct data mismatches that may have been caused by
1360
previous ghost operations or bzr upgrades. You should only
1361
need to run this command if 'bzr check' or a bzr developer
1362
advises you to run it.
1364
If a second branch is provided, cross-branch reconciliation is
1365
also attempted, which will check that data like the tree root
1366
id which was not present in very early bzr versions is represented
1367
correctly in both branches.
1369
At the same time it is run it may recompress data resulting in
1370
a potential saving in disk space or performance gain.
1372
The branch *MUST* be on a listable system such as local disk or sftp.
1375
_see_also = ['check']
1376
takes_args = ['branch?']
1378
def run(self, branch="."):
1379
from bzrlib.reconcile import reconcile
1380
dir = bzrdir.BzrDir.open(branch)
1384
class cmd_revision_history(Command):
1385
"""Display the list of revision ids on a branch."""
1388
takes_args = ['location?']
1393
def run(self, location="."):
1394
branch = Branch.open_containing(location)[0]
1395
for revid in branch.revision_history():
1396
self.outf.write(revid)
1397
self.outf.write('\n')
1400
class cmd_ancestry(Command):
1401
"""List all revisions merged into this branch."""
1403
_see_also = ['log', 'revision-history']
1404
takes_args = ['location?']
1409
def run(self, location="."):
1411
wt = WorkingTree.open_containing(location)[0]
1412
except errors.NoWorkingTree:
1413
b = Branch.open(location)
1414
last_revision = b.last_revision()
1417
last_revision = wt.last_revision()
1419
revision_ids = b.repository.get_ancestry(last_revision)
1421
for revision_id in revision_ids:
1422
self.outf.write(revision_id + '\n')
1425
class cmd_init(Command):
1426
"""Make a directory into a versioned branch.
1428
Use this to create an empty branch, or before importing an
1431
If there is a repository in a parent directory of the location, then
1432
the history of the branch will be stored in the repository. Otherwise
1433
init creates a standalone branch which carries its own history
1434
in the .bzr directory.
1436
If there is already a branch at the location but it has no working tree,
1437
the tree can be populated with 'bzr checkout'.
1439
Recipe for importing a tree of files::
1445
bzr commit -m "imported project"
1448
_see_also = ['init-repository', 'branch', 'checkout']
1449
takes_args = ['location?']
1451
Option('create-prefix',
1452
help='Create the path leading up to the branch '
1453
'if it does not already exist.'),
1454
RegistryOption('format',
1455
help='Specify a format for this branch. '
1456
'See "help formats".',
1457
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1458
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1459
value_switches=True,
1460
title="Branch Format",
1462
Option('append-revisions-only',
1463
help='Never change revnos or the existing log.'
1464
' Append revisions to it only.')
1466
def run(self, location=None, format=None, append_revisions_only=False,
1467
create_prefix=False):
1469
format = bzrdir.format_registry.make_bzrdir('default')
1470
if location is None:
1473
to_transport = transport.get_transport(location)
1475
# The path has to exist to initialize a
1476
# branch inside of it.
1477
# Just using os.mkdir, since I don't
1478
# believe that we want to create a bunch of
1479
# locations if the user supplies an extended path
1481
to_transport.ensure_base()
1482
except errors.NoSuchFile:
1483
if not create_prefix:
1484
raise errors.BzrCommandError("Parent directory of %s"
1486
"\nYou may supply --create-prefix to create all"
1487
" leading parent directories."
1489
_create_prefix(to_transport)
1492
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1493
except errors.NotBranchError:
1494
# really a NotBzrDir error...
1495
create_branch = bzrdir.BzrDir.create_branch_convenience
1496
branch = create_branch(to_transport.base, format=format,
1497
possible_transports=[to_transport])
1498
a_bzrdir = branch.bzrdir
1500
from bzrlib.transport.local import LocalTransport
1501
if a_bzrdir.has_branch():
1502
if (isinstance(to_transport, LocalTransport)
1503
and not a_bzrdir.has_workingtree()):
1504
raise errors.BranchExistsWithoutWorkingTree(location)
1505
raise errors.AlreadyBranchError(location)
1506
branch = a_bzrdir.create_branch()
1507
a_bzrdir.create_workingtree()
1508
if append_revisions_only:
1510
branch.set_append_revisions_only(True)
1511
except errors.UpgradeRequired:
1512
raise errors.BzrCommandError('This branch format cannot be set'
1513
' to append-revisions-only. Try --experimental-branch6')
1515
from bzrlib.info import describe_layout, describe_format
1517
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1518
except (errors.NoWorkingTree, errors.NotLocalUrl):
1520
repository = branch.repository
1521
layout = describe_layout(repository, branch, tree).lower()
1522
format = describe_format(a_bzrdir, repository, branch, tree)
1523
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1524
if repository.is_shared():
1525
#XXX: maybe this can be refactored into transport.path_or_url()
1526
url = repository.bzrdir.root_transport.external_url()
1528
url = urlutils.local_path_from_url(url)
1529
except errors.InvalidURL:
1531
self.outf.write("Using shared repository: %s\n" % url)
1534
class cmd_init_repository(Command):
1535
"""Create a shared repository to hold branches.
1537
New branches created under the repository directory will store their
1538
revisions in the repository, not in the branch directory.
1540
If the --no-trees option is used then the branches in the repository
1541
will not have working trees by default.
1544
Create a shared repositories holding just branches::
1546
bzr init-repo --no-trees repo
1549
Make a lightweight checkout elsewhere::
1551
bzr checkout --lightweight repo/trunk trunk-checkout
1556
_see_also = ['init', 'branch', 'checkout', 'repositories']
1557
takes_args = ["location"]
1558
takes_options = [RegistryOption('format',
1559
help='Specify a format for this repository. See'
1560
' "bzr help formats" for details.',
1561
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1562
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1563
value_switches=True, title='Repository format'),
1565
help='Branches in the repository will default to'
1566
' not having a working tree.'),
1568
aliases = ["init-repo"]
1570
def run(self, location, format=None, no_trees=False):
1572
format = bzrdir.format_registry.make_bzrdir('default')
1574
if location is None:
1577
to_transport = transport.get_transport(location)
1578
to_transport.ensure_base()
1580
newdir = format.initialize_on_transport(to_transport)
1581
repo = newdir.create_repository(shared=True)
1582
repo.set_make_working_trees(not no_trees)
1584
from bzrlib.info import show_bzrdir_info
1585
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1588
class cmd_diff(Command):
1589
"""Show differences in the working tree, between revisions or branches.
1591
If no arguments are given, all changes for the current tree are listed.
1592
If files are given, only the changes in those files are listed.
1593
Remote and multiple branches can be compared by using the --old and
1594
--new options. If not provided, the default for both is derived from
1595
the first argument, if any, or the current tree if no arguments are
1598
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1599
produces patches suitable for "patch -p1".
1603
2 - unrepresentable changes
1608
Shows the difference in the working tree versus the last commit::
1612
Difference between the working tree and revision 1::
1616
Difference between revision 2 and revision 1::
1620
Difference between revision 2 and revision 1 for branch xxx::
1624
Show just the differences for file NEWS::
1628
Show the differences in working tree xxx for file NEWS::
1632
Show the differences from branch xxx to this working tree:
1636
Show the differences between two branches for file NEWS::
1638
bzr diff --old xxx --new yyy NEWS
1640
Same as 'bzr diff' but prefix paths with old/ and new/::
1642
bzr diff --prefix old/:new/
1644
_see_also = ['status']
1645
takes_args = ['file*']
1647
Option('diff-options', type=str,
1648
help='Pass these options to the external diff program.'),
1649
Option('prefix', type=str,
1651
help='Set prefixes added to old and new filenames, as '
1652
'two values separated by a colon. (eg "old/:new/").'),
1654
help='Branch/tree to compare from.',
1658
help='Branch/tree to compare to.',
1664
help='Use this command to compare files.',
1668
aliases = ['di', 'dif']
1669
encoding_type = 'exact'
1672
def run(self, revision=None, file_list=None, diff_options=None,
1673
prefix=None, old=None, new=None, using=None):
1674
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1676
if (prefix is None) or (prefix == '0'):
1684
old_label, new_label = prefix.split(":")
1686
raise errors.BzrCommandError(
1687
'--prefix expects two values separated by a colon'
1688
' (eg "old/:new/")')
1690
if revision and len(revision) > 2:
1691
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1692
' one or two revision specifiers')
1694
old_tree, new_tree, specific_files, extra_trees = \
1695
_get_trees_to_diff(file_list, revision, old, new)
1696
return show_diff_trees(old_tree, new_tree, sys.stdout,
1697
specific_files=specific_files,
1698
external_diff_options=diff_options,
1699
old_label=old_label, new_label=new_label,
1700
extra_trees=extra_trees, using=using)
1703
class cmd_deleted(Command):
1704
"""List files deleted in the working tree.
1706
# TODO: Show files deleted since a previous revision, or
1707
# between two revisions.
1708
# TODO: Much more efficient way to do this: read in new
1709
# directories with readdir, rather than stating each one. Same
1710
# level of effort but possibly much less IO. (Or possibly not,
1711
# if the directories are very large...)
1712
_see_also = ['status', 'ls']
1713
takes_options = ['show-ids']
1716
def run(self, show_ids=False):
1717
tree = WorkingTree.open_containing(u'.')[0]
1720
old = tree.basis_tree()
1723
for path, ie in old.inventory.iter_entries():
1724
if not tree.has_id(ie.file_id):
1725
self.outf.write(path)
1727
self.outf.write(' ')
1728
self.outf.write(ie.file_id)
1729
self.outf.write('\n')
1736
class cmd_modified(Command):
1737
"""List files modified in working tree.
1741
_see_also = ['status', 'ls']
1744
help='Write an ascii NUL (\\0) separator '
1745
'between files rather than a newline.')
1749
def run(self, null=False):
1750
tree = WorkingTree.open_containing(u'.')[0]
1751
td = tree.changes_from(tree.basis_tree())
1752
for path, id, kind, text_modified, meta_modified in td.modified:
1754
self.outf.write(path + '\0')
1756
self.outf.write(osutils.quotefn(path) + '\n')
1759
class cmd_added(Command):
1760
"""List files added in working tree.
1764
_see_also = ['status', 'ls']
1767
help='Write an ascii NUL (\\0) separator '
1768
'between files rather than a newline.')
1772
def run(self, null=False):
1773
wt = WorkingTree.open_containing(u'.')[0]
1776
basis = wt.basis_tree()
1779
basis_inv = basis.inventory
1782
if file_id in basis_inv:
1784
if inv.is_root(file_id) and len(basis_inv) == 0:
1786
path = inv.id2path(file_id)
1787
if not os.access(osutils.abspath(path), os.F_OK):
1790
self.outf.write(path + '\0')
1792
self.outf.write(osutils.quotefn(path) + '\n')
1799
class cmd_root(Command):
1800
"""Show the tree root directory.
1802
The root is the nearest enclosing directory with a .bzr control
1805
takes_args = ['filename?']
1807
def run(self, filename=None):
1808
"""Print the branch root."""
1809
tree = WorkingTree.open_containing(filename)[0]
1810
self.outf.write(tree.basedir + '\n')
1813
def _parse_limit(limitstring):
1815
return int(limitstring)
1817
msg = "The limit argument must be an integer."
1818
raise errors.BzrCommandError(msg)
1821
class cmd_log(Command):
1822
"""Show log of a branch, file, or directory.
1824
By default show the log of the branch containing the working directory.
1826
To request a range of logs, you can use the command -r begin..end
1827
-r revision requests a specific revision, -r ..end or -r begin.. are
1831
Log the current branch::
1839
Log the last 10 revisions of a branch::
1841
bzr log -r -10.. http://server/branch
1844
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1846
takes_args = ['location?']
1849
help='Show from oldest to newest.'),
1851
custom_help('verbose',
1852
help='Show files changed in each revision.'),
1856
type=bzrlib.option._parse_revision_str,
1858
help='Show just the specified revision.'
1859
' See also "help revisionspec".'),
1863
help='Show revisions whose message matches this '
1864
'regular expression.',
1868
help='Limit the output to the first N revisions.',
1872
encoding_type = 'replace'
1875
def run(self, location=None, timezone='original',
1884
from bzrlib.log import show_log
1885
direction = (forward and 'forward') or 'reverse'
1887
if change is not None:
1889
raise errors.RangeInChangeOption()
1890
if revision is not None:
1891
raise errors.BzrCommandError(
1892
'--revision and --change are mutually exclusive')
1899
# find the file id to log:
1901
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1905
tree = b.basis_tree()
1906
file_id = tree.path2id(fp)
1908
raise errors.BzrCommandError(
1909
"Path does not have any revision history: %s" %
1913
# FIXME ? log the current subdir only RBC 20060203
1914
if revision is not None \
1915
and len(revision) > 0 and revision[0].get_branch():
1916
location = revision[0].get_branch()
1919
dir, relpath = bzrdir.BzrDir.open_containing(location)
1920
b = dir.open_branch()
1924
rev1, rev2 = _get_revision_range(revision, b, self.name())
1925
if log_format is None:
1926
log_format = log.log_formatter_registry.get_default(b)
1928
lf = log_format(show_ids=show_ids, to_file=self.outf,
1929
show_timezone=timezone,
1930
delta_format=get_verbosity_level())
1936
direction=direction,
1937
start_revision=rev1,
1944
def _get_revision_range(revisionspec_list, branch, command_name):
1945
"""Take the input of a revision option and turn it into a revision range.
1947
It returns RevisionInfo objects which can be used to obtain the rev_id's
1948
of the desired revisons. It does some user input validations.
1950
if revisionspec_list is None:
1953
elif len(revisionspec_list) == 1:
1954
rev1 = rev2 = revisionspec_list[0].in_history(branch)
1955
elif len(revisionspec_list) == 2:
1956
if revisionspec_list[1].get_branch() != revisionspec_list[0
1958
# b is taken from revision[0].get_branch(), and
1959
# show_log will use its revision_history. Having
1960
# different branches will lead to weird behaviors.
1961
raise errors.BzrCommandError(
1962
"bzr %s doesn't accept two revisions in different"
1963
" branches." % command_name)
1964
rev1 = revisionspec_list[0].in_history(branch)
1965
rev2 = revisionspec_list[1].in_history(branch)
1967
raise errors.BzrCommandError(
1968
'bzr %s --revision takes one or two values.' % command_name)
1972
def _revision_range_to_revid_range(revision_range):
1975
if revision_range[0] is not None:
1976
rev_id1 = revision_range[0].rev_id
1977
if revision_range[1] is not None:
1978
rev_id2 = revision_range[1].rev_id
1979
return rev_id1, rev_id2
1981
def get_log_format(long=False, short=False, line=False, default='long'):
1982
log_format = default
1986
log_format = 'short'
1992
class cmd_touching_revisions(Command):
1993
"""Return revision-ids which affected a particular file.
1995
A more user-friendly interface is "bzr log FILE".
1999
takes_args = ["filename"]
2002
def run(self, filename):
2003
tree, relpath = WorkingTree.open_containing(filename)
2005
file_id = tree.path2id(relpath)
2006
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2007
self.outf.write("%6d %s\n" % (revno, what))
2010
class cmd_ls(Command):
2011
"""List files in a tree.
2014
_see_also = ['status', 'cat']
2015
takes_args = ['path?']
2016
# TODO: Take a revision or remote path and list that tree instead.
2020
Option('non-recursive',
2021
help='Don\'t recurse into subdirectories.'),
2023
help='Print paths relative to the root of the branch.'),
2024
Option('unknown', help='Print unknown files.'),
2025
Option('versioned', help='Print versioned files.',
2027
Option('ignored', help='Print ignored files.'),
2029
help='Write an ascii NUL (\\0) separator '
2030
'between files rather than a newline.'),
2032
help='List entries of a particular kind: file, directory, symlink.',
2037
def run(self, revision=None, verbose=False,
2038
non_recursive=False, from_root=False,
2039
unknown=False, versioned=False, ignored=False,
2040
null=False, kind=None, show_ids=False, path=None):
2042
if kind and kind not in ('file', 'directory', 'symlink'):
2043
raise errors.BzrCommandError('invalid kind specified')
2045
if verbose and null:
2046
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2047
all = not (unknown or versioned or ignored)
2049
selection = {'I':ignored, '?':unknown, 'V':versioned}
2056
raise errors.BzrCommandError('cannot specify both --from-root'
2060
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2066
if revision is not None or tree is None:
2067
tree = _get_one_revision_tree('ls', revision, branch=branch)
2071
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2072
if fp.startswith(relpath):
2073
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2074
if non_recursive and '/' in fp:
2076
if not all and not selection[fc]:
2078
if kind is not None and fkind != kind:
2080
kindch = entry.kind_character()
2081
outstring = fp + kindch
2083
outstring = '%-8s %s' % (fc, outstring)
2084
if show_ids and fid is not None:
2085
outstring = "%-50s %s" % (outstring, fid)
2086
self.outf.write(outstring + '\n')
2088
self.outf.write(fp + '\0')
2091
self.outf.write(fid)
2092
self.outf.write('\0')
2100
self.outf.write('%-50s %s\n' % (outstring, my_id))
2102
self.outf.write(outstring + '\n')
2107
class cmd_unknowns(Command):
2108
"""List unknown files.
2116
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2117
self.outf.write(osutils.quotefn(f) + '\n')
2120
class cmd_ignore(Command):
2121
"""Ignore specified files or patterns.
2123
See ``bzr help patterns`` for details on the syntax of patterns.
2125
To remove patterns from the ignore list, edit the .bzrignore file.
2126
After adding, editing or deleting that file either indirectly by
2127
using this command or directly by using an editor, be sure to commit
2130
Note: ignore patterns containing shell wildcards must be quoted from
2134
Ignore the top level Makefile::
2136
bzr ignore ./Makefile
2138
Ignore class files in all directories::
2140
bzr ignore "*.class"
2142
Ignore .o files under the lib directory::
2144
bzr ignore "lib/**/*.o"
2146
Ignore .o files under the lib directory::
2148
bzr ignore "RE:lib/.*\.o"
2150
Ignore everything but the "debian" toplevel directory::
2152
bzr ignore "RE:(?!debian/).*"
2155
_see_also = ['status', 'ignored', 'patterns']
2156
takes_args = ['name_pattern*']
2158
Option('old-default-rules',
2159
help='Write out the ignore rules bzr < 0.9 always used.')
2162
def run(self, name_pattern_list=None, old_default_rules=None):
2163
from bzrlib import ignores
2164
if old_default_rules is not None:
2165
# dump the rules and exit
2166
for pattern in ignores.OLD_DEFAULTS:
2169
if not name_pattern_list:
2170
raise errors.BzrCommandError("ignore requires at least one "
2171
"NAME_PATTERN or --old-default-rules")
2172
name_pattern_list = [globbing.normalize_pattern(p)
2173
for p in name_pattern_list]
2174
for name_pattern in name_pattern_list:
2175
if (name_pattern[0] == '/' or
2176
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2177
raise errors.BzrCommandError(
2178
"NAME_PATTERN should not be an absolute path")
2179
tree, relpath = WorkingTree.open_containing(u'.')
2180
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2181
ignored = globbing.Globster(name_pattern_list)
2184
for entry in tree.list_files():
2188
if ignored.match(filename):
2189
matches.append(filename.encode('utf-8'))
2191
if len(matches) > 0:
2192
print "Warning: the following files are version controlled and" \
2193
" match your ignore pattern:\n%s" % ("\n".join(matches),)
2196
class cmd_ignored(Command):
2197
"""List ignored files and the patterns that matched them.
2199
List all the ignored files and the ignore pattern that caused the file to
2202
Alternatively, to list just the files::
2207
encoding_type = 'replace'
2208
_see_also = ['ignore', 'ls']
2212
tree = WorkingTree.open_containing(u'.')[0]
2215
for path, file_class, kind, file_id, entry in tree.list_files():
2216
if file_class != 'I':
2218
## XXX: Slightly inefficient since this was already calculated
2219
pat = tree.is_ignored(path)
2220
self.outf.write('%-50s %s\n' % (path, pat))
2225
class cmd_lookup_revision(Command):
2226
"""Lookup the revision-id from a revision-number
2229
bzr lookup-revision 33
2232
takes_args = ['revno']
2235
def run(self, revno):
2239
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2241
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2244
class cmd_export(Command):
2245
"""Export current or past revision to a destination directory or archive.
2247
If no revision is specified this exports the last committed revision.
2249
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
2250
given, try to find the format with the extension. If no extension
2251
is found exports to a directory (equivalent to --format=dir).
2253
If root is supplied, it will be used as the root directory inside
2254
container formats (tar, zip, etc). If it is not supplied it will default
2255
to the exported filename. The root option has no effect for 'dir' format.
2257
If branch is omitted then the branch containing the current working
2258
directory will be used.
2260
Note: Export of tree with non-ASCII filenames to zip is not supported.
2262
================= =========================
2263
Supported formats Autodetected by extension
2264
================= =========================
2267
tbz2 .tar.bz2, .tbz2
2270
================= =========================
2272
takes_args = ['dest', 'branch_or_subdir?']
2275
help="Type of file to export to.",
2280
help="Name of the root directory inside the exported file."),
2282
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2284
from bzrlib.export import export
2286
if branch_or_subdir is None:
2287
tree = WorkingTree.open_containing(u'.')[0]
2291
b, subdir = Branch.open_containing(branch_or_subdir)
2294
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2296
export(rev_tree, dest, format, root, subdir)
2297
except errors.NoSuchExportFormat, e:
2298
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2301
class cmd_cat(Command):
2302
"""Write the contents of a file as of a given revision to standard output.
2304
If no revision is nominated, the last revision is used.
2306
Note: Take care to redirect standard output when using this command on a
2312
Option('name-from-revision', help='The path name in the old tree.'),
2315
takes_args = ['filename']
2316
encoding_type = 'exact'
2319
def run(self, filename, revision=None, name_from_revision=False):
2320
if revision is not None and len(revision) != 1:
2321
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2322
" one revision specifier")
2323
tree, branch, relpath = \
2324
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2327
return self._run(tree, branch, relpath, filename, revision,
2332
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2334
tree = b.basis_tree()
2335
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2337
cur_file_id = tree.path2id(relpath)
2338
old_file_id = rev_tree.path2id(relpath)
2340
if name_from_revision:
2341
if old_file_id is None:
2342
raise errors.BzrCommandError(
2343
"%r is not present in revision %s" % (
2344
filename, rev_tree.get_revision_id()))
2346
content = rev_tree.get_file_text(old_file_id)
2347
elif cur_file_id is not None:
2348
content = rev_tree.get_file_text(cur_file_id)
2349
elif old_file_id is not None:
2350
content = rev_tree.get_file_text(old_file_id)
2352
raise errors.BzrCommandError(
2353
"%r is not present in revision %s" % (
2354
filename, rev_tree.get_revision_id()))
2355
self.outf.write(content)
2358
class cmd_local_time_offset(Command):
2359
"""Show the offset in seconds from GMT to local time."""
2363
print osutils.local_time_offset()
2367
class cmd_commit(Command):
2368
"""Commit changes into a new revision.
2370
If no arguments are given, the entire tree is committed.
2372
If selected files are specified, only changes to those files are
2373
committed. If a directory is specified then the directory and everything
2374
within it is committed.
2376
When excludes are given, they take precedence over selected files.
2377
For example, too commit only changes within foo, but not changes within
2380
bzr commit foo -x foo/bar
2382
If author of the change is not the same person as the committer, you can
2383
specify the author's name using the --author option. The name should be
2384
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2386
A selected-file commit may fail in some cases where the committed
2387
tree would be invalid. Consider::
2392
bzr commit foo -m "committing foo"
2393
bzr mv foo/bar foo/baz
2396
bzr commit foo/bar -m "committing bar but not baz"
2398
In the example above, the last commit will fail by design. This gives
2399
the user the opportunity to decide whether they want to commit the
2400
rename at the same time, separately first, or not at all. (As a general
2401
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2403
Note: A selected-file commit after a merge is not yet supported.
2405
# TODO: Run hooks on tree to-be-committed, and after commit.
2407
# TODO: Strict commit that fails if there are deleted files.
2408
# (what does "deleted files" mean ??)
2410
# TODO: Give better message for -s, --summary, used by tla people
2412
# XXX: verbose currently does nothing
2414
_see_also = ['bugs', 'uncommit']
2415
takes_args = ['selected*']
2417
ListOption('exclude', type=str, short_name='x',
2418
help="Do not consider changes made to a given path."),
2419
Option('message', type=unicode,
2421
help="Description of the new revision."),
2424
help='Commit even if nothing has changed.'),
2425
Option('file', type=str,
2428
help='Take commit message from this file.'),
2430
help="Refuse to commit if there are unknown "
2431
"files in the working tree."),
2432
ListOption('fixes', type=str,
2433
help="Mark a bug as being fixed by this revision."),
2434
Option('author', type=unicode,
2435
help="Set the author's name, if it's different "
2436
"from the committer."),
2438
help="Perform a local commit in a bound "
2439
"branch. Local commits are not pushed to "
2440
"the master branch until a normal commit "
2444
help='When no message is supplied, show the diff along'
2445
' with the status summary in the message editor.'),
2447
aliases = ['ci', 'checkin']
2449
def _get_bug_fix_properties(self, fixes, branch):
2451
# Configure the properties for bug fixing attributes.
2452
for fixed_bug in fixes:
2453
tokens = fixed_bug.split(':')
2454
if len(tokens) != 2:
2455
raise errors.BzrCommandError(
2456
"Invalid bug %s. Must be in the form of 'tag:id'. "
2457
"Commit refused." % fixed_bug)
2458
tag, bug_id = tokens
2460
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2461
except errors.UnknownBugTrackerAbbreviation:
2462
raise errors.BzrCommandError(
2463
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2464
except errors.MalformedBugIdentifier:
2465
raise errors.BzrCommandError(
2466
"Invalid bug identifier for %s. Commit refused."
2468
properties.append('%s fixed' % bug_url)
2469
return '\n'.join(properties)
2471
def run(self, message=None, file=None, verbose=False, selected_list=None,
2472
unchanged=False, strict=False, local=False, fixes=None,
2473
author=None, show_diff=False, exclude=None):
2474
from bzrlib.errors import (
2479
from bzrlib.msgeditor import (
2480
edit_commit_message_encoded,
2481
generate_commit_message_template,
2482
make_commit_message_template_encoded
2485
# TODO: Need a blackbox test for invoking the external editor; may be
2486
# slightly problematic to run this cross-platform.
2488
# TODO: do more checks that the commit will succeed before
2489
# spending the user's valuable time typing a commit message.
2493
tree, selected_list = tree_files(selected_list)
2494
if selected_list == ['']:
2495
# workaround - commit of root of tree should be exactly the same
2496
# as just default commit in that tree, and succeed even though
2497
# selected-file merge commit is not done yet
2502
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2504
properties['bugs'] = bug_property
2506
if local and not tree.branch.get_bound_location():
2507
raise errors.LocalRequiresBoundBranch()
2509
def get_message(commit_obj):
2510
"""Callback to get commit message"""
2511
my_message = message
2512
if my_message is None and not file:
2513
t = make_commit_message_template_encoded(tree,
2514
selected_list, diff=show_diff,
2515
output_encoding=osutils.get_user_encoding())
2516
start_message = generate_commit_message_template(commit_obj)
2517
my_message = edit_commit_message_encoded(t,
2518
start_message=start_message)
2519
if my_message is None:
2520
raise errors.BzrCommandError("please specify a commit"
2521
" message with either --message or --file")
2522
elif my_message and file:
2523
raise errors.BzrCommandError(
2524
"please specify either --message or --file")
2526
my_message = codecs.open(file, 'rt',
2527
osutils.get_user_encoding()).read()
2528
if my_message == "":
2529
raise errors.BzrCommandError("empty commit message specified")
2533
tree.commit(message_callback=get_message,
2534
specific_files=selected_list,
2535
allow_pointless=unchanged, strict=strict, local=local,
2536
reporter=None, verbose=verbose, revprops=properties,
2538
exclude=safe_relpath_files(tree, exclude))
2539
except PointlessCommit:
2540
# FIXME: This should really happen before the file is read in;
2541
# perhaps prepare the commit; get the message; then actually commit
2542
raise errors.BzrCommandError("no changes to commit."
2543
" use --unchanged to commit anyhow")
2544
except ConflictsInTree:
2545
raise errors.BzrCommandError('Conflicts detected in working '
2546
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2548
except StrictCommitFailed:
2549
raise errors.BzrCommandError("Commit refused because there are"
2550
" unknown files in the working tree.")
2551
except errors.BoundBranchOutOfDate, e:
2552
raise errors.BzrCommandError(str(e) + "\n"
2553
'To commit to master branch, run update and then commit.\n'
2554
'You can also pass --local to commit to continue working '
2558
class cmd_check(Command):
2559
"""Validate working tree structure, branch consistency and repository history.
2561
This command checks various invariants about branch and repository storage
2562
to detect data corruption or bzr bugs.
2564
The working tree and branch checks will only give output if a problem is
2565
detected. The output fields of the repository check are:
2567
revisions: This is just the number of revisions checked. It doesn't
2569
versionedfiles: This is just the number of versionedfiles checked. It
2570
doesn't indicate a problem.
2571
unreferenced ancestors: Texts that are ancestors of other texts, but
2572
are not properly referenced by the revision ancestry. This is a
2573
subtle problem that Bazaar can work around.
2574
unique file texts: This is the total number of unique file contents
2575
seen in the checked revisions. It does not indicate a problem.
2576
repeated file texts: This is the total number of repeated texts seen
2577
in the checked revisions. Texts can be repeated when their file
2578
entries are modified, but the file contents are not. It does not
2581
If no restrictions are specified, all Bazaar data that is found at the given
2582
location will be checked.
2586
Check the tree and branch at 'foo'::
2588
bzr check --tree --branch foo
2590
Check only the repository at 'bar'::
2592
bzr check --repo bar
2594
Check everything at 'baz'::
2599
_see_also = ['reconcile']
2600
takes_args = ['path?']
2601
takes_options = ['verbose',
2602
Option('branch', help="Check the branch related to the"
2603
" current directory."),
2604
Option('repo', help="Check the repository related to the"
2605
" current directory."),
2606
Option('tree', help="Check the working tree related to"
2607
" the current directory.")]
2609
def run(self, path=None, verbose=False, branch=False, repo=False,
2611
from bzrlib.check import check_dwim
2614
if not branch and not repo and not tree:
2615
branch = repo = tree = True
2616
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2619
class cmd_upgrade(Command):
2620
"""Upgrade branch storage to current format.
2622
The check command or bzr developers may sometimes advise you to run
2623
this command. When the default format has changed you may also be warned
2624
during other operations to upgrade.
2627
_see_also = ['check']
2628
takes_args = ['url?']
2630
RegistryOption('format',
2631
help='Upgrade to a specific format. See "bzr help'
2632
' formats" for details.',
2633
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
2634
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2635
value_switches=True, title='Branch format'),
2638
def run(self, url='.', format=None):
2639
from bzrlib.upgrade import upgrade
2641
format = bzrdir.format_registry.make_bzrdir('default')
2642
upgrade(url, format)
2645
class cmd_whoami(Command):
2646
"""Show or set bzr user id.
2649
Show the email of the current user::
2653
Set the current user::
2655
bzr whoami "Frank Chu <fchu@example.com>"
2657
takes_options = [ Option('email',
2658
help='Display email address only.'),
2660
help='Set identity for the current branch instead of '
2663
takes_args = ['name?']
2664
encoding_type = 'replace'
2667
def run(self, email=False, branch=False, name=None):
2669
# use branch if we're inside one; otherwise global config
2671
c = Branch.open_containing('.')[0].get_config()
2672
except errors.NotBranchError:
2673
c = config.GlobalConfig()
2675
self.outf.write(c.user_email() + '\n')
2677
self.outf.write(c.username() + '\n')
2680
# display a warning if an email address isn't included in the given name.
2682
config.extract_email_address(name)
2683
except errors.NoEmailInUsername, e:
2684
warning('"%s" does not seem to contain an email address. '
2685
'This is allowed, but not recommended.', name)
2687
# use global config unless --branch given
2689
c = Branch.open_containing('.')[0].get_config()
2691
c = config.GlobalConfig()
2692
c.set_user_option('email', name)
2695
class cmd_nick(Command):
2696
"""Print or set the branch nickname.
2698
If unset, the tree root directory name is used as the nickname.
2699
To print the current nickname, execute with no argument.
2701
Bound branches use the nickname of its master branch unless it is set
2705
_see_also = ['info']
2706
takes_args = ['nickname?']
2707
def run(self, nickname=None):
2708
branch = Branch.open_containing(u'.')[0]
2709
if nickname is None:
2710
self.printme(branch)
2712
branch.nick = nickname
2715
def printme(self, branch):
2719
class cmd_alias(Command):
2720
"""Set/unset and display aliases.
2723
Show the current aliases::
2727
Show the alias specified for 'll'::
2731
Set an alias for 'll'::
2733
bzr alias ll="log --line -r-10..-1"
2735
To remove an alias for 'll'::
2737
bzr alias --remove ll
2740
takes_args = ['name?']
2742
Option('remove', help='Remove the alias.'),
2745
def run(self, name=None, remove=False):
2747
self.remove_alias(name)
2749
self.print_aliases()
2751
equal_pos = name.find('=')
2753
self.print_alias(name)
2755
self.set_alias(name[:equal_pos], name[equal_pos+1:])
2757
def remove_alias(self, alias_name):
2758
if alias_name is None:
2759
raise errors.BzrCommandError(
2760
'bzr alias --remove expects an alias to remove.')
2761
# If alias is not found, print something like:
2762
# unalias: foo: not found
2763
c = config.GlobalConfig()
2764
c.unset_alias(alias_name)
2767
def print_aliases(self):
2768
"""Print out the defined aliases in a similar format to bash."""
2769
aliases = config.GlobalConfig().get_aliases()
2770
for key, value in sorted(aliases.iteritems()):
2771
self.outf.write('bzr alias %s="%s"\n' % (key, value))
2774
def print_alias(self, alias_name):
2775
from bzrlib.commands import get_alias
2776
alias = get_alias(alias_name)
2778
self.outf.write("bzr alias: %s: not found\n" % alias_name)
2781
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
2783
def set_alias(self, alias_name, alias_command):
2784
"""Save the alias in the global config."""
2785
c = config.GlobalConfig()
2786
c.set_alias(alias_name, alias_command)
2789
class cmd_selftest(Command):
2790
"""Run internal test suite.
2792
If arguments are given, they are regular expressions that say which tests
2793
should run. Tests matching any expression are run, and other tests are
2796
Alternatively if --first is given, matching tests are run first and then
2797
all other tests are run. This is useful if you have been working in a
2798
particular area, but want to make sure nothing else was broken.
2800
If --exclude is given, tests that match that regular expression are
2801
excluded, regardless of whether they match --first or not.
2803
To help catch accidential dependencies between tests, the --randomize
2804
option is useful. In most cases, the argument used is the word 'now'.
2805
Note that the seed used for the random number generator is displayed
2806
when this option is used. The seed can be explicitly passed as the
2807
argument to this option if required. This enables reproduction of the
2808
actual ordering used if and when an order sensitive problem is encountered.
2810
If --list-only is given, the tests that would be run are listed. This is
2811
useful when combined with --first, --exclude and/or --randomize to
2812
understand their impact. The test harness reports "Listed nn tests in ..."
2813
instead of "Ran nn tests in ..." when list mode is enabled.
2815
If the global option '--no-plugins' is given, plugins are not loaded
2816
before running the selftests. This has two effects: features provided or
2817
modified by plugins will not be tested, and tests provided by plugins will
2820
Tests that need working space on disk use a common temporary directory,
2821
typically inside $TMPDIR or /tmp.
2824
Run only tests relating to 'ignore'::
2828
Disable plugins and list tests as they're run::
2830
bzr --no-plugins selftest -v
2832
# NB: this is used from the class without creating an instance, which is
2833
# why it does not have a self parameter.
2834
def get_transport_type(typestring):
2835
"""Parse and return a transport specifier."""
2836
if typestring == "sftp":
2837
from bzrlib.transport.sftp import SFTPAbsoluteServer
2838
return SFTPAbsoluteServer
2839
if typestring == "memory":
2840
from bzrlib.transport.memory import MemoryServer
2842
if typestring == "fakenfs":
2843
from bzrlib.transport.fakenfs import FakeNFSServer
2844
return FakeNFSServer
2845
msg = "No known transport type %s. Supported types are: sftp\n" %\
2847
raise errors.BzrCommandError(msg)
2850
takes_args = ['testspecs*']
2851
takes_options = ['verbose',
2853
help='Stop when one test fails.',
2857
help='Use a different transport by default '
2858
'throughout the test suite.',
2859
type=get_transport_type),
2861
help='Run the benchmarks rather than selftests.'),
2862
Option('lsprof-timed',
2863
help='Generate lsprof output for benchmarked'
2864
' sections of code.'),
2865
Option('cache-dir', type=str,
2866
help='Cache intermediate benchmark output in this '
2869
help='Run all tests, but run specified tests first.',
2873
help='List the tests instead of running them.'),
2874
Option('randomize', type=str, argname="SEED",
2875
help='Randomize the order of tests using the given'
2876
' seed or "now" for the current time.'),
2877
Option('exclude', type=str, argname="PATTERN",
2879
help='Exclude tests that match this regular'
2881
Option('strict', help='Fail on missing dependencies or '
2883
Option('load-list', type=str, argname='TESTLISTFILE',
2884
help='Load a test id list from a text file.'),
2885
ListOption('debugflag', type=str, short_name='E',
2886
help='Turn on a selftest debug flag.'),
2887
ListOption('starting-with', type=str, argname='TESTID',
2888
param_name='starting_with', short_name='s',
2890
'Load only the tests starting with TESTID.'),
2892
encoding_type = 'replace'
2894
def run(self, testspecs_list=None, verbose=False, one=False,
2895
transport=None, benchmark=None,
2896
lsprof_timed=None, cache_dir=None,
2897
first=False, list_only=False,
2898
randomize=None, exclude=None, strict=False,
2899
load_list=None, debugflag=None, starting_with=None):
2900
from bzrlib.tests import selftest
2901
import bzrlib.benchmarks as benchmarks
2902
from bzrlib.benchmarks import tree_creator
2904
# Make deprecation warnings visible, unless -Werror is set
2905
symbol_versioning.activate_deprecation_warnings(override=False)
2907
if cache_dir is not None:
2908
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2910
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2911
print ' %s (%s python%s)' % (
2913
bzrlib.version_string,
2914
bzrlib._format_version_tuple(sys.version_info),
2917
if testspecs_list is not None:
2918
pattern = '|'.join(testspecs_list)
2922
test_suite_factory = benchmarks.test_suite
2923
# Unless user explicitly asks for quiet, be verbose in benchmarks
2924
verbose = not is_quiet()
2925
# TODO: should possibly lock the history file...
2926
benchfile = open(".perf_history", "at", buffering=1)
2928
test_suite_factory = None
2931
result = selftest(verbose=verbose,
2933
stop_on_failure=one,
2934
transport=transport,
2935
test_suite_factory=test_suite_factory,
2936
lsprof_timed=lsprof_timed,
2937
bench_history=benchfile,
2938
matching_tests_first=first,
2939
list_only=list_only,
2940
random_seed=randomize,
2941
exclude_pattern=exclude,
2943
load_list=load_list,
2944
debug_flags=debugflag,
2945
starting_with=starting_with,
2948
if benchfile is not None:
2951
note('tests passed')
2953
note('tests failed')
2954
return int(not result)
2957
class cmd_version(Command):
2958
"""Show version of bzr."""
2960
encoding_type = 'replace'
2962
Option("short", help="Print just the version number."),
2966
def run(self, short=False):
2967
from bzrlib.version import show_version
2969
self.outf.write(bzrlib.version_string + '\n')
2971
show_version(to_file=self.outf)
2974
class cmd_rocks(Command):
2975
"""Statement of optimism."""
2981
print "It sure does!"
2984
class cmd_find_merge_base(Command):
2985
"""Find and print a base revision for merging two branches."""
2986
# TODO: Options to specify revisions on either side, as if
2987
# merging only part of the history.
2988
takes_args = ['branch', 'other']
2992
def run(self, branch, other):
2993
from bzrlib.revision import ensure_null
2995
branch1 = Branch.open_containing(branch)[0]
2996
branch2 = Branch.open_containing(other)[0]
3001
last1 = ensure_null(branch1.last_revision())
3002
last2 = ensure_null(branch2.last_revision())
3004
graph = branch1.repository.get_graph(branch2.repository)
3005
base_rev_id = graph.find_unique_lca(last1, last2)
3007
print 'merge base is revision %s' % base_rev_id
3014
class cmd_merge(Command):
3015
"""Perform a three-way merge.
3017
The source of the merge can be specified either in the form of a branch,
3018
or in the form of a path to a file containing a merge directive generated
3019
with bzr send. If neither is specified, the default is the upstream branch
3020
or the branch most recently merged using --remember.
3022
When merging a branch, by default the tip will be merged. To pick a different
3023
revision, pass --revision. If you specify two values, the first will be used as
3024
BASE and the second one as OTHER. Merging individual revisions, or a subset of
3025
available revisions, like this is commonly referred to as "cherrypicking".
3027
Revision numbers are always relative to the branch being merged.
3029
By default, bzr will try to merge in all new work from the other
3030
branch, automatically determining an appropriate base. If this
3031
fails, you may need to give an explicit base.
3033
Merge will do its best to combine the changes in two branches, but there
3034
are some kinds of problems only a human can fix. When it encounters those,
3035
it will mark a conflict. A conflict means that you need to fix something,
3036
before you should commit.
3038
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3040
If there is no default branch set, the first merge will set it. After
3041
that, you can omit the branch to use the default. To change the
3042
default, use --remember. The value will only be saved if the remote
3043
location can be accessed.
3045
The results of the merge are placed into the destination working
3046
directory, where they can be reviewed (with bzr diff), tested, and then
3047
committed to record the result of the merge.
3049
merge refuses to run if there are any uncommitted changes, unless
3053
To merge the latest revision from bzr.dev::
3055
bzr merge ../bzr.dev
3057
To merge changes up to and including revision 82 from bzr.dev::
3059
bzr merge -r 82 ../bzr.dev
3061
To merge the changes introduced by 82, without previous changes::
3063
bzr merge -r 81..82 ../bzr.dev
3065
To apply a merge directive contained in in /tmp/merge:
3067
bzr merge /tmp/merge
3070
encoding_type = 'exact'
3071
_see_also = ['update', 'remerge', 'status-flags']
3072
takes_args = ['location?']
3077
help='Merge even if the destination tree has uncommitted changes.'),
3081
Option('show-base', help="Show base revision text in "
3083
Option('uncommitted', help='Apply uncommitted changes'
3084
' from a working copy, instead of branch changes.'),
3085
Option('pull', help='If the destination is already'
3086
' completely merged into the source, pull from the'
3087
' source rather than merging. When this happens,'
3088
' you do not need to commit the result.'),
3090
help='Branch to merge into, '
3091
'rather than the one containing the working directory.',
3095
Option('preview', help='Instead of merging, show a diff of the merge.')
3098
def run(self, location=None, revision=None, force=False,
3099
merge_type=None, show_base=False, reprocess=None, remember=False,
3100
uncommitted=False, pull=False,
3104
if merge_type is None:
3105
merge_type = _mod_merge.Merge3Merger
3107
if directory is None: directory = u'.'
3108
possible_transports = []
3110
allow_pending = True
3111
verified = 'inapplicable'
3112
tree = WorkingTree.open_containing(directory)[0]
3113
change_reporter = delta._ChangeReporter(
3114
unversioned_filter=tree.is_ignored)
3117
pb = ui.ui_factory.nested_progress_bar()
3118
cleanups.append(pb.finished)
3120
cleanups.append(tree.unlock)
3121
if location is not None:
3123
mergeable = bundle.read_mergeable_from_url(location,
3124
possible_transports=possible_transports)
3125
except errors.NotABundle:
3129
raise errors.BzrCommandError('Cannot use --uncommitted'
3130
' with bundles or merge directives.')
3132
if revision is not None:
3133
raise errors.BzrCommandError(
3134
'Cannot use -r with merge directives or bundles')
3135
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3138
if merger is None and uncommitted:
3139
if revision is not None and len(revision) > 0:
3140
raise errors.BzrCommandError('Cannot use --uncommitted and'
3141
' --revision at the same time.')
3142
location = self._select_branch_location(tree, location)[0]
3143
other_tree, other_path = WorkingTree.open_containing(location)
3144
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3146
allow_pending = False
3147
if other_path != '':
3148
merger.interesting_files = [other_path]
3151
merger, allow_pending = self._get_merger_from_branch(tree,
3152
location, revision, remember, possible_transports, pb)
3154
merger.merge_type = merge_type
3155
merger.reprocess = reprocess
3156
merger.show_base = show_base
3157
self.sanity_check_merger(merger)
3158
if (merger.base_rev_id == merger.other_rev_id and
3159
merger.other_rev_id is not None):
3160
note('Nothing to do.')
3163
if merger.interesting_files is not None:
3164
raise errors.BzrCommandError('Cannot pull individual files')
3165
if (merger.base_rev_id == tree.last_revision()):
3166
result = tree.pull(merger.other_branch, False,
3167
merger.other_rev_id)
3168
result.report(self.outf)
3170
merger.check_basis(not force)
3172
return self._do_preview(merger)
3174
return self._do_merge(merger, change_reporter, allow_pending,
3177
for cleanup in reversed(cleanups):
3180
def _do_preview(self, merger):
3181
from bzrlib.diff import show_diff_trees
3182
tree_merger = merger.make_merger()
3183
tt = tree_merger.make_preview_transform()
3185
result_tree = tt.get_preview_tree()
3186
show_diff_trees(merger.this_tree, result_tree, self.outf,
3187
old_label='', new_label='')
3191
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3192
merger.change_reporter = change_reporter
3193
conflict_count = merger.do_merge()
3195
merger.set_pending()
3196
if verified == 'failed':
3197
warning('Preview patch does not match changes')
3198
if conflict_count != 0:
3203
def sanity_check_merger(self, merger):
3204
if (merger.show_base and
3205
not merger.merge_type is _mod_merge.Merge3Merger):
3206
raise errors.BzrCommandError("Show-base is not supported for this"
3207
" merge type. %s" % merger.merge_type)
3208
if merger.reprocess is None:
3209
if merger.show_base:
3210
merger.reprocess = False
3212
# Use reprocess if the merger supports it
3213
merger.reprocess = merger.merge_type.supports_reprocess
3214
if merger.reprocess and not merger.merge_type.supports_reprocess:
3215
raise errors.BzrCommandError("Conflict reduction is not supported"
3216
" for merge type %s." %
3218
if merger.reprocess and merger.show_base:
3219
raise errors.BzrCommandError("Cannot do conflict reduction and"
3222
def _get_merger_from_branch(self, tree, location, revision, remember,
3223
possible_transports, pb):
3224
"""Produce a merger from a location, assuming it refers to a branch."""
3225
from bzrlib.tag import _merge_tags_if_possible
3226
# find the branch locations
3227
other_loc, user_location = self._select_branch_location(tree, location,
3229
if revision is not None and len(revision) == 2:
3230
base_loc, _unused = self._select_branch_location(tree,
3231
location, revision, 0)
3233
base_loc = other_loc
3235
other_branch, other_path = Branch.open_containing(other_loc,
3236
possible_transports)
3237
if base_loc == other_loc:
3238
base_branch = other_branch
3240
base_branch, base_path = Branch.open_containing(base_loc,
3241
possible_transports)
3242
# Find the revision ids
3243
if revision is None or len(revision) < 1 or revision[-1] is None:
3244
other_revision_id = _mod_revision.ensure_null(
3245
other_branch.last_revision())
3247
other_revision_id = revision[-1].as_revision_id(other_branch)
3248
if (revision is not None and len(revision) == 2
3249
and revision[0] is not None):
3250
base_revision_id = revision[0].as_revision_id(base_branch)
3252
base_revision_id = None
3253
# Remember where we merge from
3254
if ((remember or tree.branch.get_submit_branch() is None) and
3255
user_location is not None):
3256
tree.branch.set_submit_branch(other_branch.base)
3257
_merge_tags_if_possible(other_branch, tree.branch)
3258
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3259
other_revision_id, base_revision_id, other_branch, base_branch)
3260
if other_path != '':
3261
allow_pending = False
3262
merger.interesting_files = [other_path]
3264
allow_pending = True
3265
return merger, allow_pending
3267
def _select_branch_location(self, tree, user_location, revision=None,
3269
"""Select a branch location, according to possible inputs.
3271
If provided, branches from ``revision`` are preferred. (Both
3272
``revision`` and ``index`` must be supplied.)
3274
Otherwise, the ``location`` parameter is used. If it is None, then the
3275
``submit`` or ``parent`` location is used, and a note is printed.
3277
:param tree: The working tree to select a branch for merging into
3278
:param location: The location entered by the user
3279
:param revision: The revision parameter to the command
3280
:param index: The index to use for the revision parameter. Negative
3281
indices are permitted.
3282
:return: (selected_location, user_location). The default location
3283
will be the user-entered location.
3285
if (revision is not None and index is not None
3286
and revision[index] is not None):
3287
branch = revision[index].get_branch()
3288
if branch is not None:
3289
return branch, branch
3290
if user_location is None:
3291
location = self._get_remembered(tree, 'Merging from')
3293
location = user_location
3294
return location, user_location
3296
def _get_remembered(self, tree, verb_string):
3297
"""Use tree.branch's parent if none was supplied.
3299
Report if the remembered location was used.
3301
stored_location = tree.branch.get_submit_branch()
3302
stored_location_type = "submit"
3303
if stored_location is None:
3304
stored_location = tree.branch.get_parent()
3305
stored_location_type = "parent"
3306
mutter("%s", stored_location)
3307
if stored_location is None:
3308
raise errors.BzrCommandError("No location specified or remembered")
3309
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3310
note(u"%s remembered %s location %s", verb_string,
3311
stored_location_type, display_url)
3312
return stored_location
3315
class cmd_remerge(Command):
3318
Use this if you want to try a different merge technique while resolving
3319
conflicts. Some merge techniques are better than others, and remerge
3320
lets you try different ones on different files.
3322
The options for remerge have the same meaning and defaults as the ones for
3323
merge. The difference is that remerge can (only) be run when there is a
3324
pending merge, and it lets you specify particular files.
3327
Re-do the merge of all conflicted files, and show the base text in
3328
conflict regions, in addition to the usual THIS and OTHER texts::
3330
bzr remerge --show-base
3332
Re-do the merge of "foobar", using the weave merge algorithm, with
3333
additional processing to reduce the size of conflict regions::
3335
bzr remerge --merge-type weave --reprocess foobar
3337
takes_args = ['file*']
3342
help="Show base revision text in conflicts."),
3345
def run(self, file_list=None, merge_type=None, show_base=False,
3347
if merge_type is None:
3348
merge_type = _mod_merge.Merge3Merger
3349
tree, file_list = tree_files(file_list)
3352
parents = tree.get_parent_ids()
3353
if len(parents) != 2:
3354
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3355
" merges. Not cherrypicking or"
3357
repository = tree.branch.repository
3358
interesting_ids = None
3360
conflicts = tree.conflicts()
3361
if file_list is not None:
3362
interesting_ids = set()
3363
for filename in file_list:
3364
file_id = tree.path2id(filename)
3366
raise errors.NotVersionedError(filename)
3367
interesting_ids.add(file_id)
3368
if tree.kind(file_id) != "directory":
3371
for name, ie in tree.inventory.iter_entries(file_id):
3372
interesting_ids.add(ie.file_id)
3373
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3375
# Remerge only supports resolving contents conflicts
3376
allowed_conflicts = ('text conflict', 'contents conflict')
3377
restore_files = [c.path for c in conflicts
3378
if c.typestring in allowed_conflicts]
3379
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3380
tree.set_conflicts(ConflictList(new_conflicts))
3381
if file_list is not None:
3382
restore_files = file_list
3383
for filename in restore_files:
3385
restore(tree.abspath(filename))
3386
except errors.NotConflicted:
3388
# Disable pending merges, because the file texts we are remerging
3389
# have not had those merges performed. If we use the wrong parents
3390
# list, we imply that the working tree text has seen and rejected
3391
# all the changes from the other tree, when in fact those changes
3392
# have not yet been seen.
3393
pb = ui.ui_factory.nested_progress_bar()
3394
tree.set_parent_ids(parents[:1])
3396
merger = _mod_merge.Merger.from_revision_ids(pb,
3398
merger.interesting_ids = interesting_ids
3399
merger.merge_type = merge_type
3400
merger.show_base = show_base
3401
merger.reprocess = reprocess
3402
conflicts = merger.do_merge()
3404
tree.set_parent_ids(parents)
3414
class cmd_revert(Command):
3415
"""Revert files to a previous revision.
3417
Giving a list of files will revert only those files. Otherwise, all files
3418
will be reverted. If the revision is not specified with '--revision', the
3419
last committed revision is used.
3421
To remove only some changes, without reverting to a prior version, use
3422
merge instead. For example, "merge . --revision -2..-3" will remove the
3423
changes introduced by -2, without affecting the changes introduced by -1.
3424
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3426
By default, any files that have been manually changed will be backed up
3427
first. (Files changed only by merge are not backed up.) Backup files have
3428
'.~#~' appended to their name, where # is a number.
3430
When you provide files, you can use their current pathname or the pathname
3431
from the target revision. So you can use revert to "undelete" a file by
3432
name. If you name a directory, all the contents of that directory will be
3435
Any files that have been newly added since that revision will be deleted,
3436
with a backup kept if appropriate. Directories containing unknown files
3437
will not be deleted.
3439
The working tree contains a list of pending merged revisions, which will
3440
be included as parents in the next commit. Normally, revert clears that
3441
list as well as reverting the files. If any files are specified, revert
3442
leaves the pending merge list alone and reverts only the files. Use "bzr
3443
revert ." in the tree root to revert all files but keep the merge record,
3444
and "bzr revert --forget-merges" to clear the pending merge list without
3445
reverting any files.
3448
_see_also = ['cat', 'export']
3451
Option('no-backup', "Do not save backups of reverted files."),
3452
Option('forget-merges',
3453
'Remove pending merge marker, without changing any files.'),
3455
takes_args = ['file*']
3457
def run(self, revision=None, no_backup=False, file_list=None,
3458
forget_merges=None):
3459
tree, file_list = tree_files(file_list)
3463
tree.set_parent_ids(tree.get_parent_ids()[:1])
3465
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3470
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3471
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
3472
pb = ui.ui_factory.nested_progress_bar()
3474
tree.revert(file_list, rev_tree, not no_backup, pb,
3475
report_changes=True)
3480
class cmd_assert_fail(Command):
3481
"""Test reporting of assertion failures"""
3482
# intended just for use in testing
3487
raise AssertionError("always fails")
3490
class cmd_help(Command):
3491
"""Show help on a command or other topic.
3494
_see_also = ['topics']
3496
Option('long', 'Show help on all commands.'),
3498
takes_args = ['topic?']
3499
aliases = ['?', '--help', '-?', '-h']
3502
def run(self, topic=None, long=False):
3504
if topic is None and long:
3506
bzrlib.help.help(topic)
3509
class cmd_shell_complete(Command):
3510
"""Show appropriate completions for context.
3512
For a list of all available commands, say 'bzr shell-complete'.
3514
takes_args = ['context?']
3519
def run(self, context=None):
3520
import shellcomplete
3521
shellcomplete.shellcomplete(context)
3524
class cmd_missing(Command):
3525
"""Show unmerged/unpulled revisions between two branches.
3527
OTHER_BRANCH may be local or remote.
3529
To filter on a range of revirions, you can use the command -r begin..end
3530
-r revision requests a specific revision, -r ..end or -r begin.. are
3535
Determine the missing revisions between this and the branch at the
3536
remembered pull location::
3540
Determine the missing revisions between this and another branch::
3542
bzr missing http://server/branch
3544
Determine the missing revisions up to a specific revision on the other
3547
bzr missing -r ..-10
3549
Determine the missing revisions up to a specific revision on this
3552
bzr missing --my-revision ..-10
3555
_see_also = ['merge', 'pull']
3556
takes_args = ['other_branch?']
3558
Option('reverse', 'Reverse the order of revisions.'),
3560
'Display changes in the local branch only.'),
3561
Option('this' , 'Same as --mine-only.'),
3562
Option('theirs-only',
3563
'Display changes in the remote branch only.'),
3564
Option('other', 'Same as --theirs-only.'),
3568
custom_help('revision',
3569
help='Filter on other branch revisions (inclusive). '
3570
'See "help revisionspec" for details.'),
3571
Option('my-revision',
3572
type=_parse_revision_str,
3573
help='Filter on local branch revisions (inclusive). '
3574
'See "help revisionspec" for details.'),
3575
Option('include-merges', 'Show merged revisions.'),
3577
encoding_type = 'replace'
3580
def run(self, other_branch=None, reverse=False, mine_only=False,
3582
log_format=None, long=False, short=False, line=False,
3583
show_ids=False, verbose=False, this=False, other=False,
3584
include_merges=False, revision=None, my_revision=None):
3585
from bzrlib.missing import find_unmerged, iter_log_revisions
3594
# TODO: We should probably check that we don't have mine-only and
3595
# theirs-only set, but it gets complicated because we also have
3596
# this and other which could be used.
3603
local_branch = Branch.open_containing(u".")[0]
3604
parent = local_branch.get_parent()
3605
if other_branch is None:
3606
other_branch = parent
3607
if other_branch is None:
3608
raise errors.BzrCommandError("No peer location known"
3610
display_url = urlutils.unescape_for_display(parent,
3612
message("Using saved parent location: "
3613
+ display_url + "\n")
3615
remote_branch = Branch.open(other_branch)
3616
if remote_branch.base == local_branch.base:
3617
remote_branch = local_branch
3619
local_revid_range = _revision_range_to_revid_range(
3620
_get_revision_range(my_revision, local_branch,
3623
remote_revid_range = _revision_range_to_revid_range(
3624
_get_revision_range(revision,
3625
remote_branch, self.name()))
3627
local_branch.lock_read()
3629
remote_branch.lock_read()
3631
local_extra, remote_extra = find_unmerged(
3632
local_branch, remote_branch, restrict,
3633
backward=not reverse,
3634
include_merges=include_merges,
3635
local_revid_range=local_revid_range,
3636
remote_revid_range=remote_revid_range)
3638
if log_format is None:
3639
registry = log.log_formatter_registry
3640
log_format = registry.get_default(local_branch)
3641
lf = log_format(to_file=self.outf,
3643
show_timezone='original')
3646
if local_extra and not theirs_only:
3647
message("You have %d extra revision(s):\n" %
3649
for revision in iter_log_revisions(local_extra,
3650
local_branch.repository,
3652
lf.log_revision(revision)
3653
printed_local = True
3656
printed_local = False
3658
if remote_extra and not mine_only:
3659
if printed_local is True:
3661
message("You are missing %d revision(s):\n" %
3663
for revision in iter_log_revisions(remote_extra,
3664
remote_branch.repository,
3666
lf.log_revision(revision)
3669
if mine_only and not local_extra:
3670
# We checked local, and found nothing extra
3671
message('This branch is up to date.\n')
3672
elif theirs_only and not remote_extra:
3673
# We checked remote, and found nothing extra
3674
message('Other branch is up to date.\n')
3675
elif not (mine_only or theirs_only or local_extra or
3677
# We checked both branches, and neither one had extra
3679
message("Branches are up to date.\n")
3681
remote_branch.unlock()
3683
local_branch.unlock()
3684
if not status_code and parent is None and other_branch is not None:
3685
local_branch.lock_write()
3687
# handle race conditions - a parent might be set while we run.
3688
if local_branch.get_parent() is None:
3689
local_branch.set_parent(remote_branch.base)
3691
local_branch.unlock()
3695
class cmd_pack(Command):
3696
"""Compress the data within a repository."""
3698
_see_also = ['repositories']
3699
takes_args = ['branch_or_repo?']
3701
def run(self, branch_or_repo='.'):
3702
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3704
branch = dir.open_branch()
3705
repository = branch.repository
3706
except errors.NotBranchError:
3707
repository = dir.open_repository()
3711
class cmd_plugins(Command):
3712
"""List the installed plugins.
3714
This command displays the list of installed plugins including
3715
version of plugin and a short description of each.
3717
--verbose shows the path where each plugin is located.
3719
A plugin is an external component for Bazaar that extends the
3720
revision control system, by adding or replacing code in Bazaar.
3721
Plugins can do a variety of things, including overriding commands,
3722
adding new commands, providing additional network transports and
3723
customizing log output.
3725
See the Bazaar web site, http://bazaar-vcs.org, for further
3726
information on plugins including where to find them and how to
3727
install them. Instructions are also provided there on how to
3728
write new plugins using the Python programming language.
3730
takes_options = ['verbose']
3733
def run(self, verbose=False):
3734
import bzrlib.plugin
3735
from inspect import getdoc
3737
for name, plugin in bzrlib.plugin.plugins().items():
3738
version = plugin.__version__
3739
if version == 'unknown':
3741
name_ver = '%s %s' % (name, version)
3742
d = getdoc(plugin.module)
3744
doc = d.split('\n')[0]
3746
doc = '(no description)'
3747
result.append((name_ver, doc, plugin.path()))
3748
for name_ver, doc, path in sorted(result):
3756
class cmd_testament(Command):
3757
"""Show testament (signing-form) of a revision."""
3760
Option('long', help='Produce long-format testament.'),
3762
help='Produce a strict-format testament.')]
3763
takes_args = ['branch?']
3765
def run(self, branch=u'.', revision=None, long=False, strict=False):
3766
from bzrlib.testament import Testament, StrictTestament
3768
testament_class = StrictTestament
3770
testament_class = Testament
3772
b = Branch.open_containing(branch)[0]
3774
b = Branch.open(branch)
3777
if revision is None:
3778
rev_id = b.last_revision()
3780
rev_id = revision[0].as_revision_id(b)
3781
t = testament_class.from_revision(b.repository, rev_id)
3783
sys.stdout.writelines(t.as_text_lines())
3785
sys.stdout.write(t.as_short_text())
3790
class cmd_annotate(Command):
3791
"""Show the origin of each line in a file.
3793
This prints out the given file with an annotation on the left side
3794
indicating which revision, author and date introduced the change.
3796
If the origin is the same for a run of consecutive lines, it is
3797
shown only at the top, unless the --all option is given.
3799
# TODO: annotate directories; showing when each file was last changed
3800
# TODO: if the working copy is modified, show annotations on that
3801
# with new uncommitted lines marked
3802
aliases = ['ann', 'blame', 'praise']
3803
takes_args = ['filename']
3804
takes_options = [Option('all', help='Show annotations on all lines.'),
3805
Option('long', help='Show commit date in annotations.'),
3809
encoding_type = 'exact'
3812
def run(self, filename, all=False, long=False, revision=None,
3814
from bzrlib.annotate import annotate_file, annotate_file_tree
3815
wt, branch, relpath = \
3816
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3822
tree = _get_one_revision_tree('annotate', revision, branch=branch)
3824
file_id = wt.path2id(relpath)
3826
file_id = tree.path2id(relpath)
3828
raise errors.NotVersionedError(filename)
3829
file_version = tree.inventory[file_id].revision
3830
if wt is not None and revision is None:
3831
# If there is a tree and we're not annotating historical
3832
# versions, annotate the working tree's content.
3833
annotate_file_tree(wt, file_id, self.outf, long, all,
3836
annotate_file(branch, file_version, file_id, long, all, self.outf,
3845
class cmd_re_sign(Command):
3846
"""Create a digital signature for an existing revision."""
3847
# TODO be able to replace existing ones.
3849
hidden = True # is this right ?
3850
takes_args = ['revision_id*']
3851
takes_options = ['revision']
3853
def run(self, revision_id_list=None, revision=None):
3854
if revision_id_list is not None and revision is not None:
3855
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3856
if revision_id_list is None and revision is None:
3857
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3858
b = WorkingTree.open_containing(u'.')[0].branch
3861
return self._run(b, revision_id_list, revision)
3865
def _run(self, b, revision_id_list, revision):
3866
import bzrlib.gpg as gpg
3867
gpg_strategy = gpg.GPGStrategy(b.get_config())
3868
if revision_id_list is not None:
3869
b.repository.start_write_group()
3871
for revision_id in revision_id_list:
3872
b.repository.sign_revision(revision_id, gpg_strategy)
3874
b.repository.abort_write_group()
3877
b.repository.commit_write_group()
3878
elif revision is not None:
3879
if len(revision) == 1:
3880
revno, rev_id = revision[0].in_history(b)
3881
b.repository.start_write_group()
3883
b.repository.sign_revision(rev_id, gpg_strategy)
3885
b.repository.abort_write_group()
3888
b.repository.commit_write_group()
3889
elif len(revision) == 2:
3890
# are they both on rh- if so we can walk between them
3891
# might be nice to have a range helper for arbitrary
3892
# revision paths. hmm.
3893
from_revno, from_revid = revision[0].in_history(b)
3894
to_revno, to_revid = revision[1].in_history(b)
3895
if to_revid is None:
3896
to_revno = b.revno()
3897
if from_revno is None or to_revno is None:
3898
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3899
b.repository.start_write_group()
3901
for revno in range(from_revno, to_revno + 1):
3902
b.repository.sign_revision(b.get_rev_id(revno),
3905
b.repository.abort_write_group()
3908
b.repository.commit_write_group()
3910
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3913
class cmd_bind(Command):
3914
"""Convert the current branch into a checkout of the supplied branch.
3916
Once converted into a checkout, commits must succeed on the master branch
3917
before they will be applied to the local branch.
3919
Bound branches use the nickname of its master branch unless it is set
3920
locally, in which case binding will update the the local nickname to be
3924
_see_also = ['checkouts', 'unbind']
3925
takes_args = ['location?']
3928
def run(self, location=None):
3929
b, relpath = Branch.open_containing(u'.')
3930
if location is None:
3932
location = b.get_old_bound_location()
3933
except errors.UpgradeRequired:
3934
raise errors.BzrCommandError('No location supplied. '
3935
'This format does not remember old locations.')
3937
if location is None:
3938
raise errors.BzrCommandError('No location supplied and no '
3939
'previous location known')
3940
b_other = Branch.open(location)
3943
except errors.DivergedBranches:
3944
raise errors.BzrCommandError('These branches have diverged.'
3945
' Try merging, and then bind again.')
3946
if b.get_config().has_explicit_nickname():
3947
b.nick = b_other.nick
3950
class cmd_unbind(Command):
3951
"""Convert the current checkout into a regular branch.
3953
After unbinding, the local branch is considered independent and subsequent
3954
commits will be local only.
3957
_see_also = ['checkouts', 'bind']
3962
b, relpath = Branch.open_containing(u'.')
3964
raise errors.BzrCommandError('Local branch is not bound')
3967
class cmd_uncommit(Command):
3968
"""Remove the last committed revision.
3970
--verbose will print out what is being removed.
3971
--dry-run will go through all the motions, but not actually
3974
If --revision is specified, uncommit revisions to leave the branch at the
3975
specified revision. For example, "bzr uncommit -r 15" will leave the
3976
branch at revision 15.
3978
Uncommit leaves the working tree ready for a new commit. The only change
3979
it may make is to restore any pending merges that were present before
3983
# TODO: jam 20060108 Add an option to allow uncommit to remove
3984
# unreferenced information in 'branch-as-repository' branches.
3985
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3986
# information in shared branches as well.
3987
_see_also = ['commit']
3988
takes_options = ['verbose', 'revision',
3989
Option('dry-run', help='Don\'t actually make changes.'),
3990
Option('force', help='Say yes to all questions.'),
3992
help="Only remove the commits from the local branch"
3993
" when in a checkout."
3996
takes_args = ['location?']
3998
encoding_type = 'replace'
4000
def run(self, location=None,
4001
dry_run=False, verbose=False,
4002
revision=None, force=False, local=False):
4003
if location is None:
4005
control, relpath = bzrdir.BzrDir.open_containing(location)
4007
tree = control.open_workingtree()
4009
except (errors.NoWorkingTree, errors.NotLocalUrl):
4011
b = control.open_branch()
4013
if tree is not None:
4018
return self._run(b, tree, dry_run, verbose, revision, force,
4021
if tree is not None:
4026
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4027
from bzrlib.log import log_formatter, show_log
4028
from bzrlib.uncommit import uncommit
4030
last_revno, last_rev_id = b.last_revision_info()
4033
if revision is None:
4035
rev_id = last_rev_id
4037
# 'bzr uncommit -r 10' actually means uncommit
4038
# so that the final tree is at revno 10.
4039
# but bzrlib.uncommit.uncommit() actually uncommits
4040
# the revisions that are supplied.
4041
# So we need to offset it by one
4042
revno = revision[0].in_history(b).revno + 1
4043
if revno <= last_revno:
4044
rev_id = b.get_rev_id(revno)
4046
if rev_id is None or _mod_revision.is_null(rev_id):
4047
self.outf.write('No revisions to uncommit.\n')
4050
lf = log_formatter('short',
4052
show_timezone='original')
4057
direction='forward',
4058
start_revision=revno,
4059
end_revision=last_revno)
4062
print 'Dry-run, pretending to remove the above revisions.'
4064
val = raw_input('Press <enter> to continue')
4066
print 'The above revision(s) will be removed.'
4068
val = raw_input('Are you sure [y/N]? ')
4069
if val.lower() not in ('y', 'yes'):
4073
mutter('Uncommitting from {%s} to {%s}',
4074
last_rev_id, rev_id)
4075
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4076
revno=revno, local=local)
4077
note('You can restore the old tip by running:\n'
4078
' bzr pull . -r revid:%s', last_rev_id)
4081
class cmd_break_lock(Command):
4082
"""Break a dead lock on a repository, branch or working directory.
4084
CAUTION: Locks should only be broken when you are sure that the process
4085
holding the lock has been stopped.
4087
You can get information on what locks are open via the 'bzr info' command.
4092
takes_args = ['location?']
4094
def run(self, location=None, show=False):
4095
if location is None:
4097
control, relpath = bzrdir.BzrDir.open_containing(location)
4099
control.break_lock()
4100
except NotImplementedError:
4104
class cmd_wait_until_signalled(Command):
4105
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4107
This just prints a line to signal when it is ready, then blocks on stdin.
4113
sys.stdout.write("running\n")
4115
sys.stdin.readline()
4118
class cmd_serve(Command):
4119
"""Run the bzr server."""
4121
aliases = ['server']
4125
help='Serve on stdin/out for use from inetd or sshd.'),
4127
help='Listen for connections on nominated port of the form '
4128
'[hostname:]portnumber. Passing 0 as the port number will '
4129
'result in a dynamically allocated port. The default port is '
4133
help='Serve contents of this directory.',
4135
Option('allow-writes',
4136
help='By default the server is a readonly server. Supplying '
4137
'--allow-writes enables write access to the contents of '
4138
'the served directory and below.'
4142
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4143
from bzrlib import lockdir
4144
from bzrlib.smart import medium, server
4145
from bzrlib.transport import get_transport
4146
from bzrlib.transport.chroot import ChrootServer
4147
if directory is None:
4148
directory = os.getcwd()
4149
url = urlutils.local_path_to_url(directory)
4150
if not allow_writes:
4151
url = 'readonly+' + url
4152
chroot_server = ChrootServer(get_transport(url))
4153
chroot_server.setUp()
4154
t = get_transport(chroot_server.get_url())
4156
smart_server = medium.SmartServerPipeStreamMedium(
4157
sys.stdin, sys.stdout, t)
4159
host = medium.BZR_DEFAULT_INTERFACE
4161
port = medium.BZR_DEFAULT_PORT
4164
host, port = port.split(':')
4166
smart_server = server.SmartTCPServer(t, host=host, port=port)
4167
print 'listening on port: ', smart_server.port
4169
# for the duration of this server, no UI output is permitted.
4170
# note that this may cause problems with blackbox tests. This should
4171
# be changed with care though, as we dont want to use bandwidth sending
4172
# progress over stderr to smart server clients!
4173
old_factory = ui.ui_factory
4174
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4176
ui.ui_factory = ui.SilentUIFactory()
4177
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4178
smart_server.serve()
4180
ui.ui_factory = old_factory
4181
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4184
class cmd_join(Command):
4185
"""Combine a subtree into its containing tree.
4187
This command is for experimental use only. It requires the target tree
4188
to be in dirstate-with-subtree format, which cannot be converted into
4191
The TREE argument should be an independent tree, inside another tree, but
4192
not part of it. (Such trees can be produced by "bzr split", but also by
4193
running "bzr branch" with the target inside a tree.)
4195
The result is a combined tree, with the subtree no longer an independant
4196
part. This is marked as a merge of the subtree into the containing tree,
4197
and all history is preserved.
4199
If --reference is specified, the subtree retains its independence. It can
4200
be branched by itself, and can be part of multiple projects at the same
4201
time. But operations performed in the containing tree, such as commit
4202
and merge, will recurse into the subtree.
4205
_see_also = ['split']
4206
takes_args = ['tree']
4208
Option('reference', help='Join by reference.'),
4212
def run(self, tree, reference=False):
4213
sub_tree = WorkingTree.open(tree)
4214
parent_dir = osutils.dirname(sub_tree.basedir)
4215
containing_tree = WorkingTree.open_containing(parent_dir)[0]
4216
repo = containing_tree.branch.repository
4217
if not repo.supports_rich_root():
4218
raise errors.BzrCommandError(
4219
"Can't join trees because %s doesn't support rich root data.\n"
4220
"You can use bzr upgrade on the repository."
4224
containing_tree.add_reference(sub_tree)
4225
except errors.BadReferenceTarget, e:
4226
# XXX: Would be better to just raise a nicely printable
4227
# exception from the real origin. Also below. mbp 20070306
4228
raise errors.BzrCommandError("Cannot join %s. %s" %
4232
containing_tree.subsume(sub_tree)
4233
except errors.BadSubsumeSource, e:
4234
raise errors.BzrCommandError("Cannot join %s. %s" %
4238
class cmd_split(Command):
4239
"""Split a subdirectory of a tree into a separate tree.
4241
This command will produce a target tree in a format that supports
4242
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4243
converted into earlier formats like 'dirstate-tags'.
4245
The TREE argument should be a subdirectory of a working tree. That
4246
subdirectory will be converted into an independent tree, with its own
4247
branch. Commits in the top-level tree will not apply to the new subtree.
4250
# join is not un-hidden yet
4251
#_see_also = ['join']
4252
takes_args = ['tree']
4254
def run(self, tree):
4255
containing_tree, subdir = WorkingTree.open_containing(tree)
4256
sub_id = containing_tree.path2id(subdir)
4258
raise errors.NotVersionedError(subdir)
4260
containing_tree.extract(sub_id)
4261
except errors.RootNotRich:
4262
raise errors.UpgradeRequired(containing_tree.branch.base)
4265
class cmd_merge_directive(Command):
4266
"""Generate a merge directive for auto-merge tools.
4268
A directive requests a merge to be performed, and also provides all the
4269
information necessary to do so. This means it must either include a
4270
revision bundle, or the location of a branch containing the desired
4273
A submit branch (the location to merge into) must be supplied the first
4274
time the command is issued. After it has been supplied once, it will
4275
be remembered as the default.
4277
A public branch is optional if a revision bundle is supplied, but required
4278
if --diff or --plain is specified. It will be remembered as the default
4279
after the first use.
4282
takes_args = ['submit_branch?', 'public_branch?']
4286
_see_also = ['send']
4289
RegistryOption.from_kwargs('patch-type',
4290
'The type of patch to include in the directive.',
4292
value_switches=True,
4294
bundle='Bazaar revision bundle (default).',
4295
diff='Normal unified diff.',
4296
plain='No patch, just directive.'),
4297
Option('sign', help='GPG-sign the directive.'), 'revision',
4298
Option('mail-to', type=str,
4299
help='Instead of printing the directive, email to this address.'),
4300
Option('message', type=str, short_name='m',
4301
help='Message to use when committing this merge.')
4304
encoding_type = 'exact'
4306
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4307
sign=False, revision=None, mail_to=None, message=None):
4308
from bzrlib.revision import ensure_null, NULL_REVISION
4309
include_patch, include_bundle = {
4310
'plain': (False, False),
4311
'diff': (True, False),
4312
'bundle': (True, True),
4314
branch = Branch.open('.')
4315
stored_submit_branch = branch.get_submit_branch()
4316
if submit_branch is None:
4317
submit_branch = stored_submit_branch
4319
if stored_submit_branch is None:
4320
branch.set_submit_branch(submit_branch)
4321
if submit_branch is None:
4322
submit_branch = branch.get_parent()
4323
if submit_branch is None:
4324
raise errors.BzrCommandError('No submit branch specified or known')
4326
stored_public_branch = branch.get_public_branch()
4327
if public_branch is None:
4328
public_branch = stored_public_branch
4329
elif stored_public_branch is None:
4330
branch.set_public_branch(public_branch)
4331
if not include_bundle and public_branch is None:
4332
raise errors.BzrCommandError('No public branch specified or'
4334
base_revision_id = None
4335
if revision is not None:
4336
if len(revision) > 2:
4337
raise errors.BzrCommandError('bzr merge-directive takes '
4338
'at most two one revision identifiers')
4339
revision_id = revision[-1].as_revision_id(branch)
4340
if len(revision) == 2:
4341
base_revision_id = revision[0].as_revision_id(branch)
4343
revision_id = branch.last_revision()
4344
revision_id = ensure_null(revision_id)
4345
if revision_id == NULL_REVISION:
4346
raise errors.BzrCommandError('No revisions to bundle.')
4347
directive = merge_directive.MergeDirective2.from_objects(
4348
branch.repository, revision_id, time.time(),
4349
osutils.local_time_offset(), submit_branch,
4350
public_branch=public_branch, include_patch=include_patch,
4351
include_bundle=include_bundle, message=message,
4352
base_revision_id=base_revision_id)
4355
self.outf.write(directive.to_signed(branch))
4357
self.outf.writelines(directive.to_lines())
4359
message = directive.to_email(mail_to, branch, sign)
4360
s = SMTPConnection(branch.get_config())
4361
s.send_email(message)
4364
class cmd_send(Command):
4365
"""Mail or create a merge-directive for submitting changes.
4367
A merge directive provides many things needed for requesting merges:
4369
* A machine-readable description of the merge to perform
4371
* An optional patch that is a preview of the changes requested
4373
* An optional bundle of revision data, so that the changes can be applied
4374
directly from the merge directive, without retrieving data from a
4377
If --no-bundle is specified, then public_branch is needed (and must be
4378
up-to-date), so that the receiver can perform the merge using the
4379
public_branch. The public_branch is always included if known, so that
4380
people can check it later.
4382
The submit branch defaults to the parent, but can be overridden. Both
4383
submit branch and public branch will be remembered if supplied.
4385
If a public_branch is known for the submit_branch, that public submit
4386
branch is used in the merge instructions. This means that a local mirror
4387
can be used as your actual submit branch, once you have set public_branch
4390
Mail is sent using your preferred mail program. This should be transparent
4391
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4392
If the preferred client can't be found (or used), your editor will be used.
4394
To use a specific mail program, set the mail_client configuration option.
4395
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4396
specific clients are "claws", "evolution", "kmail", "mutt", and
4397
"thunderbird"; generic options are "default", "editor", "emacsclient",
4398
"mapi", and "xdg-email". Plugins may also add supported clients.
4400
If mail is being sent, a to address is required. This can be supplied
4401
either on the commandline, by setting the submit_to configuration
4402
option in the branch itself or the child_submit_to configuration option
4403
in the submit branch.
4405
Two formats are currently supported: "4" uses revision bundle format 4 and
4406
merge directive format 2. It is significantly faster and smaller than
4407
older formats. It is compatible with Bazaar 0.19 and later. It is the
4408
default. "0.9" uses revision bundle format 0.9 and merge directive
4409
format 1. It is compatible with Bazaar 0.12 - 0.18.
4411
Merge directives are applied using the merge command or the pull command.
4414
encoding_type = 'exact'
4416
_see_also = ['merge', 'pull']
4418
takes_args = ['submit_branch?', 'public_branch?']
4422
help='Do not include a bundle in the merge directive.'),
4423
Option('no-patch', help='Do not include a preview patch in the merge'
4426
help='Remember submit and public branch.'),
4428
help='Branch to generate the submission from, '
4429
'rather than the one containing the working directory.',
4432
Option('output', short_name='o',
4433
help='Write merge directive to this file; '
4434
'use - for stdout.',
4436
Option('mail-to', help='Mail the request to this address.',
4440
RegistryOption.from_kwargs('format',
4441
'Use the specified output format.',
4442
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4443
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4446
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4447
no_patch=False, revision=None, remember=False, output=None,
4448
format='4', mail_to=None, message=None, **kwargs):
4449
return self._run(submit_branch, revision, public_branch, remember,
4450
format, no_bundle, no_patch, output,
4451
kwargs.get('from', '.'), mail_to, message)
4453
def _run(self, submit_branch, revision, public_branch, remember, format,
4454
no_bundle, no_patch, output, from_, mail_to, message):
4455
from bzrlib.revision import NULL_REVISION
4456
branch = Branch.open_containing(from_)[0]
4458
outfile = cStringIO.StringIO()
4462
outfile = open(output, 'wb')
4463
# we may need to write data into branch's repository to calculate
4468
config = branch.get_config()
4470
mail_to = config.get_user_option('submit_to')
4471
mail_client = config.get_mail_client()
4472
if remember and submit_branch is None:
4473
raise errors.BzrCommandError(
4474
'--remember requires a branch to be specified.')
4475
stored_submit_branch = branch.get_submit_branch()
4476
remembered_submit_branch = None
4477
if submit_branch is None:
4478
submit_branch = stored_submit_branch
4479
remembered_submit_branch = "submit"
4481
if stored_submit_branch is None or remember:
4482
branch.set_submit_branch(submit_branch)
4483
if submit_branch is None:
4484
submit_branch = branch.get_parent()
4485
remembered_submit_branch = "parent"
4486
if submit_branch is None:
4487
raise errors.BzrCommandError('No submit branch known or'
4489
if remembered_submit_branch is not None:
4490
note('Using saved %s location "%s" to determine what '
4491
'changes to submit.', remembered_submit_branch,
4495
submit_config = Branch.open(submit_branch).get_config()
4496
mail_to = submit_config.get_user_option("child_submit_to")
4498
stored_public_branch = branch.get_public_branch()
4499
if public_branch is None:
4500
public_branch = stored_public_branch
4501
elif stored_public_branch is None or remember:
4502
branch.set_public_branch(public_branch)
4503
if no_bundle and public_branch is None:
4504
raise errors.BzrCommandError('No public branch specified or'
4506
base_revision_id = None
4508
if revision is not None:
4509
if len(revision) > 2:
4510
raise errors.BzrCommandError('bzr send takes '
4511
'at most two one revision identifiers')
4512
revision_id = revision[-1].as_revision_id(branch)
4513
if len(revision) == 2:
4514
base_revision_id = revision[0].as_revision_id(branch)
4515
if revision_id is None:
4516
revision_id = branch.last_revision()
4517
if revision_id == NULL_REVISION:
4518
raise errors.BzrCommandError('No revisions to submit.')
4520
directive = merge_directive.MergeDirective2.from_objects(
4521
branch.repository, revision_id, time.time(),
4522
osutils.local_time_offset(), submit_branch,
4523
public_branch=public_branch, include_patch=not no_patch,
4524
include_bundle=not no_bundle, message=message,
4525
base_revision_id=base_revision_id)
4526
elif format == '0.9':
4529
patch_type = 'bundle'
4531
raise errors.BzrCommandError('Format 0.9 does not'
4532
' permit bundle with no patch')
4538
directive = merge_directive.MergeDirective.from_objects(
4539
branch.repository, revision_id, time.time(),
4540
osutils.local_time_offset(), submit_branch,
4541
public_branch=public_branch, patch_type=patch_type,
4544
outfile.writelines(directive.to_lines())
4546
subject = '[MERGE] '
4547
if message is not None:
4550
revision = branch.repository.get_revision(revision_id)
4551
subject += revision.get_summary()
4552
basename = directive.get_disk_name(branch)
4553
mail_client.compose_merge_request(mail_to, subject,
4554
outfile.getvalue(), basename)
4561
class cmd_bundle_revisions(cmd_send):
4563
"""Create a merge-directive for submitting changes.
4565
A merge directive provides many things needed for requesting merges:
4567
* A machine-readable description of the merge to perform
4569
* An optional patch that is a preview of the changes requested
4571
* An optional bundle of revision data, so that the changes can be applied
4572
directly from the merge directive, without retrieving data from a
4575
If --no-bundle is specified, then public_branch is needed (and must be
4576
up-to-date), so that the receiver can perform the merge using the
4577
public_branch. The public_branch is always included if known, so that
4578
people can check it later.
4580
The submit branch defaults to the parent, but can be overridden. Both
4581
submit branch and public branch will be remembered if supplied.
4583
If a public_branch is known for the submit_branch, that public submit
4584
branch is used in the merge instructions. This means that a local mirror
4585
can be used as your actual submit branch, once you have set public_branch
4588
Two formats are currently supported: "4" uses revision bundle format 4 and
4589
merge directive format 2. It is significantly faster and smaller than
4590
older formats. It is compatible with Bazaar 0.19 and later. It is the
4591
default. "0.9" uses revision bundle format 0.9 and merge directive
4592
format 1. It is compatible with Bazaar 0.12 - 0.18.
4597
help='Do not include a bundle in the merge directive.'),
4598
Option('no-patch', help='Do not include a preview patch in the merge'
4601
help='Remember submit and public branch.'),
4603
help='Branch to generate the submission from, '
4604
'rather than the one containing the working directory.',
4607
Option('output', short_name='o', help='Write directive to this file.',
4610
RegistryOption.from_kwargs('format',
4611
'Use the specified output format.',
4612
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4613
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4615
aliases = ['bundle']
4617
_see_also = ['send', 'merge']
4621
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4622
no_patch=False, revision=None, remember=False, output=None,
4623
format='4', **kwargs):
4626
return self._run(submit_branch, revision, public_branch, remember,
4627
format, no_bundle, no_patch, output,
4628
kwargs.get('from', '.'), None, None)
4631
class cmd_tag(Command):
4632
"""Create, remove or modify a tag naming a revision.
4634
Tags give human-meaningful names to revisions. Commands that take a -r
4635
(--revision) option can be given -rtag:X, where X is any previously
4638
Tags are stored in the branch. Tags are copied from one branch to another
4639
along when you branch, push, pull or merge.
4641
It is an error to give a tag name that already exists unless you pass
4642
--force, in which case the tag is moved to point to the new revision.
4644
To rename a tag (change the name but keep it on the same revsion), run ``bzr
4645
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4648
_see_also = ['commit', 'tags']
4649
takes_args = ['tag_name']
4652
help='Delete this tag rather than placing it.',
4655
help='Branch in which to place the tag.',
4660
help='Replace existing tags.',
4665
def run(self, tag_name,
4671
branch, relpath = Branch.open_containing(directory)
4675
branch.tags.delete_tag(tag_name)
4676
self.outf.write('Deleted tag %s.\n' % tag_name)
4679
if len(revision) != 1:
4680
raise errors.BzrCommandError(
4681
"Tags can only be placed on a single revision, "
4683
revision_id = revision[0].as_revision_id(branch)
4685
revision_id = branch.last_revision()
4686
if (not force) and branch.tags.has_tag(tag_name):
4687
raise errors.TagAlreadyExists(tag_name)
4688
branch.tags.set_tag(tag_name, revision_id)
4689
self.outf.write('Created tag %s.\n' % tag_name)
4694
class cmd_tags(Command):
4697
This command shows a table of tag names and the revisions they reference.
4703
help='Branch whose tags should be displayed.',
4707
RegistryOption.from_kwargs('sort',
4708
'Sort tags by different criteria.', title='Sorting',
4709
alpha='Sort tags lexicographically (default).',
4710
time='Sort tags chronologically.',
4723
branch, relpath = Branch.open_containing(directory)
4725
tags = branch.tags.get_tag_dict().items()
4732
graph = branch.repository.get_graph()
4733
rev1, rev2 = _get_revision_range(revision, branch, self.name())
4734
revid1, revid2 = rev1.rev_id, rev2.rev_id
4735
# only show revisions between revid1 and revid2 (inclusive)
4736
tags = [(tag, revid) for tag, revid in tags if
4737
graph.is_between(revid, revid1, revid2)]
4742
elif sort == 'time':
4744
for tag, revid in tags:
4746
revobj = branch.repository.get_revision(revid)
4747
except errors.NoSuchRevision:
4748
timestamp = sys.maxint # place them at the end
4750
timestamp = revobj.timestamp
4751
timestamps[revid] = timestamp
4752
tags.sort(key=lambda x: timestamps[x[1]])
4754
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
4755
revno_map = branch.get_revision_id_to_revno_map()
4756
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4757
for tag, revid in tags ]
4758
for tag, revspec in tags:
4759
self.outf.write('%-20s %s\n' % (tag, revspec))
4762
class cmd_reconfigure(Command):
4763
"""Reconfigure the type of a bzr directory.
4765
A target configuration must be specified.
4767
For checkouts, the bind-to location will be auto-detected if not specified.
4768
The order of preference is
4769
1. For a lightweight checkout, the current bound location.
4770
2. For branches that used to be checkouts, the previously-bound location.
4771
3. The push location.
4772
4. The parent location.
4773
If none of these is available, --bind-to must be specified.
4776
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4777
takes_args = ['location?']
4778
takes_options = [RegistryOption.from_kwargs('target_type',
4779
title='Target type',
4780
help='The type to reconfigure the directory to.',
4781
value_switches=True, enum_switch=False,
4782
branch='Reconfigure to be an unbound branch '
4783
'with no working tree.',
4784
tree='Reconfigure to be an unbound branch '
4785
'with a working tree.',
4786
checkout='Reconfigure to be a bound branch '
4787
'with a working tree.',
4788
lightweight_checkout='Reconfigure to be a lightweight'
4789
' checkout (with no local history).',
4790
standalone='Reconfigure to be a standalone branch '
4791
'(i.e. stop using shared repository).',
4792
use_shared='Reconfigure to use a shared repository.'),
4793
Option('bind-to', help='Branch to bind checkout to.',
4796
help='Perform reconfiguration even if local changes'
4800
def run(self, location=None, target_type=None, bind_to=None, force=False):
4801
directory = bzrdir.BzrDir.open(location)
4802
if target_type is None:
4803
raise errors.BzrCommandError('No target configuration specified')
4804
elif target_type == 'branch':
4805
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4806
elif target_type == 'tree':
4807
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4808
elif target_type == 'checkout':
4809
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4811
elif target_type == 'lightweight-checkout':
4812
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4814
elif target_type == 'use-shared':
4815
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
4816
elif target_type == 'standalone':
4817
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
4818
reconfiguration.apply(force)
4821
class cmd_switch(Command):
4822
"""Set the branch of a checkout and update.
4824
For lightweight checkouts, this changes the branch being referenced.
4825
For heavyweight checkouts, this checks that there are no local commits
4826
versus the current bound branch, then it makes the local branch a mirror
4827
of the new location and binds to it.
4829
In both cases, the working tree is updated and uncommitted changes
4830
are merged. The user can commit or revert these as they desire.
4832
Pending merges need to be committed or reverted before using switch.
4834
The path to the branch to switch to can be specified relative to the parent
4835
directory of the current branch. For example, if you are currently in a
4836
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
4839
Bound branches use the nickname of its master branch unless it is set
4840
locally, in which case switching will update the the local nickname to be
4844
takes_args = ['to_location']
4845
takes_options = [Option('force',
4846
help='Switch even if local commits will be lost.')
4849
def run(self, to_location, force=False):
4850
from bzrlib import switch
4852
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4853
branch = control_dir.open_branch()
4855
to_branch = Branch.open(to_location)
4856
except errors.NotBranchError:
4857
this_branch = control_dir.open_branch()
4858
# This may be a heavy checkout, where we want the master branch
4859
this_url = this_branch.get_bound_location()
4860
# If not, use a local sibling
4861
if this_url is None:
4862
this_url = this_branch.base
4863
to_branch = Branch.open(
4864
urlutils.join(this_url, '..', to_location))
4865
switch.switch(control_dir, to_branch, force)
4866
if branch.get_config().has_explicit_nickname():
4867
branch = control_dir.open_branch() #get the new branch!
4868
branch.nick = to_branch.nick
4869
note('Switched to branch: %s',
4870
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4873
class cmd_hooks(Command):
4874
"""Show a branch's currently registered hooks.
4878
takes_args = ['path?']
4880
def run(self, path=None):
4883
branch_hooks = Branch.open(path).hooks
4884
for hook_type in branch_hooks:
4885
hooks = branch_hooks[hook_type]
4886
self.outf.write("%s:\n" % (hook_type,))
4889
self.outf.write(" %s\n" %
4890
(branch_hooks.get_hook_name(hook),))
4892
self.outf.write(" <no hooks installed>\n")
4895
class cmd_shelve(Command):
4896
"""Temporarily set aside some changes from the current tree.
4898
Shelve allows you to temporarily put changes you've made "on the shelf",
4899
ie. out of the way, until a later time when you can bring them back from
4900
the shelf with the 'unshelve' command.
4902
If shelve --list is specified, previously-shelved changes are listed.
4904
Shelve is intended to help separate several sets of changes that have
4905
been inappropriately mingled. If you just want to get rid of all changes
4906
and you don't need to restore them later, use revert. If you want to
4907
shelve all text changes at once, use shelve --all.
4909
If filenames are specified, only the changes to those files will be
4910
shelved. Other files will be left untouched.
4912
If a revision is specified, changes since that revision will be shelved.
4914
You can put multiple items on the shelf, and by default, 'unshelve' will
4915
restore the most recently shelved changes.
4918
takes_args = ['file*']
4922
Option('all', help='Shelve all changes.'),
4924
RegistryOption('writer', 'Method to use for writing diffs.',
4925
bzrlib.option.diff_writer_registry,
4926
value_switches=True, enum_switch=False),
4928
Option('list', help='List shelved changes.'),
4930
_see_also = ['unshelve']
4932
def run(self, revision=None, all=False, file_list=None, message=None,
4933
writer=None, list=False):
4935
return self.run_for_list()
4936
from bzrlib.shelf_ui import Shelver
4938
writer = bzrlib.option.diff_writer_registry.get()
4940
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
4942
except errors.UserAbort:
4945
def run_for_list(self):
4946
tree = WorkingTree.open_containing('.')[0]
4949
manager = tree.get_shelf_manager()
4950
shelves = manager.active_shelves()
4951
if len(shelves) == 0:
4952
note('No shelved changes.')
4954
for shelf_id in reversed(shelves):
4955
message = manager.get_metadata(shelf_id).get('message')
4957
message = '<no message>'
4958
self.outf.write('%3d: %s\n' % (shelf_id, message))
4964
class cmd_unshelve(Command):
4965
"""Restore shelved changes.
4967
By default, the most recently shelved changes are restored. However if you
4968
specify a patch by name those changes will be restored instead. This
4969
works best when the changes don't depend on each other.
4972
takes_args = ['shelf_id?']
4974
RegistryOption.from_kwargs(
4975
'action', help="The action to perform.",
4976
enum_switch=False, value_switches=True,
4977
apply="Apply changes and remove from the shelf.",
4978
dry_run="Show changes, but do not apply or remove them.",
4979
delete_only="Delete changes without applying them."
4982
_see_also = ['shelve']
4984
def run(self, shelf_id=None, action='apply'):
4985
from bzrlib.shelf_ui import Unshelver
4986
Unshelver.from_args(shelf_id, action).run()
4989
def _create_prefix(cur_transport):
4990
needed = [cur_transport]
4991
# Recurse upwards until we can create a directory successfully
4993
new_transport = cur_transport.clone('..')
4994
if new_transport.base == cur_transport.base:
4995
raise errors.BzrCommandError(
4996
"Failed to create path prefix for %s."
4997
% cur_transport.base)
4999
new_transport.mkdir('.')
5000
except errors.NoSuchFile:
5001
needed.append(new_transport)
5002
cur_transport = new_transport
5005
# Now we only need to create child directories
5007
cur_transport = needed.pop()
5008
cur_transport.ensure_base()
5011
# these get imported and then picked up by the scan for cmd_*
5012
# TODO: Some more consistent way to split command definitions across files;
5013
# we do need to load at least some information about them to know of
5014
# aliases. ideally we would avoid loading the implementation until the
5015
# details were needed.
5016
from bzrlib.cmd_version_info import cmd_version_info
5017
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5018
from bzrlib.bundle.commands import (
5021
from bzrlib.sign_my_commits import cmd_sign_my_commits
5022
from bzrlib.weave_commands import cmd_versionedfile_list, \
5023
cmd_weave_plan_merge, cmd_weave_merge_text