1
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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, RevisionInfo
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(command_name, revisions):
79
if len(revisions) != 1:
80
raise errors.BzrCommandError(
81
'bzr %s --revision takes exactly one revision identifier' % (
86
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
91
rev_tree = tree.basis_tree()
93
rev_tree = branch.basis_tree()
95
revision = _get_one_revision(command_name, revisions)
96
rev_tree = revision.as_tree(branch)
100
# XXX: Bad function name; should possibly also be a class method of
101
# WorkingTree rather than a function.
102
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True):
103
"""Convert command-line paths to a WorkingTree and relative paths.
105
This is typically used for command-line processors that take one or
106
more filenames, and infer the workingtree that contains them.
108
The filenames given are not required to exist.
110
:param file_list: Filenames to convert.
112
:param default_branch: Fallback tree path to use if file_list is empty or
115
:return: workingtree, [relative_paths]
117
if file_list is None or len(file_list) == 0:
118
return WorkingTree.open_containing(default_branch)[0], file_list
119
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
120
return tree, safe_relpath_files(tree, file_list, canonicalize)
123
def safe_relpath_files(tree, file_list, canonicalize=True):
124
"""Convert file_list into a list of relpaths in tree.
126
:param tree: A tree to operate on.
127
:param file_list: A list of user provided paths or None.
128
:return: A list of relative paths.
129
:raises errors.PathNotChild: When a provided path is in a different tree
132
if file_list is None:
135
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
136
# doesn't - fix that up here before we enter the loop.
138
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
141
for filename in file_list:
143
new_list.append(fixer(osutils.dereference_path(filename)))
144
except errors.PathNotChild:
145
raise errors.FileInWrongBranch(tree.branch, filename)
149
# TODO: Make sure no commands unconditionally use the working directory as a
150
# branch. If a filename argument is used, the first of them should be used to
151
# specify the branch. (Perhaps this can be factored out into some kind of
152
# Argument class, representing a file in a branch, where the first occurrence
155
class cmd_status(Command):
156
"""Display status summary.
158
This reports on versioned and unknown files, reporting them
159
grouped by state. Possible states are:
162
Versioned in the working copy but not in the previous revision.
165
Versioned in the previous revision but removed or deleted
169
Path of this file changed from the previous revision;
170
the text may also have changed. This includes files whose
171
parent directory was renamed.
174
Text has changed since the previous revision.
177
File kind has been changed (e.g. from file to directory).
180
Not versioned and not matching an ignore pattern.
182
To see ignored files use 'bzr ignored'. For details on the
183
changes to file texts, use 'bzr diff'.
185
Note that --short or -S gives status flags for each item, similar
186
to Subversion's status command. To get output similar to svn -q,
189
If no arguments are specified, the status of the entire working
190
directory is shown. Otherwise, only the status of the specified
191
files or directories is reported. If a directory is given, status
192
is reported for everything inside that directory.
194
Before merges are committed, the pending merge tip revisions are
195
shown. To see all pending merge revisions, use the -v option.
196
To skip the display of pending merge information altogether, use
197
the no-pending option or specify a file/directory.
199
If a revision argument is given, the status is calculated against
200
that revision, or between two revisions if two are provided.
203
# TODO: --no-recurse, --recurse options
205
takes_args = ['file*']
206
takes_options = ['show-ids', 'revision', 'change', 'verbose',
207
Option('short', help='Use short status indicators.',
209
Option('versioned', help='Only show versioned files.',
211
Option('no-pending', help='Don\'t show pending merges.',
214
aliases = ['st', 'stat']
216
encoding_type = 'replace'
217
_see_also = ['diff', 'revert', 'status-flags']
220
def run(self, show_ids=False, file_list=None, revision=None, short=False,
221
versioned=False, no_pending=False, verbose=False):
222
from bzrlib.status import show_tree_status
224
if revision and len(revision) > 2:
225
raise errors.BzrCommandError('bzr status --revision takes exactly'
226
' one or two revision specifiers')
228
tree, relfile_list = tree_files(file_list)
229
# Avoid asking for specific files when that is not needed.
230
if relfile_list == ['']:
232
# Don't disable pending merges for full trees other than '.'.
233
if file_list == ['.']:
235
# A specific path within a tree was given.
236
elif relfile_list is not None:
238
show_tree_status(tree, show_ids=show_ids,
239
specific_files=relfile_list, revision=revision,
240
to_file=self.outf, short=short, versioned=versioned,
241
show_pending=(not no_pending), verbose=verbose)
244
class cmd_cat_revision(Command):
245
"""Write out metadata for a revision.
247
The revision to print can either be specified by a specific
248
revision identifier, or you can use --revision.
252
takes_args = ['revision_id?']
253
takes_options = ['revision']
254
# cat-revision is more for frontends so should be exact
258
def run(self, revision_id=None, revision=None):
259
if revision_id is not None and revision is not None:
260
raise errors.BzrCommandError('You can only supply one of'
261
' revision_id or --revision')
262
if revision_id is None and revision is None:
263
raise errors.BzrCommandError('You must supply either'
264
' --revision or a revision_id')
265
b = WorkingTree.open_containing(u'.')[0].branch
267
# TODO: jam 20060112 should cat-revision always output utf-8?
268
if revision_id is not None:
269
revision_id = osutils.safe_revision_id(revision_id, warn=False)
271
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
272
except errors.NoSuchRevision:
273
msg = "The repository %s contains no revision %s." % (b.repository.base,
275
raise errors.BzrCommandError(msg)
276
elif revision is not None:
279
raise errors.BzrCommandError('You cannot specify a NULL'
281
rev_id = rev.as_revision_id(b)
282
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
285
class cmd_dump_btree(Command):
286
"""Dump the contents of a btree index file to stdout.
288
PATH is a btree index file, it can be any URL. This includes things like
289
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
291
By default, the tuples stored in the index file will be displayed. With
292
--raw, we will uncompress the pages, but otherwise display the raw bytes
296
# TODO: Do we want to dump the internal nodes as well?
297
# TODO: It would be nice to be able to dump the un-parsed information,
298
# rather than only going through iter_all_entries. However, this is
299
# good enough for a start
301
encoding_type = 'exact'
302
takes_args = ['path']
303
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
304
' rather than the parsed tuples.'),
307
def run(self, path, raw=False):
308
dirname, basename = osutils.split(path)
309
t = transport.get_transport(dirname)
311
self._dump_raw_bytes(t, basename)
313
self._dump_entries(t, basename)
315
def _get_index_and_bytes(self, trans, basename):
316
"""Create a BTreeGraphIndex and raw bytes."""
317
bt = btree_index.BTreeGraphIndex(trans, basename, None)
318
bytes = trans.get_bytes(basename)
319
bt._file = cStringIO.StringIO(bytes)
320
bt._size = len(bytes)
323
def _dump_raw_bytes(self, trans, basename):
326
# We need to parse at least the root node.
327
# This is because the first page of every row starts with an
328
# uncompressed header.
329
bt, bytes = self._get_index_and_bytes(trans, basename)
330
for page_idx, page_start in enumerate(xrange(0, len(bytes),
331
btree_index._PAGE_SIZE)):
332
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
333
page_bytes = bytes[page_start:page_end]
335
self.outf.write('Root node:\n')
336
header_end, data = bt._parse_header_from_bytes(page_bytes)
337
self.outf.write(page_bytes[:header_end])
339
self.outf.write('\nPage %d\n' % (page_idx,))
340
decomp_bytes = zlib.decompress(page_bytes)
341
self.outf.write(decomp_bytes)
342
self.outf.write('\n')
344
def _dump_entries(self, trans, basename):
346
st = trans.stat(basename)
347
except errors.TransportNotPossible:
348
# We can't stat, so we'll fake it because we have to do the 'get()'
350
bt, _ = self._get_index_and_bytes(trans, basename)
352
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
353
for node in bt.iter_all_entries():
354
# Node is made up of:
355
# (index, key, value, [references])
356
self.outf.write('%s\n' % (node[1:],))
359
class cmd_remove_tree(Command):
360
"""Remove the working tree from a given branch/checkout.
362
Since a lightweight checkout is little more than a working tree
363
this will refuse to run against one.
365
To re-create the working tree, use "bzr checkout".
367
_see_also = ['checkout', 'working-trees']
368
takes_args = ['location?']
371
help='Remove the working tree even if it has '
372
'uncommitted changes.'),
375
def run(self, location='.', force=False):
376
d = bzrdir.BzrDir.open(location)
379
working = d.open_workingtree()
380
except errors.NoWorkingTree:
381
raise errors.BzrCommandError("No working tree to remove")
382
except errors.NotLocalUrl:
383
raise errors.BzrCommandError("You cannot remove the working tree of a "
386
changes = working.changes_from(working.basis_tree())
387
if changes.has_changed():
388
raise errors.UncommittedChanges(working)
390
working_path = working.bzrdir.root_transport.base
391
branch_path = working.branch.bzrdir.root_transport.base
392
if working_path != branch_path:
393
raise errors.BzrCommandError("You cannot remove the working tree from "
394
"a lightweight checkout")
396
d.destroy_workingtree()
399
class cmd_revno(Command):
400
"""Show current revision number.
402
This is equal to the number of revisions on this branch.
406
takes_args = ['location?']
409
def run(self, location=u'.'):
410
self.outf.write(str(Branch.open_containing(location)[0].revno()))
411
self.outf.write('\n')
414
class cmd_revision_info(Command):
415
"""Show revision number and revision id for a given revision identifier.
418
takes_args = ['revision_info*']
422
help='Branch to examine, '
423
'rather than the one containing the working directory.',
430
def run(self, revision=None, directory=u'.', revision_info_list=[]):
433
if revision is not None:
434
revs.extend(revision)
435
if revision_info_list is not None:
436
for rev in revision_info_list:
437
revs.append(RevisionSpec.from_string(rev))
439
b = Branch.open_containing(directory)[0]
442
revs.append(RevisionSpec.from_string('-1'))
445
revision_id = rev.as_revision_id(b)
447
revno = '%4d' % (b.revision_id_to_revno(revision_id))
448
except errors.NoSuchRevision:
449
dotted_map = b.get_revision_id_to_revno_map()
450
revno = '.'.join(str(i) for i in dotted_map[revision_id])
451
print '%s %s' % (revno, revision_id)
454
class cmd_add(Command):
455
"""Add specified files or directories.
457
In non-recursive mode, all the named items are added, regardless
458
of whether they were previously ignored. A warning is given if
459
any of the named files are already versioned.
461
In recursive mode (the default), files are treated the same way
462
but the behaviour for directories is different. Directories that
463
are already versioned do not give a warning. All directories,
464
whether already versioned or not, are searched for files or
465
subdirectories that are neither versioned or ignored, and these
466
are added. This search proceeds recursively into versioned
467
directories. If no names are given '.' is assumed.
469
Therefore simply saying 'bzr add' will version all files that
470
are currently unknown.
472
Adding a file whose parent directory is not versioned will
473
implicitly add the parent, and so on up to the root. This means
474
you should never need to explicitly add a directory, they'll just
475
get added when you add a file in the directory.
477
--dry-run will show which files would be added, but not actually
480
--file-ids-from will try to use the file ids from the supplied path.
481
It looks up ids trying to find a matching parent directory with the
482
same filename, and then by pure path. This option is rarely needed
483
but can be useful when adding the same logical file into two
484
branches that will be merged later (without showing the two different
485
adds as a conflict). It is also useful when merging another project
486
into a subdirectory of this one.
488
takes_args = ['file*']
491
help="Don't recursively add the contents of directories."),
493
help="Show what would be done, but don't actually do anything."),
495
Option('file-ids-from',
497
help='Lookup file ids from this tree.'),
499
encoding_type = 'replace'
500
_see_also = ['remove']
502
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
507
if file_ids_from is not None:
509
base_tree, base_path = WorkingTree.open_containing(
511
except errors.NoWorkingTree:
512
base_branch, base_path = Branch.open_containing(
514
base_tree = base_branch.basis_tree()
516
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
517
to_file=self.outf, should_print=(not is_quiet()))
519
action = bzrlib.add.AddAction(to_file=self.outf,
520
should_print=(not is_quiet()))
523
base_tree.lock_read()
525
file_list = self._maybe_expand_globs(file_list)
527
tree = WorkingTree.open_containing(file_list[0])[0]
529
tree = WorkingTree.open_containing(u'.')[0]
530
added, ignored = tree.smart_add(file_list, not
531
no_recurse, action=action, save=not dry_run)
533
if base_tree is not None:
537
for glob in sorted(ignored.keys()):
538
for path in ignored[glob]:
539
self.outf.write("ignored %s matching \"%s\"\n"
543
for glob, paths in ignored.items():
544
match_len += len(paths)
545
self.outf.write("ignored %d file(s).\n" % match_len)
546
self.outf.write("If you wish to add some of these files,"
547
" please add them by name.\n")
550
class cmd_mkdir(Command):
551
"""Create a new versioned directory.
553
This is equivalent to creating the directory and then adding it.
556
takes_args = ['dir+']
557
encoding_type = 'replace'
559
def run(self, dir_list):
562
wt, dd = WorkingTree.open_containing(d)
564
self.outf.write('added %s\n' % d)
567
class cmd_relpath(Command):
568
"""Show path of a file relative to root"""
570
takes_args = ['filename']
574
def run(self, filename):
575
# TODO: jam 20050106 Can relpath return a munged path if
576
# sys.stdout encoding cannot represent it?
577
tree, relpath = WorkingTree.open_containing(filename)
578
self.outf.write(relpath)
579
self.outf.write('\n')
582
class cmd_inventory(Command):
583
"""Show inventory of the current working copy or a revision.
585
It is possible to limit the output to a particular entry
586
type using the --kind option. For example: --kind file.
588
It is also possible to restrict the list of files to a specific
589
set. For example: bzr inventory --show-ids this/file
598
help='List entries of a particular kind: file, directory, symlink.',
601
takes_args = ['file*']
604
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
605
if kind and kind not in ['file', 'directory', 'symlink']:
606
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
608
work_tree, file_list = tree_files(file_list)
609
work_tree.lock_read()
611
if revision is not None:
612
if len(revision) > 1:
613
raise errors.BzrCommandError(
614
'bzr inventory --revision takes exactly one revision'
616
tree = revision[0].as_tree(work_tree.branch)
618
extra_trees = [work_tree]
624
if file_list is not None:
625
file_ids = tree.paths2ids(file_list, trees=extra_trees,
626
require_versioned=True)
627
# find_ids_across_trees may include some paths that don't
629
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
630
for file_id in file_ids if file_id in tree)
632
entries = tree.inventory.entries()
635
if tree is not work_tree:
638
for path, entry in entries:
639
if kind and kind != entry.kind:
642
self.outf.write('%-50s %s\n' % (path, entry.file_id))
644
self.outf.write(path)
645
self.outf.write('\n')
648
class cmd_mv(Command):
649
"""Move or rename a file.
652
bzr mv OLDNAME NEWNAME
654
bzr mv SOURCE... DESTINATION
656
If the last argument is a versioned directory, all the other names
657
are moved into it. Otherwise, there must be exactly two arguments
658
and the file is changed to a new name.
660
If OLDNAME does not exist on the filesystem but is versioned and
661
NEWNAME does exist on the filesystem but is not versioned, mv
662
assumes that the file has been manually moved and only updates
663
its internal inventory to reflect that change.
664
The same is valid when moving many SOURCE files to a DESTINATION.
666
Files cannot be moved between branches.
669
takes_args = ['names*']
670
takes_options = [Option("after", help="Move only the bzr identifier"
671
" of the file, because the file has already been moved."),
673
aliases = ['move', 'rename']
674
encoding_type = 'replace'
676
def run(self, names_list, after=False):
677
if names_list is None:
680
if len(names_list) < 2:
681
raise errors.BzrCommandError("missing file argument")
682
tree, rel_names = tree_files(names_list, canonicalize=False)
685
self._run(tree, names_list, rel_names, after)
689
def _run(self, tree, names_list, rel_names, after):
690
into_existing = osutils.isdir(names_list[-1])
691
if into_existing and len(names_list) == 2:
693
# a. case-insensitive filesystem and change case of dir
694
# b. move directory after the fact (if the source used to be
695
# a directory, but now doesn't exist in the working tree
696
# and the target is an existing directory, just rename it)
697
if (not tree.case_sensitive
698
and rel_names[0].lower() == rel_names[1].lower()):
699
into_existing = False
702
# 'fix' the case of a potential 'from'
703
from_id = tree.path2id(
704
tree.get_canonical_inventory_path(rel_names[0]))
705
if (not osutils.lexists(names_list[0]) and
706
from_id and inv.get_file_kind(from_id) == "directory"):
707
into_existing = False
710
# move into existing directory
711
# All entries reference existing inventory items, so fix them up
712
# for cicp file-systems.
713
rel_names = tree.get_canonical_inventory_paths(rel_names)
714
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
715
self.outf.write("%s => %s\n" % pair)
717
if len(names_list) != 2:
718
raise errors.BzrCommandError('to mv multiple files the'
719
' destination must be a versioned'
722
# for cicp file-systems: the src references an existing inventory
724
src = tree.get_canonical_inventory_path(rel_names[0])
725
# Find the canonical version of the destination: In all cases, the
726
# parent of the target must be in the inventory, so we fetch the
727
# canonical version from there (we do not always *use* the
728
# canonicalized tail portion - we may be attempting to rename the
730
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
731
dest_parent = osutils.dirname(canon_dest)
732
spec_tail = osutils.basename(rel_names[1])
733
# For a CICP file-system, we need to avoid creating 2 inventory
734
# entries that differ only by case. So regardless of the case
735
# we *want* to use (ie, specified by the user or the file-system),
736
# we must always choose to use the case of any existing inventory
737
# items. The only exception to this is when we are attempting a
738
# case-only rename (ie, canonical versions of src and dest are
740
dest_id = tree.path2id(canon_dest)
741
if dest_id is None or tree.path2id(src) == dest_id:
742
# No existing item we care about, so work out what case we
743
# are actually going to use.
745
# If 'after' is specified, the tail must refer to a file on disk.
747
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
749
# pathjoin with an empty tail adds a slash, which breaks
751
dest_parent_fq = tree.basedir
753
dest_tail = osutils.canonical_relpath(
755
osutils.pathjoin(dest_parent_fq, spec_tail))
757
# not 'after', so case as specified is used
758
dest_tail = spec_tail
760
# Use the existing item so 'mv' fails with AlreadyVersioned.
761
dest_tail = os.path.basename(canon_dest)
762
dest = osutils.pathjoin(dest_parent, dest_tail)
763
mutter("attempting to move %s => %s", src, dest)
764
tree.rename_one(src, dest, after=after)
765
self.outf.write("%s => %s\n" % (src, dest))
768
class cmd_pull(Command):
769
"""Turn this branch into a mirror of another branch.
771
This command only works on branches that have not diverged. Branches are
772
considered diverged if the destination branch's most recent commit is one
773
that has not been merged (directly or indirectly) into the parent.
775
If branches have diverged, you can use 'bzr merge' to integrate the changes
776
from one into the other. Once one branch has merged, the other should
777
be able to pull it again.
779
If you want to forget your local changes and just update your branch to
780
match the remote one, use pull --overwrite.
782
If there is no default location set, the first pull will set it. After
783
that, you can omit the location to use the default. To change the
784
default, use --remember. The value will only be saved if the remote
785
location can be accessed.
787
Note: The location can be specified either in the form of a branch,
788
or in the form of a path to a file containing a merge directive generated
792
_see_also = ['push', 'update', 'status-flags']
793
takes_options = ['remember', 'overwrite', 'revision',
794
custom_help('verbose',
795
help='Show logs of pulled revisions.'),
797
help='Branch to pull into, '
798
'rather than the one containing the working directory.',
803
takes_args = ['location?']
804
encoding_type = 'replace'
806
def run(self, location=None, remember=False, overwrite=False,
807
revision=None, verbose=False,
809
# FIXME: too much stuff is in the command class
812
if directory is None:
815
tree_to = WorkingTree.open_containing(directory)[0]
816
branch_to = tree_to.branch
817
except errors.NoWorkingTree:
819
branch_to = Branch.open_containing(directory)[0]
821
possible_transports = []
822
if location is not None:
824
mergeable = bundle.read_mergeable_from_url(location,
825
possible_transports=possible_transports)
826
except errors.NotABundle:
829
stored_loc = branch_to.get_parent()
831
if stored_loc is None:
832
raise errors.BzrCommandError("No pull location known or"
835
display_url = urlutils.unescape_for_display(stored_loc,
838
self.outf.write("Using saved parent location: %s\n" % display_url)
839
location = stored_loc
841
if mergeable is not None:
842
if revision is not None:
843
raise errors.BzrCommandError(
844
'Cannot use -r with merge directives or bundles')
845
mergeable.install_revisions(branch_to.repository)
846
base_revision_id, revision_id, verified = \
847
mergeable.get_merge_request(branch_to.repository)
848
branch_from = branch_to
850
branch_from = Branch.open(location,
851
possible_transports=possible_transports)
853
if branch_to.get_parent() is None or remember:
854
branch_to.set_parent(branch_from.base)
856
if revision is not None:
857
if len(revision) == 1:
858
revision_id = revision[0].as_revision_id(branch_from)
860
raise errors.BzrCommandError(
861
'bzr pull --revision takes one value.')
863
branch_to.lock_write()
865
if tree_to is not None:
866
change_reporter = delta._ChangeReporter(
867
unversioned_filter=tree_to.is_ignored)
868
result = tree_to.pull(branch_from, overwrite, revision_id,
870
possible_transports=possible_transports)
872
result = branch_to.pull(branch_from, overwrite, revision_id)
874
result.report(self.outf)
875
if verbose and result.old_revid != result.new_revid:
876
log.show_branch_change(branch_to, self.outf, result.old_revno,
882
class cmd_push(Command):
883
"""Update a mirror of this branch.
885
The target branch will not have its working tree populated because this
886
is both expensive, and is not supported on remote file systems.
888
Some smart servers or protocols *may* put the working tree in place in
891
This command only works on branches that have not diverged. Branches are
892
considered diverged if the destination branch's most recent commit is one
893
that has not been merged (directly or indirectly) by the source branch.
895
If branches have diverged, you can use 'bzr push --overwrite' to replace
896
the other branch completely, discarding its unmerged changes.
898
If you want to ensure you have the different changes in the other branch,
899
do a merge (see bzr help merge) from the other branch, and commit that.
900
After that you will be able to do a push without '--overwrite'.
902
If there is no default push location set, the first push will set it.
903
After that, you can omit the location to use the default. To change the
904
default, use --remember. The value will only be saved if the remote
905
location can be accessed.
908
_see_also = ['pull', 'update', 'working-trees']
909
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
910
Option('create-prefix',
911
help='Create the path leading up to the branch '
912
'if it does not already exist.'),
914
help='Branch to push from, '
915
'rather than the one containing the working directory.',
919
Option('use-existing-dir',
920
help='By default push will fail if the target'
921
' directory exists, but does not already'
922
' have a control directory. This flag will'
923
' allow push to proceed.'),
925
help='Create a stacked branch that references the public location '
926
'of the parent branch.'),
928
help='Create a stacked branch that refers to another branch '
929
'for the commit history. Only the work not present in the '
930
'referenced branch is included in the branch created.',
933
takes_args = ['location?']
934
encoding_type = 'replace'
936
def run(self, location=None, remember=False, overwrite=False,
937
create_prefix=False, verbose=False, revision=None,
938
use_existing_dir=False, directory=None, stacked_on=None,
940
from bzrlib.push import _show_push_branch
942
# Get the source branch and revision_id
943
if directory is None:
945
br_from = Branch.open_containing(directory)[0]
946
if revision is not None:
947
if len(revision) == 1:
948
revision_id = revision[0].in_history(br_from).rev_id
950
raise errors.BzrCommandError(
951
'bzr push --revision takes one value.')
953
revision_id = br_from.last_revision()
955
# Get the stacked_on branch, if any
956
if stacked_on is not None:
957
stacked_on = urlutils.normalize_url(stacked_on)
959
parent_url = br_from.get_parent()
961
parent = Branch.open(parent_url)
962
stacked_on = parent.get_public_branch()
964
# I considered excluding non-http url's here, thus forcing
965
# 'public' branches only, but that only works for some
966
# users, so it's best to just depend on the user spotting an
967
# error by the feedback given to them. RBC 20080227.
968
stacked_on = parent_url
970
raise errors.BzrCommandError(
971
"Could not determine branch to refer to.")
973
# Get the destination location
975
stored_loc = br_from.get_push_location()
976
if stored_loc is None:
977
raise errors.BzrCommandError(
978
"No push location known or specified.")
980
display_url = urlutils.unescape_for_display(stored_loc,
982
self.outf.write("Using saved push location: %s\n" % display_url)
983
location = stored_loc
985
_show_push_branch(br_from, revision_id, location, self.outf,
986
verbose=verbose, overwrite=overwrite, remember=remember,
987
stacked_on=stacked_on, create_prefix=create_prefix,
988
use_existing_dir=use_existing_dir)
991
class cmd_branch(Command):
992
"""Create a new copy of a branch.
994
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
995
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
996
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
997
is derived from the FROM_LOCATION by stripping a leading scheme or drive
998
identifier, if any. For example, "branch lp:foo-bar" will attempt to
1001
To retrieve the branch as of a particular revision, supply the --revision
1002
parameter, as in "branch foo/bar -r 5".
1005
_see_also = ['checkout']
1006
takes_args = ['from_location', 'to_location?']
1007
takes_options = ['revision', Option('hardlink',
1008
help='Hard-link working tree files where possible.'),
1010
help='Create a stacked branch referring to the source branch. '
1011
'The new branch will depend on the availability of the source '
1012
'branch for all operations.'),
1013
Option('standalone',
1014
help='Do not use a shared repository, even if available.'),
1016
aliases = ['get', 'clone']
1018
def run(self, from_location, to_location=None, revision=None,
1019
hardlink=False, stacked=False, standalone=False):
1020
from bzrlib.tag import _merge_tags_if_possible
1022
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1024
revision = _get_one_revision(revision)
1027
if revision is not None:
1028
revision_id = revision.as_revision_id(br_from)
1030
# FIXME - wt.last_revision, fallback to branch, fall back to
1031
# None or perhaps NULL_REVISION to mean copy nothing
1033
revision_id = br_from.last_revision()
1034
if to_location is None:
1035
to_location = urlutils.derive_to_location(from_location)
1036
to_transport = transport.get_transport(to_location)
1038
to_transport.mkdir('.')
1039
except errors.FileExists:
1040
raise errors.BzrCommandError('Target directory "%s" already'
1041
' exists.' % to_location)
1042
except errors.NoSuchFile:
1043
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1046
# preserve whatever source format we have.
1047
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1048
possible_transports=[to_transport],
1049
accelerator_tree=accelerator_tree,
1050
hardlink=hardlink, stacked=stacked,
1051
force_new_repo=standalone,
1052
source_branch=br_from)
1053
branch = dir.open_branch()
1054
except errors.NoSuchRevision:
1055
to_transport.delete_tree('.')
1056
msg = "The branch %s has no revision %s." % (from_location,
1058
raise errors.BzrCommandError(msg)
1059
_merge_tags_if_possible(br_from, branch)
1060
# If the source branch is stacked, the new branch may
1061
# be stacked whether we asked for that explicitly or not.
1062
# We therefore need a try/except here and not just 'if stacked:'
1064
note('Created new stacked branch referring to %s.' %
1065
branch.get_stacked_on_url())
1066
except (errors.NotStacked, errors.UnstackableBranchFormat,
1067
errors.UnstackableRepositoryFormat), e:
1068
note('Branched %d revision(s).' % branch.revno())
1073
class cmd_checkout(Command):
1074
"""Create a new checkout of an existing branch.
1076
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1077
the branch found in '.'. This is useful if you have removed the working tree
1078
or if it was never created - i.e. if you pushed the branch to its current
1079
location using SFTP.
1081
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1082
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1083
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1084
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
1085
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
1088
To retrieve the branch as of a particular revision, supply the --revision
1089
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
1090
out of date [so you cannot commit] but it may be useful (i.e. to examine old
1094
_see_also = ['checkouts', 'branch']
1095
takes_args = ['branch_location?', 'to_location?']
1096
takes_options = ['revision',
1097
Option('lightweight',
1098
help="Perform a lightweight checkout. Lightweight "
1099
"checkouts depend on access to the branch for "
1100
"every operation. Normal checkouts can perform "
1101
"common operations like diff and status without "
1102
"such access, and also support local commits."
1104
Option('files-from', type=str,
1105
help="Get file contents from this tree."),
1107
help='Hard-link working tree files where possible.'
1112
def run(self, branch_location=None, to_location=None, revision=None,
1113
lightweight=False, files_from=None, hardlink=False):
1114
if branch_location is None:
1115
branch_location = osutils.getcwd()
1116
to_location = branch_location
1117
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1119
revision = _get_one_revision(revision)
1120
if files_from is not None:
1121
accelerator_tree = WorkingTree.open(files_from)
1122
if revision is not None:
1123
revision_id = revision.as_revision_id(source)
1126
if to_location is None:
1127
to_location = urlutils.derive_to_location(branch_location)
1128
# if the source and to_location are the same,
1129
# and there is no working tree,
1130
# then reconstitute a branch
1131
if (osutils.abspath(to_location) ==
1132
osutils.abspath(branch_location)):
1134
source.bzrdir.open_workingtree()
1135
except errors.NoWorkingTree:
1136
source.bzrdir.create_workingtree(revision_id)
1138
source.create_checkout(to_location, revision_id, lightweight,
1139
accelerator_tree, hardlink)
1142
class cmd_renames(Command):
1143
"""Show list of renamed files.
1145
# TODO: Option to show renames between two historical versions.
1147
# TODO: Only show renames under dir, rather than in the whole branch.
1148
_see_also = ['status']
1149
takes_args = ['dir?']
1152
def run(self, dir=u'.'):
1153
tree = WorkingTree.open_containing(dir)[0]
1156
new_inv = tree.inventory
1157
old_tree = tree.basis_tree()
1158
old_tree.lock_read()
1160
old_inv = old_tree.inventory
1162
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1163
for f, paths, c, v, p, n, k, e in iterator:
1164
if paths[0] == paths[1]:
1168
renames.append(paths)
1170
for old_name, new_name in renames:
1171
self.outf.write("%s => %s\n" % (old_name, new_name))
1178
class cmd_update(Command):
1179
"""Update a tree to have the latest code committed to its branch.
1181
This will perform a merge into the working tree, and may generate
1182
conflicts. If you have any local changes, you will still
1183
need to commit them after the update for the update to be complete.
1185
If you want to discard your local changes, you can just do a
1186
'bzr revert' instead of 'bzr commit' after the update.
1189
_see_also = ['pull', 'working-trees', 'status-flags']
1190
takes_args = ['dir?']
1193
def run(self, dir='.'):
1194
tree = WorkingTree.open_containing(dir)[0]
1195
possible_transports = []
1196
master = tree.branch.get_master_branch(
1197
possible_transports=possible_transports)
1198
if master is not None:
1201
tree.lock_tree_write()
1203
existing_pending_merges = tree.get_parent_ids()[1:]
1204
last_rev = _mod_revision.ensure_null(tree.last_revision())
1205
if last_rev == _mod_revision.ensure_null(
1206
tree.branch.last_revision()):
1207
# may be up to date, check master too.
1208
if master is None or last_rev == _mod_revision.ensure_null(
1209
master.last_revision()):
1210
revno = tree.branch.revision_id_to_revno(last_rev)
1211
note("Tree is up to date at revision %d." % (revno,))
1213
conflicts = tree.update(
1214
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1215
possible_transports=possible_transports)
1216
revno = tree.branch.revision_id_to_revno(
1217
_mod_revision.ensure_null(tree.last_revision()))
1218
note('Updated to revision %d.' % (revno,))
1219
if tree.get_parent_ids()[1:] != existing_pending_merges:
1220
note('Your local commits will now show as pending merges with '
1221
"'bzr status', and can be committed with 'bzr commit'.")
1230
class cmd_info(Command):
1231
"""Show information about a working tree, branch or repository.
1233
This command will show all known locations and formats associated to the
1234
tree, branch or repository. Statistical information is included with
1237
Branches and working trees will also report any missing revisions.
1239
_see_also = ['revno', 'working-trees', 'repositories']
1240
takes_args = ['location?']
1241
takes_options = ['verbose']
1242
encoding_type = 'replace'
1245
def run(self, location=None, verbose=False):
1250
from bzrlib.info import show_bzrdir_info
1251
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1252
verbose=noise_level, outfile=self.outf)
1255
class cmd_remove(Command):
1256
"""Remove files or directories.
1258
This makes bzr stop tracking changes to the specified files. bzr will delete
1259
them if they can easily be recovered using revert. If no options or
1260
parameters are given bzr will scan for files that are being tracked by bzr
1261
but missing in your tree and stop tracking them for you.
1263
takes_args = ['file*']
1264
takes_options = ['verbose',
1265
Option('new', help='Only remove files that have never been committed.'),
1266
RegistryOption.from_kwargs('file-deletion-strategy',
1267
'The file deletion mode to be used.',
1268
title='Deletion Strategy', value_switches=True, enum_switch=False,
1269
safe='Only delete files if they can be'
1270
' safely recovered (default).',
1271
keep="Don't delete any files.",
1272
force='Delete all the specified files, even if they can not be '
1273
'recovered and even if they are non-empty directories.')]
1274
aliases = ['rm', 'del']
1275
encoding_type = 'replace'
1277
def run(self, file_list, verbose=False, new=False,
1278
file_deletion_strategy='safe'):
1279
tree, file_list = tree_files(file_list)
1281
if file_list is not None:
1282
file_list = [f for f in file_list]
1286
# Heuristics should probably all move into tree.remove_smart or
1289
added = tree.changes_from(tree.basis_tree(),
1290
specific_files=file_list).added
1291
file_list = sorted([f[0] for f in added], reverse=True)
1292
if len(file_list) == 0:
1293
raise errors.BzrCommandError('No matching files.')
1294
elif file_list is None:
1295
# missing files show up in iter_changes(basis) as
1296
# versioned-with-no-kind.
1298
for change in tree.iter_changes(tree.basis_tree()):
1299
# Find paths in the working tree that have no kind:
1300
if change[1][1] is not None and change[6][1] is None:
1301
missing.append(change[1][1])
1302
file_list = sorted(missing, reverse=True)
1303
file_deletion_strategy = 'keep'
1304
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1305
keep_files=file_deletion_strategy=='keep',
1306
force=file_deletion_strategy=='force')
1311
class cmd_file_id(Command):
1312
"""Print file_id of a particular file or directory.
1314
The file_id is assigned when the file is first added and remains the
1315
same through all revisions where the file exists, even when it is
1320
_see_also = ['inventory', 'ls']
1321
takes_args = ['filename']
1324
def run(self, filename):
1325
tree, relpath = WorkingTree.open_containing(filename)
1326
i = tree.path2id(relpath)
1328
raise errors.NotVersionedError(filename)
1330
self.outf.write(i + '\n')
1333
class cmd_file_path(Command):
1334
"""Print path of file_ids to a file or directory.
1336
This prints one line for each directory down to the target,
1337
starting at the branch root.
1341
takes_args = ['filename']
1344
def run(self, filename):
1345
tree, relpath = WorkingTree.open_containing(filename)
1346
fid = tree.path2id(relpath)
1348
raise errors.NotVersionedError(filename)
1349
segments = osutils.splitpath(relpath)
1350
for pos in range(1, len(segments) + 1):
1351
path = osutils.joinpath(segments[:pos])
1352
self.outf.write("%s\n" % tree.path2id(path))
1355
class cmd_reconcile(Command):
1356
"""Reconcile bzr metadata in a branch.
1358
This can correct data mismatches that may have been caused by
1359
previous ghost operations or bzr upgrades. You should only
1360
need to run this command if 'bzr check' or a bzr developer
1361
advises you to run it.
1363
If a second branch is provided, cross-branch reconciliation is
1364
also attempted, which will check that data like the tree root
1365
id which was not present in very early bzr versions is represented
1366
correctly in both branches.
1368
At the same time it is run it may recompress data resulting in
1369
a potential saving in disk space or performance gain.
1371
The branch *MUST* be on a listable system such as local disk or sftp.
1374
_see_also = ['check']
1375
takes_args = ['branch?']
1377
def run(self, branch="."):
1378
from bzrlib.reconcile import reconcile
1379
dir = bzrdir.BzrDir.open(branch)
1383
class cmd_revision_history(Command):
1384
"""Display the list of revision ids on a branch."""
1387
takes_args = ['location?']
1392
def run(self, location="."):
1393
branch = Branch.open_containing(location)[0]
1394
for revid in branch.revision_history():
1395
self.outf.write(revid)
1396
self.outf.write('\n')
1399
class cmd_ancestry(Command):
1400
"""List all revisions merged into this branch."""
1402
_see_also = ['log', 'revision-history']
1403
takes_args = ['location?']
1408
def run(self, location="."):
1410
wt = WorkingTree.open_containing(location)[0]
1411
except errors.NoWorkingTree:
1412
b = Branch.open(location)
1413
last_revision = b.last_revision()
1416
last_revision = wt.last_revision()
1418
revision_ids = b.repository.get_ancestry(last_revision)
1420
for revision_id in revision_ids:
1421
self.outf.write(revision_id + '\n')
1424
class cmd_init(Command):
1425
"""Make a directory into a versioned branch.
1427
Use this to create an empty branch, or before importing an
1430
If there is a repository in a parent directory of the location, then
1431
the history of the branch will be stored in the repository. Otherwise
1432
init creates a standalone branch which carries its own history
1433
in the .bzr directory.
1435
If there is already a branch at the location but it has no working tree,
1436
the tree can be populated with 'bzr checkout'.
1438
Recipe for importing a tree of files::
1444
bzr commit -m "imported project"
1447
_see_also = ['init-repository', 'branch', 'checkout']
1448
takes_args = ['location?']
1450
Option('create-prefix',
1451
help='Create the path leading up to the branch '
1452
'if it does not already exist.'),
1453
RegistryOption('format',
1454
help='Specify a format for this branch. '
1455
'See "help formats".',
1456
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1457
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1458
value_switches=True,
1459
title="Branch Format",
1461
Option('append-revisions-only',
1462
help='Never change revnos or the existing log.'
1463
' Append revisions to it only.')
1465
def run(self, location=None, format=None, append_revisions_only=False,
1466
create_prefix=False):
1468
format = bzrdir.format_registry.make_bzrdir('default')
1469
if location is None:
1472
to_transport = transport.get_transport(location)
1474
# The path has to exist to initialize a
1475
# branch inside of it.
1476
# Just using os.mkdir, since I don't
1477
# believe that we want to create a bunch of
1478
# locations if the user supplies an extended path
1480
to_transport.ensure_base()
1481
except errors.NoSuchFile:
1482
if not create_prefix:
1483
raise errors.BzrCommandError("Parent directory of %s"
1485
"\nYou may supply --create-prefix to create all"
1486
" leading parent directories."
1488
_create_prefix(to_transport)
1491
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1492
except errors.NotBranchError:
1493
# really a NotBzrDir error...
1494
create_branch = bzrdir.BzrDir.create_branch_convenience
1495
branch = create_branch(to_transport.base, format=format,
1496
possible_transports=[to_transport])
1497
a_bzrdir = branch.bzrdir
1499
from bzrlib.transport.local import LocalTransport
1500
if a_bzrdir.has_branch():
1501
if (isinstance(to_transport, LocalTransport)
1502
and not a_bzrdir.has_workingtree()):
1503
raise errors.BranchExistsWithoutWorkingTree(location)
1504
raise errors.AlreadyBranchError(location)
1505
branch = a_bzrdir.create_branch()
1506
a_bzrdir.create_workingtree()
1507
if append_revisions_only:
1509
branch.set_append_revisions_only(True)
1510
except errors.UpgradeRequired:
1511
raise errors.BzrCommandError('This branch format cannot be set'
1512
' to append-revisions-only. Try --experimental-branch6')
1514
from bzrlib.info import describe_layout, describe_format
1516
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1517
except (errors.NoWorkingTree, errors.NotLocalUrl):
1519
repository = branch.repository
1520
layout = describe_layout(repository, branch, tree).lower()
1521
format = describe_format(a_bzrdir, repository, branch, tree)
1522
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1523
if repository.is_shared():
1524
#XXX: maybe this can be refactored into transport.path_or_url()
1525
url = repository.bzrdir.root_transport.external_url()
1527
url = urlutils.local_path_from_url(url)
1528
except errors.InvalidURL:
1530
self.outf.write("Using shared repository: %s\n" % url)
1533
class cmd_init_repository(Command):
1534
"""Create a shared repository to hold branches.
1536
New branches created under the repository directory will store their
1537
revisions in the repository, not in the branch directory.
1539
If the --no-trees option is used then the branches in the repository
1540
will not have working trees by default.
1543
Create a shared repositories holding just branches::
1545
bzr init-repo --no-trees repo
1548
Make a lightweight checkout elsewhere::
1550
bzr checkout --lightweight repo/trunk trunk-checkout
1555
_see_also = ['init', 'branch', 'checkout', 'repositories']
1556
takes_args = ["location"]
1557
takes_options = [RegistryOption('format',
1558
help='Specify a format for this repository. See'
1559
' "bzr help formats" for details.',
1560
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1561
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1562
value_switches=True, title='Repository format'),
1564
help='Branches in the repository will default to'
1565
' not having a working tree.'),
1567
aliases = ["init-repo"]
1569
def run(self, location, format=None, no_trees=False):
1571
format = bzrdir.format_registry.make_bzrdir('default')
1573
if location is None:
1576
to_transport = transport.get_transport(location)
1577
to_transport.ensure_base()
1579
newdir = format.initialize_on_transport(to_transport)
1580
repo = newdir.create_repository(shared=True)
1581
repo.set_make_working_trees(not no_trees)
1583
from bzrlib.info import show_bzrdir_info
1584
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1587
class cmd_diff(Command):
1588
"""Show differences in the working tree, between revisions or branches.
1590
If no arguments are given, all changes for the current tree are listed.
1591
If files are given, only the changes in those files are listed.
1592
Remote and multiple branches can be compared by using the --old and
1593
--new options. If not provided, the default for both is derived from
1594
the first argument, if any, or the current tree if no arguments are
1597
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1598
produces patches suitable for "patch -p1".
1602
2 - unrepresentable changes
1607
Shows the difference in the working tree versus the last commit::
1611
Difference between the working tree and revision 1::
1615
Difference between revision 2 and revision 1::
1619
Difference between revision 2 and revision 1 for branch xxx::
1623
Show just the differences for file NEWS::
1627
Show the differences in working tree xxx for file NEWS::
1631
Show the differences from branch xxx to this working tree:
1635
Show the differences between two branches for file NEWS::
1637
bzr diff --old xxx --new yyy NEWS
1639
Same as 'bzr diff' but prefix paths with old/ and new/::
1641
bzr diff --prefix old/:new/
1643
_see_also = ['status']
1644
takes_args = ['file*']
1646
Option('diff-options', type=str,
1647
help='Pass these options to the external diff program.'),
1648
Option('prefix', type=str,
1650
help='Set prefixes added to old and new filenames, as '
1651
'two values separated by a colon. (eg "old/:new/").'),
1653
help='Branch/tree to compare from.',
1657
help='Branch/tree to compare to.',
1663
help='Use this command to compare files.',
1667
aliases = ['di', 'dif']
1668
encoding_type = 'exact'
1671
def run(self, revision=None, file_list=None, diff_options=None,
1672
prefix=None, old=None, new=None, using=None):
1673
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1675
if (prefix is None) or (prefix == '0'):
1683
old_label, new_label = prefix.split(":")
1685
raise errors.BzrCommandError(
1686
'--prefix expects two values separated by a colon'
1687
' (eg "old/:new/")')
1689
if revision and len(revision) > 2:
1690
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1691
' one or two revision specifiers')
1693
old_tree, new_tree, specific_files, extra_trees = \
1694
_get_trees_to_diff(file_list, revision, old, new)
1695
return show_diff_trees(old_tree, new_tree, sys.stdout,
1696
specific_files=specific_files,
1697
external_diff_options=diff_options,
1698
old_label=old_label, new_label=new_label,
1699
extra_trees=extra_trees, using=using)
1702
class cmd_deleted(Command):
1703
"""List files deleted in the working tree.
1705
# TODO: Show files deleted since a previous revision, or
1706
# between two revisions.
1707
# TODO: Much more efficient way to do this: read in new
1708
# directories with readdir, rather than stating each one. Same
1709
# level of effort but possibly much less IO. (Or possibly not,
1710
# if the directories are very large...)
1711
_see_also = ['status', 'ls']
1712
takes_options = ['show-ids']
1715
def run(self, show_ids=False):
1716
tree = WorkingTree.open_containing(u'.')[0]
1719
old = tree.basis_tree()
1722
for path, ie in old.inventory.iter_entries():
1723
if not tree.has_id(ie.file_id):
1724
self.outf.write(path)
1726
self.outf.write(' ')
1727
self.outf.write(ie.file_id)
1728
self.outf.write('\n')
1735
class cmd_modified(Command):
1736
"""List files modified in working tree.
1740
_see_also = ['status', 'ls']
1743
help='Write an ascii NUL (\\0) separator '
1744
'between files rather than a newline.')
1748
def run(self, null=False):
1749
tree = WorkingTree.open_containing(u'.')[0]
1750
td = tree.changes_from(tree.basis_tree())
1751
for path, id, kind, text_modified, meta_modified in td.modified:
1753
self.outf.write(path + '\0')
1755
self.outf.write(osutils.quotefn(path) + '\n')
1758
class cmd_added(Command):
1759
"""List files added in working tree.
1763
_see_also = ['status', 'ls']
1766
help='Write an ascii NUL (\\0) separator '
1767
'between files rather than a newline.')
1771
def run(self, null=False):
1772
wt = WorkingTree.open_containing(u'.')[0]
1775
basis = wt.basis_tree()
1778
basis_inv = basis.inventory
1781
if file_id in basis_inv:
1783
if inv.is_root(file_id) and len(basis_inv) == 0:
1785
path = inv.id2path(file_id)
1786
if not os.access(osutils.abspath(path), os.F_OK):
1789
self.outf.write(path + '\0')
1791
self.outf.write(osutils.quotefn(path) + '\n')
1798
class cmd_root(Command):
1799
"""Show the tree root directory.
1801
The root is the nearest enclosing directory with a .bzr control
1804
takes_args = ['filename?']
1806
def run(self, filename=None):
1807
"""Print the branch root."""
1808
tree = WorkingTree.open_containing(filename)[0]
1809
self.outf.write(tree.basedir + '\n')
1812
def _parse_limit(limitstring):
1814
return int(limitstring)
1816
msg = "The limit argument must be an integer."
1817
raise errors.BzrCommandError(msg)
1820
def _parse_levels(s):
1824
msg = "The levels argument must be an integer."
1825
raise errors.BzrCommandError(msg)
1828
class cmd_log(Command):
1829
"""Show log of a branch, file, or directory.
1831
By default show the log of the branch containing the working directory.
1833
To request a range of logs, you can use the command -r begin..end
1834
-r revision requests a specific revision, -r ..end or -r begin.. are
1838
Log the current branch::
1846
Log the last 10 revisions of a branch::
1848
bzr log -r -10.. http://server/branch
1851
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1853
takes_args = ['location?']
1856
help='Show from oldest to newest.'),
1858
custom_help('verbose',
1859
help='Show files changed in each revision.'),
1863
type=bzrlib.option._parse_revision_str,
1865
help='Show just the specified revision.'
1866
' See also "help revisionspec".'),
1870
help='Number of levels to display - 0 for all, 1 for flat.',
1872
type=_parse_levels),
1875
help='Show revisions whose message matches this '
1876
'regular expression.',
1880
help='Limit the output to the first N revisions.',
1885
help='Show changes made in each revision as a patch.'),
1887
encoding_type = 'replace'
1890
def run(self, location=None, timezone='original',
1901
from bzrlib.log import show_log, _get_fileid_to_log
1902
direction = (forward and 'forward') or 'reverse'
1904
if change is not None:
1906
raise errors.RangeInChangeOption()
1907
if revision is not None:
1908
raise errors.BzrCommandError(
1909
'--revision and --change are mutually exclusive')
1916
# find the file id to log:
1918
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1921
file_id = _get_fileid_to_log(revision, tree, b, fp)
1923
raise errors.BzrCommandError(
1924
"Path unknown at end or start of revision range: %s" %
1928
# FIXME ? log the current subdir only RBC 20060203
1929
if revision is not None \
1930
and len(revision) > 0 and revision[0].get_branch():
1931
location = revision[0].get_branch()
1934
dir, relpath = bzrdir.BzrDir.open_containing(location)
1935
b = dir.open_branch()
1939
rev1, rev2 = _get_revision_range(revision, b, self.name())
1940
if log_format is None:
1941
log_format = log.log_formatter_registry.get_default(b)
1943
lf = log_format(show_ids=show_ids, to_file=self.outf,
1944
show_timezone=timezone,
1945
delta_format=get_verbosity_level(),
1952
direction=direction,
1953
start_revision=rev1,
1957
show_diff=show_diff)
1962
def _get_revision_range(revisionspec_list, branch, command_name):
1963
"""Take the input of a revision option and turn it into a revision range.
1965
It returns RevisionInfo objects which can be used to obtain the rev_id's
1966
of the desired revisons. It does some user input validations.
1968
if revisionspec_list is None:
1971
elif len(revisionspec_list) == 1:
1972
rev1 = rev2 = revisionspec_list[0].in_history(branch)
1973
elif len(revisionspec_list) == 2:
1974
start_spec = revisionspec_list[0]
1975
end_spec = revisionspec_list[1]
1976
if end_spec.get_branch() != start_spec.get_branch():
1977
# b is taken from revision[0].get_branch(), and
1978
# show_log will use its revision_history. Having
1979
# different branches will lead to weird behaviors.
1980
raise errors.BzrCommandError(
1981
"bzr %s doesn't accept two revisions in different"
1982
" branches." % command_name)
1983
rev1 = start_spec.in_history(branch)
1984
# Avoid loading all of history when we know a missing
1985
# end of range means the last revision ...
1986
if end_spec.spec is None:
1987
last_revno, last_revision_id = branch.last_revision_info()
1988
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
1990
rev2 = end_spec.in_history(branch)
1992
raise errors.BzrCommandError(
1993
'bzr %s --revision takes one or two values.' % command_name)
1997
def _revision_range_to_revid_range(revision_range):
2000
if revision_range[0] is not None:
2001
rev_id1 = revision_range[0].rev_id
2002
if revision_range[1] is not None:
2003
rev_id2 = revision_range[1].rev_id
2004
return rev_id1, rev_id2
2006
def get_log_format(long=False, short=False, line=False, default='long'):
2007
log_format = default
2011
log_format = 'short'
2017
class cmd_touching_revisions(Command):
2018
"""Return revision-ids which affected a particular file.
2020
A more user-friendly interface is "bzr log FILE".
2024
takes_args = ["filename"]
2027
def run(self, filename):
2028
tree, relpath = WorkingTree.open_containing(filename)
2030
file_id = tree.path2id(relpath)
2031
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2032
self.outf.write("%6d %s\n" % (revno, what))
2035
class cmd_ls(Command):
2036
"""List files in a tree.
2039
_see_also = ['status', 'cat']
2040
takes_args = ['path?']
2041
# TODO: Take a revision or remote path and list that tree instead.
2045
Option('non-recursive',
2046
help='Don\'t recurse into subdirectories.'),
2048
help='Print paths relative to the root of the branch.'),
2049
Option('unknown', help='Print unknown files.'),
2050
Option('versioned', help='Print versioned files.',
2052
Option('ignored', help='Print ignored files.'),
2054
help='Write an ascii NUL (\\0) separator '
2055
'between files rather than a newline.'),
2057
help='List entries of a particular kind: file, directory, symlink.',
2062
def run(self, revision=None, verbose=False,
2063
non_recursive=False, from_root=False,
2064
unknown=False, versioned=False, ignored=False,
2065
null=False, kind=None, show_ids=False, path=None):
2067
if kind and kind not in ('file', 'directory', 'symlink'):
2068
raise errors.BzrCommandError('invalid kind specified')
2070
if verbose and null:
2071
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2072
all = not (unknown or versioned or ignored)
2074
selection = {'I':ignored, '?':unknown, 'V':versioned}
2081
raise errors.BzrCommandError('cannot specify both --from-root'
2085
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2091
if revision is not None or tree is None:
2092
tree = _get_one_revision_tree('ls', revision, branch=branch)
2096
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2097
if fp.startswith(relpath):
2098
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2099
if non_recursive and '/' in fp:
2101
if not all and not selection[fc]:
2103
if kind is not None and fkind != kind:
2105
kindch = entry.kind_character()
2106
outstring = fp + kindch
2108
outstring = '%-8s %s' % (fc, outstring)
2109
if show_ids and fid is not None:
2110
outstring = "%-50s %s" % (outstring, fid)
2111
self.outf.write(outstring + '\n')
2113
self.outf.write(fp + '\0')
2116
self.outf.write(fid)
2117
self.outf.write('\0')
2125
self.outf.write('%-50s %s\n' % (outstring, my_id))
2127
self.outf.write(outstring + '\n')
2132
class cmd_unknowns(Command):
2133
"""List unknown files.
2141
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2142
self.outf.write(osutils.quotefn(f) + '\n')
2145
class cmd_ignore(Command):
2146
"""Ignore specified files or patterns.
2148
See ``bzr help patterns`` for details on the syntax of patterns.
2150
To remove patterns from the ignore list, edit the .bzrignore file.
2151
After adding, editing or deleting that file either indirectly by
2152
using this command or directly by using an editor, be sure to commit
2155
Note: ignore patterns containing shell wildcards must be quoted from
2159
Ignore the top level Makefile::
2161
bzr ignore ./Makefile
2163
Ignore class files in all directories::
2165
bzr ignore "*.class"
2167
Ignore .o files under the lib directory::
2169
bzr ignore "lib/**/*.o"
2171
Ignore .o files under the lib directory::
2173
bzr ignore "RE:lib/.*\.o"
2175
Ignore everything but the "debian" toplevel directory::
2177
bzr ignore "RE:(?!debian/).*"
2180
_see_also = ['status', 'ignored', 'patterns']
2181
takes_args = ['name_pattern*']
2183
Option('old-default-rules',
2184
help='Write out the ignore rules bzr < 0.9 always used.')
2187
def run(self, name_pattern_list=None, old_default_rules=None):
2188
from bzrlib import ignores
2189
if old_default_rules is not None:
2190
# dump the rules and exit
2191
for pattern in ignores.OLD_DEFAULTS:
2194
if not name_pattern_list:
2195
raise errors.BzrCommandError("ignore requires at least one "
2196
"NAME_PATTERN or --old-default-rules")
2197
name_pattern_list = [globbing.normalize_pattern(p)
2198
for p in name_pattern_list]
2199
for name_pattern in name_pattern_list:
2200
if (name_pattern[0] == '/' or
2201
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2202
raise errors.BzrCommandError(
2203
"NAME_PATTERN should not be an absolute path")
2204
tree, relpath = WorkingTree.open_containing(u'.')
2205
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2206
ignored = globbing.Globster(name_pattern_list)
2209
for entry in tree.list_files():
2213
if ignored.match(filename):
2214
matches.append(filename.encode('utf-8'))
2216
if len(matches) > 0:
2217
print "Warning: the following files are version controlled and" \
2218
" match your ignore pattern:\n%s" % ("\n".join(matches),)
2221
class cmd_ignored(Command):
2222
"""List ignored files and the patterns that matched them.
2224
List all the ignored files and the ignore pattern that caused the file to
2227
Alternatively, to list just the files::
2232
encoding_type = 'replace'
2233
_see_also = ['ignore', 'ls']
2237
tree = WorkingTree.open_containing(u'.')[0]
2240
for path, file_class, kind, file_id, entry in tree.list_files():
2241
if file_class != 'I':
2243
## XXX: Slightly inefficient since this was already calculated
2244
pat = tree.is_ignored(path)
2245
self.outf.write('%-50s %s\n' % (path, pat))
2250
class cmd_lookup_revision(Command):
2251
"""Lookup the revision-id from a revision-number
2254
bzr lookup-revision 33
2257
takes_args = ['revno']
2260
def run(self, revno):
2264
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2266
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2269
class cmd_export(Command):
2270
"""Export current or past revision to a destination directory or archive.
2272
If no revision is specified this exports the last committed revision.
2274
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
2275
given, try to find the format with the extension. If no extension
2276
is found exports to a directory (equivalent to --format=dir).
2278
If root is supplied, it will be used as the root directory inside
2279
container formats (tar, zip, etc). If it is not supplied it will default
2280
to the exported filename. The root option has no effect for 'dir' format.
2282
If branch is omitted then the branch containing the current working
2283
directory will be used.
2285
Note: Export of tree with non-ASCII filenames to zip is not supported.
2287
================= =========================
2288
Supported formats Autodetected by extension
2289
================= =========================
2292
tbz2 .tar.bz2, .tbz2
2295
================= =========================
2297
takes_args = ['dest', 'branch_or_subdir?']
2300
help="Type of file to export to.",
2305
help="Name of the root directory inside the exported file."),
2307
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2309
from bzrlib.export import export
2311
if branch_or_subdir is None:
2312
tree = WorkingTree.open_containing(u'.')[0]
2316
b, subdir = Branch.open_containing(branch_or_subdir)
2319
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2321
export(rev_tree, dest, format, root, subdir)
2322
except errors.NoSuchExportFormat, e:
2323
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2326
class cmd_cat(Command):
2327
"""Write the contents of a file as of a given revision to standard output.
2329
If no revision is nominated, the last revision is used.
2331
Note: Take care to redirect standard output when using this command on a
2337
Option('name-from-revision', help='The path name in the old tree.'),
2340
takes_args = ['filename']
2341
encoding_type = 'exact'
2344
def run(self, filename, revision=None, name_from_revision=False):
2345
if revision is not None and len(revision) != 1:
2346
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2347
" one revision specifier")
2348
tree, branch, relpath = \
2349
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2352
return self._run(tree, branch, relpath, filename, revision,
2357
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2359
tree = b.basis_tree()
2360
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2362
cur_file_id = tree.path2id(relpath)
2363
old_file_id = rev_tree.path2id(relpath)
2365
if name_from_revision:
2366
if old_file_id is None:
2367
raise errors.BzrCommandError(
2368
"%r is not present in revision %s" % (
2369
filename, rev_tree.get_revision_id()))
2371
content = rev_tree.get_file_text(old_file_id)
2372
elif cur_file_id is not None:
2373
content = rev_tree.get_file_text(cur_file_id)
2374
elif old_file_id is not None:
2375
content = rev_tree.get_file_text(old_file_id)
2377
raise errors.BzrCommandError(
2378
"%r is not present in revision %s" % (
2379
filename, rev_tree.get_revision_id()))
2380
self.outf.write(content)
2383
class cmd_local_time_offset(Command):
2384
"""Show the offset in seconds from GMT to local time."""
2388
print osutils.local_time_offset()
2392
class cmd_commit(Command):
2393
"""Commit changes into a new revision.
2395
If no arguments are given, the entire tree is committed.
2397
If selected files are specified, only changes to those files are
2398
committed. If a directory is specified then the directory and everything
2399
within it is committed.
2401
When excludes are given, they take precedence over selected files.
2402
For example, too commit only changes within foo, but not changes within
2405
bzr commit foo -x foo/bar
2407
If author of the change is not the same person as the committer, you can
2408
specify the author's name using the --author option. The name should be
2409
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2411
A selected-file commit may fail in some cases where the committed
2412
tree would be invalid. Consider::
2417
bzr commit foo -m "committing foo"
2418
bzr mv foo/bar foo/baz
2421
bzr commit foo/bar -m "committing bar but not baz"
2423
In the example above, the last commit will fail by design. This gives
2424
the user the opportunity to decide whether they want to commit the
2425
rename at the same time, separately first, or not at all. (As a general
2426
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2428
Note: A selected-file commit after a merge is not yet supported.
2430
# TODO: Run hooks on tree to-be-committed, and after commit.
2432
# TODO: Strict commit that fails if there are deleted files.
2433
# (what does "deleted files" mean ??)
2435
# TODO: Give better message for -s, --summary, used by tla people
2437
# XXX: verbose currently does nothing
2439
_see_also = ['bugs', 'uncommit']
2440
takes_args = ['selected*']
2442
ListOption('exclude', type=str, short_name='x',
2443
help="Do not consider changes made to a given path."),
2444
Option('message', type=unicode,
2446
help="Description of the new revision."),
2449
help='Commit even if nothing has changed.'),
2450
Option('file', type=str,
2453
help='Take commit message from this file.'),
2455
help="Refuse to commit if there are unknown "
2456
"files in the working tree."),
2457
ListOption('fixes', type=str,
2458
help="Mark a bug as being fixed by this revision."),
2459
Option('author', type=unicode,
2460
help="Set the author's name, if it's different "
2461
"from the committer."),
2463
help="Perform a local commit in a bound "
2464
"branch. Local commits are not pushed to "
2465
"the master branch until a normal commit "
2469
help='When no message is supplied, show the diff along'
2470
' with the status summary in the message editor.'),
2472
aliases = ['ci', 'checkin']
2474
def _get_bug_fix_properties(self, fixes, branch):
2476
# Configure the properties for bug fixing attributes.
2477
for fixed_bug in fixes:
2478
tokens = fixed_bug.split(':')
2479
if len(tokens) != 2:
2480
raise errors.BzrCommandError(
2481
"Invalid bug %s. Must be in the form of 'tag:id'. "
2482
"Commit refused." % fixed_bug)
2483
tag, bug_id = tokens
2485
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2486
except errors.UnknownBugTrackerAbbreviation:
2487
raise errors.BzrCommandError(
2488
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2489
except errors.MalformedBugIdentifier:
2490
raise errors.BzrCommandError(
2491
"Invalid bug identifier for %s. Commit refused."
2493
properties.append('%s fixed' % bug_url)
2494
return '\n'.join(properties)
2496
def run(self, message=None, file=None, verbose=False, selected_list=None,
2497
unchanged=False, strict=False, local=False, fixes=None,
2498
author=None, show_diff=False, exclude=None):
2499
from bzrlib.errors import (
2504
from bzrlib.msgeditor import (
2505
edit_commit_message_encoded,
2506
generate_commit_message_template,
2507
make_commit_message_template_encoded
2510
# TODO: Need a blackbox test for invoking the external editor; may be
2511
# slightly problematic to run this cross-platform.
2513
# TODO: do more checks that the commit will succeed before
2514
# spending the user's valuable time typing a commit message.
2518
tree, selected_list = tree_files(selected_list)
2519
if selected_list == ['']:
2520
# workaround - commit of root of tree should be exactly the same
2521
# as just default commit in that tree, and succeed even though
2522
# selected-file merge commit is not done yet
2527
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2529
properties['bugs'] = bug_property
2531
if local and not tree.branch.get_bound_location():
2532
raise errors.LocalRequiresBoundBranch()
2534
def get_message(commit_obj):
2535
"""Callback to get commit message"""
2536
my_message = message
2537
if my_message is None and not file:
2538
t = make_commit_message_template_encoded(tree,
2539
selected_list, diff=show_diff,
2540
output_encoding=osutils.get_user_encoding())
2541
start_message = generate_commit_message_template(commit_obj)
2542
my_message = edit_commit_message_encoded(t,
2543
start_message=start_message)
2544
if my_message is None:
2545
raise errors.BzrCommandError("please specify a commit"
2546
" message with either --message or --file")
2547
elif my_message and file:
2548
raise errors.BzrCommandError(
2549
"please specify either --message or --file")
2551
my_message = codecs.open(file, 'rt',
2552
osutils.get_user_encoding()).read()
2553
if my_message == "":
2554
raise errors.BzrCommandError("empty commit message specified")
2558
tree.commit(message_callback=get_message,
2559
specific_files=selected_list,
2560
allow_pointless=unchanged, strict=strict, local=local,
2561
reporter=None, verbose=verbose, revprops=properties,
2563
exclude=safe_relpath_files(tree, exclude))
2564
except PointlessCommit:
2565
# FIXME: This should really happen before the file is read in;
2566
# perhaps prepare the commit; get the message; then actually commit
2567
raise errors.BzrCommandError("no changes to commit."
2568
" use --unchanged to commit anyhow")
2569
except ConflictsInTree:
2570
raise errors.BzrCommandError('Conflicts detected in working '
2571
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2573
except StrictCommitFailed:
2574
raise errors.BzrCommandError("Commit refused because there are"
2575
" unknown files in the working tree.")
2576
except errors.BoundBranchOutOfDate, e:
2577
raise errors.BzrCommandError(str(e) + "\n"
2578
'To commit to master branch, run update and then commit.\n'
2579
'You can also pass --local to commit to continue working '
2583
class cmd_check(Command):
2584
"""Validate working tree structure, branch consistency and repository history.
2586
This command checks various invariants about branch and repository storage
2587
to detect data corruption or bzr bugs.
2589
The working tree and branch checks will only give output if a problem is
2590
detected. The output fields of the repository check are:
2592
revisions: This is just the number of revisions checked. It doesn't
2594
versionedfiles: This is just the number of versionedfiles checked. It
2595
doesn't indicate a problem.
2596
unreferenced ancestors: Texts that are ancestors of other texts, but
2597
are not properly referenced by the revision ancestry. This is a
2598
subtle problem that Bazaar can work around.
2599
unique file texts: This is the total number of unique file contents
2600
seen in the checked revisions. It does not indicate a problem.
2601
repeated file texts: This is the total number of repeated texts seen
2602
in the checked revisions. Texts can be repeated when their file
2603
entries are modified, but the file contents are not. It does not
2606
If no restrictions are specified, all Bazaar data that is found at the given
2607
location will be checked.
2611
Check the tree and branch at 'foo'::
2613
bzr check --tree --branch foo
2615
Check only the repository at 'bar'::
2617
bzr check --repo bar
2619
Check everything at 'baz'::
2624
_see_also = ['reconcile']
2625
takes_args = ['path?']
2626
takes_options = ['verbose',
2627
Option('branch', help="Check the branch related to the"
2628
" current directory."),
2629
Option('repo', help="Check the repository related to the"
2630
" current directory."),
2631
Option('tree', help="Check the working tree related to"
2632
" the current directory.")]
2634
def run(self, path=None, verbose=False, branch=False, repo=False,
2636
from bzrlib.check import check_dwim
2639
if not branch and not repo and not tree:
2640
branch = repo = tree = True
2641
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2644
class cmd_upgrade(Command):
2645
"""Upgrade branch storage to current format.
2647
The check command or bzr developers may sometimes advise you to run
2648
this command. When the default format has changed you may also be warned
2649
during other operations to upgrade.
2652
_see_also = ['check']
2653
takes_args = ['url?']
2655
RegistryOption('format',
2656
help='Upgrade to a specific format. See "bzr help'
2657
' formats" for details.',
2658
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
2659
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2660
value_switches=True, title='Branch format'),
2663
def run(self, url='.', format=None):
2664
from bzrlib.upgrade import upgrade
2666
format = bzrdir.format_registry.make_bzrdir('default')
2667
upgrade(url, format)
2670
class cmd_whoami(Command):
2671
"""Show or set bzr user id.
2674
Show the email of the current user::
2678
Set the current user::
2680
bzr whoami "Frank Chu <fchu@example.com>"
2682
takes_options = [ Option('email',
2683
help='Display email address only.'),
2685
help='Set identity for the current branch instead of '
2688
takes_args = ['name?']
2689
encoding_type = 'replace'
2692
def run(self, email=False, branch=False, name=None):
2694
# use branch if we're inside one; otherwise global config
2696
c = Branch.open_containing('.')[0].get_config()
2697
except errors.NotBranchError:
2698
c = config.GlobalConfig()
2700
self.outf.write(c.user_email() + '\n')
2702
self.outf.write(c.username() + '\n')
2705
# display a warning if an email address isn't included in the given name.
2707
config.extract_email_address(name)
2708
except errors.NoEmailInUsername, e:
2709
warning('"%s" does not seem to contain an email address. '
2710
'This is allowed, but not recommended.', name)
2712
# use global config unless --branch given
2714
c = Branch.open_containing('.')[0].get_config()
2716
c = config.GlobalConfig()
2717
c.set_user_option('email', name)
2720
class cmd_nick(Command):
2721
"""Print or set the branch nickname.
2723
If unset, the tree root directory name is used as the nickname.
2724
To print the current nickname, execute with no argument.
2726
Bound branches use the nickname of its master branch unless it is set
2730
_see_also = ['info']
2731
takes_args = ['nickname?']
2732
def run(self, nickname=None):
2733
branch = Branch.open_containing(u'.')[0]
2734
if nickname is None:
2735
self.printme(branch)
2737
branch.nick = nickname
2740
def printme(self, branch):
2744
class cmd_alias(Command):
2745
"""Set/unset and display aliases.
2748
Show the current aliases::
2752
Show the alias specified for 'll'::
2756
Set an alias for 'll'::
2758
bzr alias ll="log --line -r-10..-1"
2760
To remove an alias for 'll'::
2762
bzr alias --remove ll
2765
takes_args = ['name?']
2767
Option('remove', help='Remove the alias.'),
2770
def run(self, name=None, remove=False):
2772
self.remove_alias(name)
2774
self.print_aliases()
2776
equal_pos = name.find('=')
2778
self.print_alias(name)
2780
self.set_alias(name[:equal_pos], name[equal_pos+1:])
2782
def remove_alias(self, alias_name):
2783
if alias_name is None:
2784
raise errors.BzrCommandError(
2785
'bzr alias --remove expects an alias to remove.')
2786
# If alias is not found, print something like:
2787
# unalias: foo: not found
2788
c = config.GlobalConfig()
2789
c.unset_alias(alias_name)
2792
def print_aliases(self):
2793
"""Print out the defined aliases in a similar format to bash."""
2794
aliases = config.GlobalConfig().get_aliases()
2795
for key, value in sorted(aliases.iteritems()):
2796
self.outf.write('bzr alias %s="%s"\n' % (key, value))
2799
def print_alias(self, alias_name):
2800
from bzrlib.commands import get_alias
2801
alias = get_alias(alias_name)
2803
self.outf.write("bzr alias: %s: not found\n" % alias_name)
2806
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
2808
def set_alias(self, alias_name, alias_command):
2809
"""Save the alias in the global config."""
2810
c = config.GlobalConfig()
2811
c.set_alias(alias_name, alias_command)
2814
class cmd_selftest(Command):
2815
"""Run internal test suite.
2817
If arguments are given, they are regular expressions that say which tests
2818
should run. Tests matching any expression are run, and other tests are
2821
Alternatively if --first is given, matching tests are run first and then
2822
all other tests are run. This is useful if you have been working in a
2823
particular area, but want to make sure nothing else was broken.
2825
If --exclude is given, tests that match that regular expression are
2826
excluded, regardless of whether they match --first or not.
2828
To help catch accidential dependencies between tests, the --randomize
2829
option is useful. In most cases, the argument used is the word 'now'.
2830
Note that the seed used for the random number generator is displayed
2831
when this option is used. The seed can be explicitly passed as the
2832
argument to this option if required. This enables reproduction of the
2833
actual ordering used if and when an order sensitive problem is encountered.
2835
If --list-only is given, the tests that would be run are listed. This is
2836
useful when combined with --first, --exclude and/or --randomize to
2837
understand their impact. The test harness reports "Listed nn tests in ..."
2838
instead of "Ran nn tests in ..." when list mode is enabled.
2840
If the global option '--no-plugins' is given, plugins are not loaded
2841
before running the selftests. This has two effects: features provided or
2842
modified by plugins will not be tested, and tests provided by plugins will
2845
Tests that need working space on disk use a common temporary directory,
2846
typically inside $TMPDIR or /tmp.
2849
Run only tests relating to 'ignore'::
2853
Disable plugins and list tests as they're run::
2855
bzr --no-plugins selftest -v
2857
# NB: this is used from the class without creating an instance, which is
2858
# why it does not have a self parameter.
2859
def get_transport_type(typestring):
2860
"""Parse and return a transport specifier."""
2861
if typestring == "sftp":
2862
from bzrlib.transport.sftp import SFTPAbsoluteServer
2863
return SFTPAbsoluteServer
2864
if typestring == "memory":
2865
from bzrlib.transport.memory import MemoryServer
2867
if typestring == "fakenfs":
2868
from bzrlib.transport.fakenfs import FakeNFSServer
2869
return FakeNFSServer
2870
msg = "No known transport type %s. Supported types are: sftp\n" %\
2872
raise errors.BzrCommandError(msg)
2875
takes_args = ['testspecs*']
2876
takes_options = ['verbose',
2878
help='Stop when one test fails.',
2882
help='Use a different transport by default '
2883
'throughout the test suite.',
2884
type=get_transport_type),
2886
help='Run the benchmarks rather than selftests.'),
2887
Option('lsprof-timed',
2888
help='Generate lsprof output for benchmarked'
2889
' sections of code.'),
2890
Option('cache-dir', type=str,
2891
help='Cache intermediate benchmark output in this '
2894
help='Run all tests, but run specified tests first.',
2898
help='List the tests instead of running them.'),
2899
Option('randomize', type=str, argname="SEED",
2900
help='Randomize the order of tests using the given'
2901
' seed or "now" for the current time.'),
2902
Option('exclude', type=str, argname="PATTERN",
2904
help='Exclude tests that match this regular'
2906
Option('strict', help='Fail on missing dependencies or '
2908
Option('load-list', type=str, argname='TESTLISTFILE',
2909
help='Load a test id list from a text file.'),
2910
ListOption('debugflag', type=str, short_name='E',
2911
help='Turn on a selftest debug flag.'),
2912
ListOption('starting-with', type=str, argname='TESTID',
2913
param_name='starting_with', short_name='s',
2915
'Load only the tests starting with TESTID.'),
2917
encoding_type = 'replace'
2919
def run(self, testspecs_list=None, verbose=False, one=False,
2920
transport=None, benchmark=None,
2921
lsprof_timed=None, cache_dir=None,
2922
first=False, list_only=False,
2923
randomize=None, exclude=None, strict=False,
2924
load_list=None, debugflag=None, starting_with=None):
2925
from bzrlib.tests import selftest
2926
import bzrlib.benchmarks as benchmarks
2927
from bzrlib.benchmarks import tree_creator
2929
# Make deprecation warnings visible, unless -Werror is set
2930
symbol_versioning.activate_deprecation_warnings(override=False)
2932
if cache_dir is not None:
2933
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2935
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2936
print ' %s (%s python%s)' % (
2938
bzrlib.version_string,
2939
bzrlib._format_version_tuple(sys.version_info),
2942
if testspecs_list is not None:
2943
pattern = '|'.join(testspecs_list)
2947
test_suite_factory = benchmarks.test_suite
2948
# Unless user explicitly asks for quiet, be verbose in benchmarks
2949
verbose = not is_quiet()
2950
# TODO: should possibly lock the history file...
2951
benchfile = open(".perf_history", "at", buffering=1)
2953
test_suite_factory = None
2956
result = selftest(verbose=verbose,
2958
stop_on_failure=one,
2959
transport=transport,
2960
test_suite_factory=test_suite_factory,
2961
lsprof_timed=lsprof_timed,
2962
bench_history=benchfile,
2963
matching_tests_first=first,
2964
list_only=list_only,
2965
random_seed=randomize,
2966
exclude_pattern=exclude,
2968
load_list=load_list,
2969
debug_flags=debugflag,
2970
starting_with=starting_with,
2973
if benchfile is not None:
2976
note('tests passed')
2978
note('tests failed')
2979
return int(not result)
2982
class cmd_version(Command):
2983
"""Show version of bzr."""
2985
encoding_type = 'replace'
2987
Option("short", help="Print just the version number."),
2991
def run(self, short=False):
2992
from bzrlib.version import show_version
2994
self.outf.write(bzrlib.version_string + '\n')
2996
show_version(to_file=self.outf)
2999
class cmd_rocks(Command):
3000
"""Statement of optimism."""
3006
print "It sure does!"
3009
class cmd_find_merge_base(Command):
3010
"""Find and print a base revision for merging two branches."""
3011
# TODO: Options to specify revisions on either side, as if
3012
# merging only part of the history.
3013
takes_args = ['branch', 'other']
3017
def run(self, branch, other):
3018
from bzrlib.revision import ensure_null
3020
branch1 = Branch.open_containing(branch)[0]
3021
branch2 = Branch.open_containing(other)[0]
3026
last1 = ensure_null(branch1.last_revision())
3027
last2 = ensure_null(branch2.last_revision())
3029
graph = branch1.repository.get_graph(branch2.repository)
3030
base_rev_id = graph.find_unique_lca(last1, last2)
3032
print 'merge base is revision %s' % base_rev_id
3039
class cmd_merge(Command):
3040
"""Perform a three-way merge.
3042
The source of the merge can be specified either in the form of a branch,
3043
or in the form of a path to a file containing a merge directive generated
3044
with bzr send. If neither is specified, the default is the upstream branch
3045
or the branch most recently merged using --remember.
3047
When merging a branch, by default the tip will be merged. To pick a different
3048
revision, pass --revision. If you specify two values, the first will be used as
3049
BASE and the second one as OTHER. Merging individual revisions, or a subset of
3050
available revisions, like this is commonly referred to as "cherrypicking".
3052
Revision numbers are always relative to the branch being merged.
3054
By default, bzr will try to merge in all new work from the other
3055
branch, automatically determining an appropriate base. If this
3056
fails, you may need to give an explicit base.
3058
Merge will do its best to combine the changes in two branches, but there
3059
are some kinds of problems only a human can fix. When it encounters those,
3060
it will mark a conflict. A conflict means that you need to fix something,
3061
before you should commit.
3063
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3065
If there is no default branch set, the first merge will set it. After
3066
that, you can omit the branch to use the default. To change the
3067
default, use --remember. The value will only be saved if the remote
3068
location can be accessed.
3070
The results of the merge are placed into the destination working
3071
directory, where they can be reviewed (with bzr diff), tested, and then
3072
committed to record the result of the merge.
3074
merge refuses to run if there are any uncommitted changes, unless
3078
To merge the latest revision from bzr.dev::
3080
bzr merge ../bzr.dev
3082
To merge changes up to and including revision 82 from bzr.dev::
3084
bzr merge -r 82 ../bzr.dev
3086
To merge the changes introduced by 82, without previous changes::
3088
bzr merge -r 81..82 ../bzr.dev
3090
To apply a merge directive contained in in /tmp/merge:
3092
bzr merge /tmp/merge
3095
encoding_type = 'exact'
3096
_see_also = ['update', 'remerge', 'status-flags']
3097
takes_args = ['location?']
3102
help='Merge even if the destination tree has uncommitted changes.'),
3106
Option('show-base', help="Show base revision text in "
3108
Option('uncommitted', help='Apply uncommitted changes'
3109
' from a working copy, instead of branch changes.'),
3110
Option('pull', help='If the destination is already'
3111
' completely merged into the source, pull from the'
3112
' source rather than merging. When this happens,'
3113
' you do not need to commit the result.'),
3115
help='Branch to merge into, '
3116
'rather than the one containing the working directory.',
3120
Option('preview', help='Instead of merging, show a diff of the merge.')
3123
def run(self, location=None, revision=None, force=False,
3124
merge_type=None, show_base=False, reprocess=None, remember=False,
3125
uncommitted=False, pull=False,
3129
if merge_type is None:
3130
merge_type = _mod_merge.Merge3Merger
3132
if directory is None: directory = u'.'
3133
possible_transports = []
3135
allow_pending = True
3136
verified = 'inapplicable'
3137
tree = WorkingTree.open_containing(directory)[0]
3138
change_reporter = delta._ChangeReporter(
3139
unversioned_filter=tree.is_ignored)
3142
pb = ui.ui_factory.nested_progress_bar()
3143
cleanups.append(pb.finished)
3145
cleanups.append(tree.unlock)
3146
if location is not None:
3148
mergeable = bundle.read_mergeable_from_url(location,
3149
possible_transports=possible_transports)
3150
except errors.NotABundle:
3154
raise errors.BzrCommandError('Cannot use --uncommitted'
3155
' with bundles or merge directives.')
3157
if revision is not None:
3158
raise errors.BzrCommandError(
3159
'Cannot use -r with merge directives or bundles')
3160
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3163
if merger is None and uncommitted:
3164
if revision is not None and len(revision) > 0:
3165
raise errors.BzrCommandError('Cannot use --uncommitted and'
3166
' --revision at the same time.')
3167
location = self._select_branch_location(tree, location)[0]
3168
other_tree, other_path = WorkingTree.open_containing(location)
3169
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3171
allow_pending = False
3172
if other_path != '':
3173
merger.interesting_files = [other_path]
3176
merger, allow_pending = self._get_merger_from_branch(tree,
3177
location, revision, remember, possible_transports, pb)
3179
merger.merge_type = merge_type
3180
merger.reprocess = reprocess
3181
merger.show_base = show_base
3182
self.sanity_check_merger(merger)
3183
if (merger.base_rev_id == merger.other_rev_id and
3184
merger.other_rev_id is not None):
3185
note('Nothing to do.')
3188
if merger.interesting_files is not None:
3189
raise errors.BzrCommandError('Cannot pull individual files')
3190
if (merger.base_rev_id == tree.last_revision()):
3191
result = tree.pull(merger.other_branch, False,
3192
merger.other_rev_id)
3193
result.report(self.outf)
3195
merger.check_basis(not force)
3197
return self._do_preview(merger)
3199
return self._do_merge(merger, change_reporter, allow_pending,
3202
for cleanup in reversed(cleanups):
3205
def _do_preview(self, merger):
3206
from bzrlib.diff import show_diff_trees
3207
tree_merger = merger.make_merger()
3208
tt = tree_merger.make_preview_transform()
3210
result_tree = tt.get_preview_tree()
3211
show_diff_trees(merger.this_tree, result_tree, self.outf,
3212
old_label='', new_label='')
3216
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3217
merger.change_reporter = change_reporter
3218
conflict_count = merger.do_merge()
3220
merger.set_pending()
3221
if verified == 'failed':
3222
warning('Preview patch does not match changes')
3223
if conflict_count != 0:
3228
def sanity_check_merger(self, merger):
3229
if (merger.show_base and
3230
not merger.merge_type is _mod_merge.Merge3Merger):
3231
raise errors.BzrCommandError("Show-base is not supported for this"
3232
" merge type. %s" % merger.merge_type)
3233
if merger.reprocess is None:
3234
if merger.show_base:
3235
merger.reprocess = False
3237
# Use reprocess if the merger supports it
3238
merger.reprocess = merger.merge_type.supports_reprocess
3239
if merger.reprocess and not merger.merge_type.supports_reprocess:
3240
raise errors.BzrCommandError("Conflict reduction is not supported"
3241
" for merge type %s." %
3243
if merger.reprocess and merger.show_base:
3244
raise errors.BzrCommandError("Cannot do conflict reduction and"
3247
def _get_merger_from_branch(self, tree, location, revision, remember,
3248
possible_transports, pb):
3249
"""Produce a merger from a location, assuming it refers to a branch."""
3250
from bzrlib.tag import _merge_tags_if_possible
3251
# find the branch locations
3252
other_loc, user_location = self._select_branch_location(tree, location,
3254
if revision is not None and len(revision) == 2:
3255
base_loc, _unused = self._select_branch_location(tree,
3256
location, revision, 0)
3258
base_loc = other_loc
3260
other_branch, other_path = Branch.open_containing(other_loc,
3261
possible_transports)
3262
if base_loc == other_loc:
3263
base_branch = other_branch
3265
base_branch, base_path = Branch.open_containing(base_loc,
3266
possible_transports)
3267
# Find the revision ids
3268
if revision is None or len(revision) < 1 or revision[-1] is None:
3269
other_revision_id = _mod_revision.ensure_null(
3270
other_branch.last_revision())
3272
other_revision_id = revision[-1].as_revision_id(other_branch)
3273
if (revision is not None and len(revision) == 2
3274
and revision[0] is not None):
3275
base_revision_id = revision[0].as_revision_id(base_branch)
3277
base_revision_id = None
3278
# Remember where we merge from
3279
if ((remember or tree.branch.get_submit_branch() is None) and
3280
user_location is not None):
3281
tree.branch.set_submit_branch(other_branch.base)
3282
_merge_tags_if_possible(other_branch, tree.branch)
3283
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3284
other_revision_id, base_revision_id, other_branch, base_branch)
3285
if other_path != '':
3286
allow_pending = False
3287
merger.interesting_files = [other_path]
3289
allow_pending = True
3290
return merger, allow_pending
3292
def _select_branch_location(self, tree, user_location, revision=None,
3294
"""Select a branch location, according to possible inputs.
3296
If provided, branches from ``revision`` are preferred. (Both
3297
``revision`` and ``index`` must be supplied.)
3299
Otherwise, the ``location`` parameter is used. If it is None, then the
3300
``submit`` or ``parent`` location is used, and a note is printed.
3302
:param tree: The working tree to select a branch for merging into
3303
:param location: The location entered by the user
3304
:param revision: The revision parameter to the command
3305
:param index: The index to use for the revision parameter. Negative
3306
indices are permitted.
3307
:return: (selected_location, user_location). The default location
3308
will be the user-entered location.
3310
if (revision is not None and index is not None
3311
and revision[index] is not None):
3312
branch = revision[index].get_branch()
3313
if branch is not None:
3314
return branch, branch
3315
if user_location is None:
3316
location = self._get_remembered(tree, 'Merging from')
3318
location = user_location
3319
return location, user_location
3321
def _get_remembered(self, tree, verb_string):
3322
"""Use tree.branch's parent if none was supplied.
3324
Report if the remembered location was used.
3326
stored_location = tree.branch.get_submit_branch()
3327
stored_location_type = "submit"
3328
if stored_location is None:
3329
stored_location = tree.branch.get_parent()
3330
stored_location_type = "parent"
3331
mutter("%s", stored_location)
3332
if stored_location is None:
3333
raise errors.BzrCommandError("No location specified or remembered")
3334
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3335
note(u"%s remembered %s location %s", verb_string,
3336
stored_location_type, display_url)
3337
return stored_location
3340
class cmd_remerge(Command):
3343
Use this if you want to try a different merge technique while resolving
3344
conflicts. Some merge techniques are better than others, and remerge
3345
lets you try different ones on different files.
3347
The options for remerge have the same meaning and defaults as the ones for
3348
merge. The difference is that remerge can (only) be run when there is a
3349
pending merge, and it lets you specify particular files.
3352
Re-do the merge of all conflicted files, and show the base text in
3353
conflict regions, in addition to the usual THIS and OTHER texts::
3355
bzr remerge --show-base
3357
Re-do the merge of "foobar", using the weave merge algorithm, with
3358
additional processing to reduce the size of conflict regions::
3360
bzr remerge --merge-type weave --reprocess foobar
3362
takes_args = ['file*']
3367
help="Show base revision text in conflicts."),
3370
def run(self, file_list=None, merge_type=None, show_base=False,
3372
if merge_type is None:
3373
merge_type = _mod_merge.Merge3Merger
3374
tree, file_list = tree_files(file_list)
3377
parents = tree.get_parent_ids()
3378
if len(parents) != 2:
3379
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3380
" merges. Not cherrypicking or"
3382
repository = tree.branch.repository
3383
interesting_ids = None
3385
conflicts = tree.conflicts()
3386
if file_list is not None:
3387
interesting_ids = set()
3388
for filename in file_list:
3389
file_id = tree.path2id(filename)
3391
raise errors.NotVersionedError(filename)
3392
interesting_ids.add(file_id)
3393
if tree.kind(file_id) != "directory":
3396
for name, ie in tree.inventory.iter_entries(file_id):
3397
interesting_ids.add(ie.file_id)
3398
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3400
# Remerge only supports resolving contents conflicts
3401
allowed_conflicts = ('text conflict', 'contents conflict')
3402
restore_files = [c.path for c in conflicts
3403
if c.typestring in allowed_conflicts]
3404
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3405
tree.set_conflicts(ConflictList(new_conflicts))
3406
if file_list is not None:
3407
restore_files = file_list
3408
for filename in restore_files:
3410
restore(tree.abspath(filename))
3411
except errors.NotConflicted:
3413
# Disable pending merges, because the file texts we are remerging
3414
# have not had those merges performed. If we use the wrong parents
3415
# list, we imply that the working tree text has seen and rejected
3416
# all the changes from the other tree, when in fact those changes
3417
# have not yet been seen.
3418
pb = ui.ui_factory.nested_progress_bar()
3419
tree.set_parent_ids(parents[:1])
3421
merger = _mod_merge.Merger.from_revision_ids(pb,
3423
merger.interesting_ids = interesting_ids
3424
merger.merge_type = merge_type
3425
merger.show_base = show_base
3426
merger.reprocess = reprocess
3427
conflicts = merger.do_merge()
3429
tree.set_parent_ids(parents)
3439
class cmd_revert(Command):
3440
"""Revert files to a previous revision.
3442
Giving a list of files will revert only those files. Otherwise, all files
3443
will be reverted. If the revision is not specified with '--revision', the
3444
last committed revision is used.
3446
To remove only some changes, without reverting to a prior version, use
3447
merge instead. For example, "merge . --revision -2..-3" will remove the
3448
changes introduced by -2, without affecting the changes introduced by -1.
3449
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3451
By default, any files that have been manually changed will be backed up
3452
first. (Files changed only by merge are not backed up.) Backup files have
3453
'.~#~' appended to their name, where # is a number.
3455
When you provide files, you can use their current pathname or the pathname
3456
from the target revision. So you can use revert to "undelete" a file by
3457
name. If you name a directory, all the contents of that directory will be
3460
Any files that have been newly added since that revision will be deleted,
3461
with a backup kept if appropriate. Directories containing unknown files
3462
will not be deleted.
3464
The working tree contains a list of pending merged revisions, which will
3465
be included as parents in the next commit. Normally, revert clears that
3466
list as well as reverting the files. If any files are specified, revert
3467
leaves the pending merge list alone and reverts only the files. Use "bzr
3468
revert ." in the tree root to revert all files but keep the merge record,
3469
and "bzr revert --forget-merges" to clear the pending merge list without
3470
reverting any files.
3473
_see_also = ['cat', 'export']
3476
Option('no-backup', "Do not save backups of reverted files."),
3477
Option('forget-merges',
3478
'Remove pending merge marker, without changing any files.'),
3480
takes_args = ['file*']
3482
def run(self, revision=None, no_backup=False, file_list=None,
3483
forget_merges=None):
3484
tree, file_list = tree_files(file_list)
3488
tree.set_parent_ids(tree.get_parent_ids()[:1])
3490
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3495
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3496
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
3497
pb = ui.ui_factory.nested_progress_bar()
3499
tree.revert(file_list, rev_tree, not no_backup, pb,
3500
report_changes=True)
3505
class cmd_assert_fail(Command):
3506
"""Test reporting of assertion failures"""
3507
# intended just for use in testing
3512
raise AssertionError("always fails")
3515
class cmd_help(Command):
3516
"""Show help on a command or other topic.
3519
_see_also = ['topics']
3521
Option('long', 'Show help on all commands.'),
3523
takes_args = ['topic?']
3524
aliases = ['?', '--help', '-?', '-h']
3527
def run(self, topic=None, long=False):
3529
if topic is None and long:
3531
bzrlib.help.help(topic)
3534
class cmd_shell_complete(Command):
3535
"""Show appropriate completions for context.
3537
For a list of all available commands, say 'bzr shell-complete'.
3539
takes_args = ['context?']
3544
def run(self, context=None):
3545
import shellcomplete
3546
shellcomplete.shellcomplete(context)
3549
class cmd_missing(Command):
3550
"""Show unmerged/unpulled revisions between two branches.
3552
OTHER_BRANCH may be local or remote.
3554
To filter on a range of revirions, you can use the command -r begin..end
3555
-r revision requests a specific revision, -r ..end or -r begin.. are
3560
Determine the missing revisions between this and the branch at the
3561
remembered pull location::
3565
Determine the missing revisions between this and another branch::
3567
bzr missing http://server/branch
3569
Determine the missing revisions up to a specific revision on the other
3572
bzr missing -r ..-10
3574
Determine the missing revisions up to a specific revision on this
3577
bzr missing --my-revision ..-10
3580
_see_also = ['merge', 'pull']
3581
takes_args = ['other_branch?']
3583
Option('reverse', 'Reverse the order of revisions.'),
3585
'Display changes in the local branch only.'),
3586
Option('this' , 'Same as --mine-only.'),
3587
Option('theirs-only',
3588
'Display changes in the remote branch only.'),
3589
Option('other', 'Same as --theirs-only.'),
3593
custom_help('revision',
3594
help='Filter on other branch revisions (inclusive). '
3595
'See "help revisionspec" for details.'),
3596
Option('my-revision',
3597
type=_parse_revision_str,
3598
help='Filter on local branch revisions (inclusive). '
3599
'See "help revisionspec" for details.'),
3600
Option('include-merges', 'Show merged revisions.'),
3602
encoding_type = 'replace'
3605
def run(self, other_branch=None, reverse=False, mine_only=False,
3607
log_format=None, long=False, short=False, line=False,
3608
show_ids=False, verbose=False, this=False, other=False,
3609
include_merges=False, revision=None, my_revision=None):
3610
from bzrlib.missing import find_unmerged, iter_log_revisions
3619
# TODO: We should probably check that we don't have mine-only and
3620
# theirs-only set, but it gets complicated because we also have
3621
# this and other which could be used.
3628
local_branch = Branch.open_containing(u".")[0]
3629
parent = local_branch.get_parent()
3630
if other_branch is None:
3631
other_branch = parent
3632
if other_branch is None:
3633
raise errors.BzrCommandError("No peer location known"
3635
display_url = urlutils.unescape_for_display(parent,
3637
message("Using saved parent location: "
3638
+ display_url + "\n")
3640
remote_branch = Branch.open(other_branch)
3641
if remote_branch.base == local_branch.base:
3642
remote_branch = local_branch
3644
local_revid_range = _revision_range_to_revid_range(
3645
_get_revision_range(my_revision, local_branch,
3648
remote_revid_range = _revision_range_to_revid_range(
3649
_get_revision_range(revision,
3650
remote_branch, self.name()))
3652
local_branch.lock_read()
3654
remote_branch.lock_read()
3656
local_extra, remote_extra = find_unmerged(
3657
local_branch, remote_branch, restrict,
3658
backward=not reverse,
3659
include_merges=include_merges,
3660
local_revid_range=local_revid_range,
3661
remote_revid_range=remote_revid_range)
3663
if log_format is None:
3664
registry = log.log_formatter_registry
3665
log_format = registry.get_default(local_branch)
3666
lf = log_format(to_file=self.outf,
3668
show_timezone='original')
3671
if local_extra and not theirs_only:
3672
message("You have %d extra revision(s):\n" %
3674
for revision in iter_log_revisions(local_extra,
3675
local_branch.repository,
3677
lf.log_revision(revision)
3678
printed_local = True
3681
printed_local = False
3683
if remote_extra and not mine_only:
3684
if printed_local is True:
3686
message("You are missing %d revision(s):\n" %
3688
for revision in iter_log_revisions(remote_extra,
3689
remote_branch.repository,
3691
lf.log_revision(revision)
3694
if mine_only and not local_extra:
3695
# We checked local, and found nothing extra
3696
message('This branch is up to date.\n')
3697
elif theirs_only and not remote_extra:
3698
# We checked remote, and found nothing extra
3699
message('Other branch is up to date.\n')
3700
elif not (mine_only or theirs_only or local_extra or
3702
# We checked both branches, and neither one had extra
3704
message("Branches are up to date.\n")
3706
remote_branch.unlock()
3708
local_branch.unlock()
3709
if not status_code and parent is None and other_branch is not None:
3710
local_branch.lock_write()
3712
# handle race conditions - a parent might be set while we run.
3713
if local_branch.get_parent() is None:
3714
local_branch.set_parent(remote_branch.base)
3716
local_branch.unlock()
3720
class cmd_pack(Command):
3721
"""Compress the data within a repository."""
3723
_see_also = ['repositories']
3724
takes_args = ['branch_or_repo?']
3726
def run(self, branch_or_repo='.'):
3727
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3729
branch = dir.open_branch()
3730
repository = branch.repository
3731
except errors.NotBranchError:
3732
repository = dir.open_repository()
3736
class cmd_plugins(Command):
3737
"""List the installed plugins.
3739
This command displays the list of installed plugins including
3740
version of plugin and a short description of each.
3742
--verbose shows the path where each plugin is located.
3744
A plugin is an external component for Bazaar that extends the
3745
revision control system, by adding or replacing code in Bazaar.
3746
Plugins can do a variety of things, including overriding commands,
3747
adding new commands, providing additional network transports and
3748
customizing log output.
3750
See the Bazaar web site, http://bazaar-vcs.org, for further
3751
information on plugins including where to find them and how to
3752
install them. Instructions are also provided there on how to
3753
write new plugins using the Python programming language.
3755
takes_options = ['verbose']
3758
def run(self, verbose=False):
3759
import bzrlib.plugin
3760
from inspect import getdoc
3762
for name, plugin in bzrlib.plugin.plugins().items():
3763
version = plugin.__version__
3764
if version == 'unknown':
3766
name_ver = '%s %s' % (name, version)
3767
d = getdoc(plugin.module)
3769
doc = d.split('\n')[0]
3771
doc = '(no description)'
3772
result.append((name_ver, doc, plugin.path()))
3773
for name_ver, doc, path in sorted(result):
3781
class cmd_testament(Command):
3782
"""Show testament (signing-form) of a revision."""
3785
Option('long', help='Produce long-format testament.'),
3787
help='Produce a strict-format testament.')]
3788
takes_args = ['branch?']
3790
def run(self, branch=u'.', revision=None, long=False, strict=False):
3791
from bzrlib.testament import Testament, StrictTestament
3793
testament_class = StrictTestament
3795
testament_class = Testament
3797
b = Branch.open_containing(branch)[0]
3799
b = Branch.open(branch)
3802
if revision is None:
3803
rev_id = b.last_revision()
3805
rev_id = revision[0].as_revision_id(b)
3806
t = testament_class.from_revision(b.repository, rev_id)
3808
sys.stdout.writelines(t.as_text_lines())
3810
sys.stdout.write(t.as_short_text())
3815
class cmd_annotate(Command):
3816
"""Show the origin of each line in a file.
3818
This prints out the given file with an annotation on the left side
3819
indicating which revision, author and date introduced the change.
3821
If the origin is the same for a run of consecutive lines, it is
3822
shown only at the top, unless the --all option is given.
3824
# TODO: annotate directories; showing when each file was last changed
3825
# TODO: if the working copy is modified, show annotations on that
3826
# with new uncommitted lines marked
3827
aliases = ['ann', 'blame', 'praise']
3828
takes_args = ['filename']
3829
takes_options = [Option('all', help='Show annotations on all lines.'),
3830
Option('long', help='Show commit date in annotations.'),
3834
encoding_type = 'exact'
3837
def run(self, filename, all=False, long=False, revision=None,
3839
from bzrlib.annotate import annotate_file, annotate_file_tree
3840
wt, branch, relpath = \
3841
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3847
tree = _get_one_revision_tree('annotate', revision, branch=branch)
3849
file_id = wt.path2id(relpath)
3851
file_id = tree.path2id(relpath)
3853
raise errors.NotVersionedError(filename)
3854
file_version = tree.inventory[file_id].revision
3855
if wt is not None and revision is None:
3856
# If there is a tree and we're not annotating historical
3857
# versions, annotate the working tree's content.
3858
annotate_file_tree(wt, file_id, self.outf, long, all,
3861
annotate_file(branch, file_version, file_id, long, all, self.outf,
3870
class cmd_re_sign(Command):
3871
"""Create a digital signature for an existing revision."""
3872
# TODO be able to replace existing ones.
3874
hidden = True # is this right ?
3875
takes_args = ['revision_id*']
3876
takes_options = ['revision']
3878
def run(self, revision_id_list=None, revision=None):
3879
if revision_id_list is not None and revision is not None:
3880
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3881
if revision_id_list is None and revision is None:
3882
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3883
b = WorkingTree.open_containing(u'.')[0].branch
3886
return self._run(b, revision_id_list, revision)
3890
def _run(self, b, revision_id_list, revision):
3891
import bzrlib.gpg as gpg
3892
gpg_strategy = gpg.GPGStrategy(b.get_config())
3893
if revision_id_list is not None:
3894
b.repository.start_write_group()
3896
for revision_id in revision_id_list:
3897
b.repository.sign_revision(revision_id, gpg_strategy)
3899
b.repository.abort_write_group()
3902
b.repository.commit_write_group()
3903
elif revision is not None:
3904
if len(revision) == 1:
3905
revno, rev_id = revision[0].in_history(b)
3906
b.repository.start_write_group()
3908
b.repository.sign_revision(rev_id, gpg_strategy)
3910
b.repository.abort_write_group()
3913
b.repository.commit_write_group()
3914
elif len(revision) == 2:
3915
# are they both on rh- if so we can walk between them
3916
# might be nice to have a range helper for arbitrary
3917
# revision paths. hmm.
3918
from_revno, from_revid = revision[0].in_history(b)
3919
to_revno, to_revid = revision[1].in_history(b)
3920
if to_revid is None:
3921
to_revno = b.revno()
3922
if from_revno is None or to_revno is None:
3923
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3924
b.repository.start_write_group()
3926
for revno in range(from_revno, to_revno + 1):
3927
b.repository.sign_revision(b.get_rev_id(revno),
3930
b.repository.abort_write_group()
3933
b.repository.commit_write_group()
3935
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3938
class cmd_bind(Command):
3939
"""Convert the current branch into a checkout of the supplied branch.
3941
Once converted into a checkout, commits must succeed on the master branch
3942
before they will be applied to the local branch.
3944
Bound branches use the nickname of its master branch unless it is set
3945
locally, in which case binding will update the the local nickname to be
3949
_see_also = ['checkouts', 'unbind']
3950
takes_args = ['location?']
3953
def run(self, location=None):
3954
b, relpath = Branch.open_containing(u'.')
3955
if location is None:
3957
location = b.get_old_bound_location()
3958
except errors.UpgradeRequired:
3959
raise errors.BzrCommandError('No location supplied. '
3960
'This format does not remember old locations.')
3962
if location is None:
3963
raise errors.BzrCommandError('No location supplied and no '
3964
'previous location known')
3965
b_other = Branch.open(location)
3968
except errors.DivergedBranches:
3969
raise errors.BzrCommandError('These branches have diverged.'
3970
' Try merging, and then bind again.')
3971
if b.get_config().has_explicit_nickname():
3972
b.nick = b_other.nick
3975
class cmd_unbind(Command):
3976
"""Convert the current checkout into a regular branch.
3978
After unbinding, the local branch is considered independent and subsequent
3979
commits will be local only.
3982
_see_also = ['checkouts', 'bind']
3987
b, relpath = Branch.open_containing(u'.')
3989
raise errors.BzrCommandError('Local branch is not bound')
3992
class cmd_uncommit(Command):
3993
"""Remove the last committed revision.
3995
--verbose will print out what is being removed.
3996
--dry-run will go through all the motions, but not actually
3999
If --revision is specified, uncommit revisions to leave the branch at the
4000
specified revision. For example, "bzr uncommit -r 15" will leave the
4001
branch at revision 15.
4003
Uncommit leaves the working tree ready for a new commit. The only change
4004
it may make is to restore any pending merges that were present before
4008
# TODO: jam 20060108 Add an option to allow uncommit to remove
4009
# unreferenced information in 'branch-as-repository' branches.
4010
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
4011
# information in shared branches as well.
4012
_see_also = ['commit']
4013
takes_options = ['verbose', 'revision',
4014
Option('dry-run', help='Don\'t actually make changes.'),
4015
Option('force', help='Say yes to all questions.'),
4017
help="Only remove the commits from the local branch"
4018
" when in a checkout."
4021
takes_args = ['location?']
4023
encoding_type = 'replace'
4025
def run(self, location=None,
4026
dry_run=False, verbose=False,
4027
revision=None, force=False, local=False):
4028
if location is None:
4030
control, relpath = bzrdir.BzrDir.open_containing(location)
4032
tree = control.open_workingtree()
4034
except (errors.NoWorkingTree, errors.NotLocalUrl):
4036
b = control.open_branch()
4038
if tree is not None:
4043
return self._run(b, tree, dry_run, verbose, revision, force,
4046
if tree is not None:
4051
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4052
from bzrlib.log import log_formatter, show_log
4053
from bzrlib.uncommit import uncommit
4055
last_revno, last_rev_id = b.last_revision_info()
4058
if revision is None:
4060
rev_id = last_rev_id
4062
# 'bzr uncommit -r 10' actually means uncommit
4063
# so that the final tree is at revno 10.
4064
# but bzrlib.uncommit.uncommit() actually uncommits
4065
# the revisions that are supplied.
4066
# So we need to offset it by one
4067
revno = revision[0].in_history(b).revno + 1
4068
if revno <= last_revno:
4069
rev_id = b.get_rev_id(revno)
4071
if rev_id is None or _mod_revision.is_null(rev_id):
4072
self.outf.write('No revisions to uncommit.\n')
4075
lf = log_formatter('short',
4077
show_timezone='original')
4082
direction='forward',
4083
start_revision=revno,
4084
end_revision=last_revno)
4087
print 'Dry-run, pretending to remove the above revisions.'
4089
val = raw_input('Press <enter> to continue')
4091
print 'The above revision(s) will be removed.'
4093
val = raw_input('Are you sure [y/N]? ')
4094
if val.lower() not in ('y', 'yes'):
4098
mutter('Uncommitting from {%s} to {%s}',
4099
last_rev_id, rev_id)
4100
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4101
revno=revno, local=local)
4102
note('You can restore the old tip by running:\n'
4103
' bzr pull . -r revid:%s', last_rev_id)
4106
class cmd_break_lock(Command):
4107
"""Break a dead lock on a repository, branch or working directory.
4109
CAUTION: Locks should only be broken when you are sure that the process
4110
holding the lock has been stopped.
4112
You can get information on what locks are open via the 'bzr info' command.
4117
takes_args = ['location?']
4119
def run(self, location=None, show=False):
4120
if location is None:
4122
control, relpath = bzrdir.BzrDir.open_containing(location)
4124
control.break_lock()
4125
except NotImplementedError:
4129
class cmd_wait_until_signalled(Command):
4130
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4132
This just prints a line to signal when it is ready, then blocks on stdin.
4138
sys.stdout.write("running\n")
4140
sys.stdin.readline()
4143
class cmd_serve(Command):
4144
"""Run the bzr server."""
4146
aliases = ['server']
4150
help='Serve on stdin/out for use from inetd or sshd.'),
4152
help='Listen for connections on nominated port of the form '
4153
'[hostname:]portnumber. Passing 0 as the port number will '
4154
'result in a dynamically allocated port. The default port is '
4158
help='Serve contents of this directory.',
4160
Option('allow-writes',
4161
help='By default the server is a readonly server. Supplying '
4162
'--allow-writes enables write access to the contents of '
4163
'the served directory and below.'
4167
def run_smart_server(self, smart_server):
4168
"""Run 'smart_server' forever, with no UI output at all."""
4169
# For the duration of this server, no UI output is permitted. note
4170
# that this may cause problems with blackbox tests. This should be
4171
# changed with care though, as we dont want to use bandwidth sending
4172
# progress over stderr to smart server clients!
4173
from bzrlib import lockdir
4174
old_factory = ui.ui_factory
4175
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4177
ui.ui_factory = ui.SilentUIFactory()
4178
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4179
smart_server.serve()
4181
ui.ui_factory = old_factory
4182
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4184
def get_host_and_port(self, port):
4185
"""Return the host and port to run the smart server on.
4187
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4188
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4190
If 'port' has a colon in it, the string before the colon will be
4191
interpreted as the host.
4193
:param port: A string of the port to run the server on.
4194
:return: A tuple of (host, port), where 'host' is a host name or IP,
4195
and port is an integer TCP/IP port.
4197
from bzrlib.smart import medium
4198
host = medium.BZR_DEFAULT_INTERFACE
4200
port = medium.BZR_DEFAULT_PORT
4203
host, port = port.split(':')
4207
def get_smart_server(self, transport, inet, port):
4208
"""Construct a smart server.
4210
:param transport: The base transport from which branches will be
4212
:param inet: If True, serve over stdin and stdout. Used for running
4214
:param port: The port to listen on. By default, it's `
4215
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4217
:return: A smart server.
4219
from bzrlib.smart import medium, server
4221
smart_server = medium.SmartServerPipeStreamMedium(
4222
sys.stdin, sys.stdout, transport)
4224
host, port = self.get_host_and_port(port)
4225
smart_server = server.SmartTCPServer(
4226
transport, host=host, port=port)
4227
note('listening on port: %s' % smart_server.port)
4230
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4231
from bzrlib.transport import get_transport
4232
from bzrlib.transport.chroot import ChrootServer
4233
if directory is None:
4234
directory = os.getcwd()
4235
url = urlutils.local_path_to_url(directory)
4236
if not allow_writes:
4237
url = 'readonly+' + url
4238
chroot_server = ChrootServer(get_transport(url))
4239
chroot_server.setUp()
4240
t = get_transport(chroot_server.get_url())
4241
smart_server = self.get_smart_server(t, inet, port)
4242
self.run_smart_server(smart_server)
4245
class cmd_join(Command):
4246
"""Combine a subtree into its containing tree.
4248
This command is for experimental use only. It requires the target tree
4249
to be in dirstate-with-subtree format, which cannot be converted into
4252
The TREE argument should be an independent tree, inside another tree, but
4253
not part of it. (Such trees can be produced by "bzr split", but also by
4254
running "bzr branch" with the target inside a tree.)
4256
The result is a combined tree, with the subtree no longer an independant
4257
part. This is marked as a merge of the subtree into the containing tree,
4258
and all history is preserved.
4260
If --reference is specified, the subtree retains its independence. It can
4261
be branched by itself, and can be part of multiple projects at the same
4262
time. But operations performed in the containing tree, such as commit
4263
and merge, will recurse into the subtree.
4266
_see_also = ['split']
4267
takes_args = ['tree']
4269
Option('reference', help='Join by reference.'),
4273
def run(self, tree, reference=False):
4274
sub_tree = WorkingTree.open(tree)
4275
parent_dir = osutils.dirname(sub_tree.basedir)
4276
containing_tree = WorkingTree.open_containing(parent_dir)[0]
4277
repo = containing_tree.branch.repository
4278
if not repo.supports_rich_root():
4279
raise errors.BzrCommandError(
4280
"Can't join trees because %s doesn't support rich root data.\n"
4281
"You can use bzr upgrade on the repository."
4285
containing_tree.add_reference(sub_tree)
4286
except errors.BadReferenceTarget, e:
4287
# XXX: Would be better to just raise a nicely printable
4288
# exception from the real origin. Also below. mbp 20070306
4289
raise errors.BzrCommandError("Cannot join %s. %s" %
4293
containing_tree.subsume(sub_tree)
4294
except errors.BadSubsumeSource, e:
4295
raise errors.BzrCommandError("Cannot join %s. %s" %
4299
class cmd_split(Command):
4300
"""Split a subdirectory of a tree into a separate tree.
4302
This command will produce a target tree in a format that supports
4303
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4304
converted into earlier formats like 'dirstate-tags'.
4306
The TREE argument should be a subdirectory of a working tree. That
4307
subdirectory will be converted into an independent tree, with its own
4308
branch. Commits in the top-level tree will not apply to the new subtree.
4311
# join is not un-hidden yet
4312
#_see_also = ['join']
4313
takes_args = ['tree']
4315
def run(self, tree):
4316
containing_tree, subdir = WorkingTree.open_containing(tree)
4317
sub_id = containing_tree.path2id(subdir)
4319
raise errors.NotVersionedError(subdir)
4321
containing_tree.extract(sub_id)
4322
except errors.RootNotRich:
4323
raise errors.UpgradeRequired(containing_tree.branch.base)
4326
class cmd_merge_directive(Command):
4327
"""Generate a merge directive for auto-merge tools.
4329
A directive requests a merge to be performed, and also provides all the
4330
information necessary to do so. This means it must either include a
4331
revision bundle, or the location of a branch containing the desired
4334
A submit branch (the location to merge into) must be supplied the first
4335
time the command is issued. After it has been supplied once, it will
4336
be remembered as the default.
4338
A public branch is optional if a revision bundle is supplied, but required
4339
if --diff or --plain is specified. It will be remembered as the default
4340
after the first use.
4343
takes_args = ['submit_branch?', 'public_branch?']
4347
_see_also = ['send']
4350
RegistryOption.from_kwargs('patch-type',
4351
'The type of patch to include in the directive.',
4353
value_switches=True,
4355
bundle='Bazaar revision bundle (default).',
4356
diff='Normal unified diff.',
4357
plain='No patch, just directive.'),
4358
Option('sign', help='GPG-sign the directive.'), 'revision',
4359
Option('mail-to', type=str,
4360
help='Instead of printing the directive, email to this address.'),
4361
Option('message', type=str, short_name='m',
4362
help='Message to use when committing this merge.')
4365
encoding_type = 'exact'
4367
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4368
sign=False, revision=None, mail_to=None, message=None):
4369
from bzrlib.revision import ensure_null, NULL_REVISION
4370
include_patch, include_bundle = {
4371
'plain': (False, False),
4372
'diff': (True, False),
4373
'bundle': (True, True),
4375
branch = Branch.open('.')
4376
stored_submit_branch = branch.get_submit_branch()
4377
if submit_branch is None:
4378
submit_branch = stored_submit_branch
4380
if stored_submit_branch is None:
4381
branch.set_submit_branch(submit_branch)
4382
if submit_branch is None:
4383
submit_branch = branch.get_parent()
4384
if submit_branch is None:
4385
raise errors.BzrCommandError('No submit branch specified or known')
4387
stored_public_branch = branch.get_public_branch()
4388
if public_branch is None:
4389
public_branch = stored_public_branch
4390
elif stored_public_branch is None:
4391
branch.set_public_branch(public_branch)
4392
if not include_bundle and public_branch is None:
4393
raise errors.BzrCommandError('No public branch specified or'
4395
base_revision_id = None
4396
if revision is not None:
4397
if len(revision) > 2:
4398
raise errors.BzrCommandError('bzr merge-directive takes '
4399
'at most two one revision identifiers')
4400
revision_id = revision[-1].as_revision_id(branch)
4401
if len(revision) == 2:
4402
base_revision_id = revision[0].as_revision_id(branch)
4404
revision_id = branch.last_revision()
4405
revision_id = ensure_null(revision_id)
4406
if revision_id == NULL_REVISION:
4407
raise errors.BzrCommandError('No revisions to bundle.')
4408
directive = merge_directive.MergeDirective2.from_objects(
4409
branch.repository, revision_id, time.time(),
4410
osutils.local_time_offset(), submit_branch,
4411
public_branch=public_branch, include_patch=include_patch,
4412
include_bundle=include_bundle, message=message,
4413
base_revision_id=base_revision_id)
4416
self.outf.write(directive.to_signed(branch))
4418
self.outf.writelines(directive.to_lines())
4420
message = directive.to_email(mail_to, branch, sign)
4421
s = SMTPConnection(branch.get_config())
4422
s.send_email(message)
4425
class cmd_send(Command):
4426
"""Mail or create a merge-directive for submitting changes.
4428
A merge directive provides many things needed for requesting merges:
4430
* A machine-readable description of the merge to perform
4432
* An optional patch that is a preview of the changes requested
4434
* An optional bundle of revision data, so that the changes can be applied
4435
directly from the merge directive, without retrieving data from a
4438
If --no-bundle is specified, then public_branch is needed (and must be
4439
up-to-date), so that the receiver can perform the merge using the
4440
public_branch. The public_branch is always included if known, so that
4441
people can check it later.
4443
The submit branch defaults to the parent, but can be overridden. Both
4444
submit branch and public branch will be remembered if supplied.
4446
If a public_branch is known for the submit_branch, that public submit
4447
branch is used in the merge instructions. This means that a local mirror
4448
can be used as your actual submit branch, once you have set public_branch
4451
Mail is sent using your preferred mail program. This should be transparent
4452
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4453
If the preferred client can't be found (or used), your editor will be used.
4455
To use a specific mail program, set the mail_client configuration option.
4456
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4457
specific clients are "claws", "evolution", "kmail", "mutt", and
4458
"thunderbird"; generic options are "default", "editor", "emacsclient",
4459
"mapi", and "xdg-email". Plugins may also add supported clients.
4461
If mail is being sent, a to address is required. This can be supplied
4462
either on the commandline, by setting the submit_to configuration
4463
option in the branch itself or the child_submit_to configuration option
4464
in the submit branch.
4466
Two formats are currently supported: "4" uses revision bundle format 4 and
4467
merge directive format 2. It is significantly faster and smaller than
4468
older formats. It is compatible with Bazaar 0.19 and later. It is the
4469
default. "0.9" uses revision bundle format 0.9 and merge directive
4470
format 1. It is compatible with Bazaar 0.12 - 0.18.
4472
Merge directives are applied using the merge command or the pull command.
4475
encoding_type = 'exact'
4477
_see_also = ['merge', 'pull']
4479
takes_args = ['submit_branch?', 'public_branch?']
4483
help='Do not include a bundle in the merge directive.'),
4484
Option('no-patch', help='Do not include a preview patch in the merge'
4487
help='Remember submit and public branch.'),
4489
help='Branch to generate the submission from, '
4490
'rather than the one containing the working directory.',
4493
Option('output', short_name='o',
4494
help='Write merge directive to this file; '
4495
'use - for stdout.',
4497
Option('mail-to', help='Mail the request to this address.',
4501
RegistryOption.from_kwargs('format',
4502
'Use the specified output format.',
4503
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4504
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4507
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4508
no_patch=False, revision=None, remember=False, output=None,
4509
format='4', mail_to=None, message=None, **kwargs):
4510
return self._run(submit_branch, revision, public_branch, remember,
4511
format, no_bundle, no_patch, output,
4512
kwargs.get('from', '.'), mail_to, message)
4514
def _run(self, submit_branch, revision, public_branch, remember, format,
4515
no_bundle, no_patch, output, from_, mail_to, message):
4516
from bzrlib.revision import NULL_REVISION
4517
branch = Branch.open_containing(from_)[0]
4519
outfile = cStringIO.StringIO()
4523
outfile = open(output, 'wb')
4524
# we may need to write data into branch's repository to calculate
4529
config = branch.get_config()
4531
mail_to = config.get_user_option('submit_to')
4532
mail_client = config.get_mail_client()
4533
if remember and submit_branch is None:
4534
raise errors.BzrCommandError(
4535
'--remember requires a branch to be specified.')
4536
stored_submit_branch = branch.get_submit_branch()
4537
remembered_submit_branch = None
4538
if submit_branch is None:
4539
submit_branch = stored_submit_branch
4540
remembered_submit_branch = "submit"
4542
if stored_submit_branch is None or remember:
4543
branch.set_submit_branch(submit_branch)
4544
if submit_branch is None:
4545
submit_branch = branch.get_parent()
4546
remembered_submit_branch = "parent"
4547
if submit_branch is None:
4548
raise errors.BzrCommandError('No submit branch known or'
4550
if remembered_submit_branch is not None:
4551
note('Using saved %s location "%s" to determine what '
4552
'changes to submit.', remembered_submit_branch,
4556
submit_config = Branch.open(submit_branch).get_config()
4557
mail_to = submit_config.get_user_option("child_submit_to")
4559
stored_public_branch = branch.get_public_branch()
4560
if public_branch is None:
4561
public_branch = stored_public_branch
4562
elif stored_public_branch is None or remember:
4563
branch.set_public_branch(public_branch)
4564
if no_bundle and public_branch is None:
4565
raise errors.BzrCommandError('No public branch specified or'
4567
base_revision_id = None
4569
if revision is not None:
4570
if len(revision) > 2:
4571
raise errors.BzrCommandError('bzr send takes '
4572
'at most two one revision identifiers')
4573
revision_id = revision[-1].as_revision_id(branch)
4574
if len(revision) == 2:
4575
base_revision_id = revision[0].as_revision_id(branch)
4576
if revision_id is None:
4577
revision_id = branch.last_revision()
4578
if revision_id == NULL_REVISION:
4579
raise errors.BzrCommandError('No revisions to submit.')
4581
directive = merge_directive.MergeDirective2.from_objects(
4582
branch.repository, revision_id, time.time(),
4583
osutils.local_time_offset(), submit_branch,
4584
public_branch=public_branch, include_patch=not no_patch,
4585
include_bundle=not no_bundle, message=message,
4586
base_revision_id=base_revision_id)
4587
elif format == '0.9':
4590
patch_type = 'bundle'
4592
raise errors.BzrCommandError('Format 0.9 does not'
4593
' permit bundle with no patch')
4599
directive = merge_directive.MergeDirective.from_objects(
4600
branch.repository, revision_id, time.time(),
4601
osutils.local_time_offset(), submit_branch,
4602
public_branch=public_branch, patch_type=patch_type,
4605
outfile.writelines(directive.to_lines())
4607
subject = '[MERGE] '
4608
if message is not None:
4611
revision = branch.repository.get_revision(revision_id)
4612
subject += revision.get_summary()
4613
basename = directive.get_disk_name(branch)
4614
mail_client.compose_merge_request(mail_to, subject,
4615
outfile.getvalue(), basename)
4622
class cmd_bundle_revisions(cmd_send):
4624
"""Create a merge-directive for submitting changes.
4626
A merge directive provides many things needed for requesting merges:
4628
* A machine-readable description of the merge to perform
4630
* An optional patch that is a preview of the changes requested
4632
* An optional bundle of revision data, so that the changes can be applied
4633
directly from the merge directive, without retrieving data from a
4636
If --no-bundle is specified, then public_branch is needed (and must be
4637
up-to-date), so that the receiver can perform the merge using the
4638
public_branch. The public_branch is always included if known, so that
4639
people can check it later.
4641
The submit branch defaults to the parent, but can be overridden. Both
4642
submit branch and public branch will be remembered if supplied.
4644
If a public_branch is known for the submit_branch, that public submit
4645
branch is used in the merge instructions. This means that a local mirror
4646
can be used as your actual submit branch, once you have set public_branch
4649
Two formats are currently supported: "4" uses revision bundle format 4 and
4650
merge directive format 2. It is significantly faster and smaller than
4651
older formats. It is compatible with Bazaar 0.19 and later. It is the
4652
default. "0.9" uses revision bundle format 0.9 and merge directive
4653
format 1. It is compatible with Bazaar 0.12 - 0.18.
4658
help='Do not include a bundle in the merge directive.'),
4659
Option('no-patch', help='Do not include a preview patch in the merge'
4662
help='Remember submit and public branch.'),
4664
help='Branch to generate the submission from, '
4665
'rather than the one containing the working directory.',
4668
Option('output', short_name='o', help='Write directive to this file.',
4671
RegistryOption.from_kwargs('format',
4672
'Use the specified output format.',
4673
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4674
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4676
aliases = ['bundle']
4678
_see_also = ['send', 'merge']
4682
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4683
no_patch=False, revision=None, remember=False, output=None,
4684
format='4', **kwargs):
4687
return self._run(submit_branch, revision, public_branch, remember,
4688
format, no_bundle, no_patch, output,
4689
kwargs.get('from', '.'), None, None)
4692
class cmd_tag(Command):
4693
"""Create, remove or modify a tag naming a revision.
4695
Tags give human-meaningful names to revisions. Commands that take a -r
4696
(--revision) option can be given -rtag:X, where X is any previously
4699
Tags are stored in the branch. Tags are copied from one branch to another
4700
along when you branch, push, pull or merge.
4702
It is an error to give a tag name that already exists unless you pass
4703
--force, in which case the tag is moved to point to the new revision.
4705
To rename a tag (change the name but keep it on the same revsion), run ``bzr
4706
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4709
_see_also = ['commit', 'tags']
4710
takes_args = ['tag_name']
4713
help='Delete this tag rather than placing it.',
4716
help='Branch in which to place the tag.',
4721
help='Replace existing tags.',
4726
def run(self, tag_name,
4732
branch, relpath = Branch.open_containing(directory)
4736
branch.tags.delete_tag(tag_name)
4737
self.outf.write('Deleted tag %s.\n' % tag_name)
4740
if len(revision) != 1:
4741
raise errors.BzrCommandError(
4742
"Tags can only be placed on a single revision, "
4744
revision_id = revision[0].as_revision_id(branch)
4746
revision_id = branch.last_revision()
4747
if (not force) and branch.tags.has_tag(tag_name):
4748
raise errors.TagAlreadyExists(tag_name)
4749
branch.tags.set_tag(tag_name, revision_id)
4750
self.outf.write('Created tag %s.\n' % tag_name)
4755
class cmd_tags(Command):
4758
This command shows a table of tag names and the revisions they reference.
4764
help='Branch whose tags should be displayed.',
4768
RegistryOption.from_kwargs('sort',
4769
'Sort tags by different criteria.', title='Sorting',
4770
alpha='Sort tags lexicographically (default).',
4771
time='Sort tags chronologically.',
4784
branch, relpath = Branch.open_containing(directory)
4786
tags = branch.tags.get_tag_dict().items()
4793
graph = branch.repository.get_graph()
4794
rev1, rev2 = _get_revision_range(revision, branch, self.name())
4795
revid1, revid2 = rev1.rev_id, rev2.rev_id
4796
# only show revisions between revid1 and revid2 (inclusive)
4797
tags = [(tag, revid) for tag, revid in tags if
4798
graph.is_between(revid, revid1, revid2)]
4803
elif sort == 'time':
4805
for tag, revid in tags:
4807
revobj = branch.repository.get_revision(revid)
4808
except errors.NoSuchRevision:
4809
timestamp = sys.maxint # place them at the end
4811
timestamp = revobj.timestamp
4812
timestamps[revid] = timestamp
4813
tags.sort(key=lambda x: timestamps[x[1]])
4815
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
4816
revno_map = branch.get_revision_id_to_revno_map()
4817
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4818
for tag, revid in tags ]
4819
for tag, revspec in tags:
4820
self.outf.write('%-20s %s\n' % (tag, revspec))
4823
class cmd_reconfigure(Command):
4824
"""Reconfigure the type of a bzr directory.
4826
A target configuration must be specified.
4828
For checkouts, the bind-to location will be auto-detected if not specified.
4829
The order of preference is
4830
1. For a lightweight checkout, the current bound location.
4831
2. For branches that used to be checkouts, the previously-bound location.
4832
3. The push location.
4833
4. The parent location.
4834
If none of these is available, --bind-to must be specified.
4837
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4838
takes_args = ['location?']
4839
takes_options = [RegistryOption.from_kwargs('target_type',
4840
title='Target type',
4841
help='The type to reconfigure the directory to.',
4842
value_switches=True, enum_switch=False,
4843
branch='Reconfigure to be an unbound branch '
4844
'with no working tree.',
4845
tree='Reconfigure to be an unbound branch '
4846
'with a working tree.',
4847
checkout='Reconfigure to be a bound branch '
4848
'with a working tree.',
4849
lightweight_checkout='Reconfigure to be a lightweight'
4850
' checkout (with no local history).',
4851
standalone='Reconfigure to be a standalone branch '
4852
'(i.e. stop using shared repository).',
4853
use_shared='Reconfigure to use a shared repository.'),
4854
Option('bind-to', help='Branch to bind checkout to.',
4857
help='Perform reconfiguration even if local changes'
4861
def run(self, location=None, target_type=None, bind_to=None, force=False):
4862
directory = bzrdir.BzrDir.open(location)
4863
if target_type is None:
4864
raise errors.BzrCommandError('No target configuration specified')
4865
elif target_type == 'branch':
4866
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4867
elif target_type == 'tree':
4868
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4869
elif target_type == 'checkout':
4870
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4872
elif target_type == 'lightweight-checkout':
4873
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4875
elif target_type == 'use-shared':
4876
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
4877
elif target_type == 'standalone':
4878
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
4879
reconfiguration.apply(force)
4882
class cmd_switch(Command):
4883
"""Set the branch of a checkout and update.
4885
For lightweight checkouts, this changes the branch being referenced.
4886
For heavyweight checkouts, this checks that there are no local commits
4887
versus the current bound branch, then it makes the local branch a mirror
4888
of the new location and binds to it.
4890
In both cases, the working tree is updated and uncommitted changes
4891
are merged. The user can commit or revert these as they desire.
4893
Pending merges need to be committed or reverted before using switch.
4895
The path to the branch to switch to can be specified relative to the parent
4896
directory of the current branch. For example, if you are currently in a
4897
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
4900
Bound branches use the nickname of its master branch unless it is set
4901
locally, in which case switching will update the the local nickname to be
4905
takes_args = ['to_location']
4906
takes_options = [Option('force',
4907
help='Switch even if local commits will be lost.')
4910
def run(self, to_location, force=False):
4911
from bzrlib import switch
4913
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4914
branch = control_dir.open_branch()
4916
to_branch = Branch.open(to_location)
4917
except errors.NotBranchError:
4918
this_branch = control_dir.open_branch()
4919
# This may be a heavy checkout, where we want the master branch
4920
this_url = this_branch.get_bound_location()
4921
# If not, use a local sibling
4922
if this_url is None:
4923
this_url = this_branch.base
4924
to_branch = Branch.open(
4925
urlutils.join(this_url, '..', to_location))
4926
switch.switch(control_dir, to_branch, force)
4927
if branch.get_config().has_explicit_nickname():
4928
branch = control_dir.open_branch() #get the new branch!
4929
branch.nick = to_branch.nick
4930
note('Switched to branch: %s',
4931
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4934
class cmd_hooks(Command):
4935
"""Show a branch's currently registered hooks.
4939
takes_args = ['path?']
4941
def run(self, path=None):
4944
branch_hooks = Branch.open(path).hooks
4945
for hook_type in branch_hooks:
4946
hooks = branch_hooks[hook_type]
4947
self.outf.write("%s:\n" % (hook_type,))
4950
self.outf.write(" %s\n" %
4951
(branch_hooks.get_hook_name(hook),))
4953
self.outf.write(" <no hooks installed>\n")
4956
class cmd_shelve(Command):
4957
"""Temporarily set aside some changes from the current tree.
4959
Shelve allows you to temporarily put changes you've made "on the shelf",
4960
ie. out of the way, until a later time when you can bring them back from
4961
the shelf with the 'unshelve' command.
4963
If shelve --list is specified, previously-shelved changes are listed.
4965
Shelve is intended to help separate several sets of changes that have
4966
been inappropriately mingled. If you just want to get rid of all changes
4967
and you don't need to restore them later, use revert. If you want to
4968
shelve all text changes at once, use shelve --all.
4970
If filenames are specified, only the changes to those files will be
4971
shelved. Other files will be left untouched.
4973
If a revision is specified, changes since that revision will be shelved.
4975
You can put multiple items on the shelf, and by default, 'unshelve' will
4976
restore the most recently shelved changes.
4979
takes_args = ['file*']
4983
Option('all', help='Shelve all changes.'),
4985
RegistryOption('writer', 'Method to use for writing diffs.',
4986
bzrlib.option.diff_writer_registry,
4987
value_switches=True, enum_switch=False),
4989
Option('list', help='List shelved changes.'),
4991
_see_also = ['unshelve']
4993
def run(self, revision=None, all=False, file_list=None, message=None,
4994
writer=None, list=False):
4996
return self.run_for_list()
4997
from bzrlib.shelf_ui import Shelver
4999
writer = bzrlib.option.diff_writer_registry.get()
5001
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5003
except errors.UserAbort:
5006
def run_for_list(self):
5007
tree = WorkingTree.open_containing('.')[0]
5010
manager = tree.get_shelf_manager()
5011
shelves = manager.active_shelves()
5012
if len(shelves) == 0:
5013
note('No shelved changes.')
5015
for shelf_id in reversed(shelves):
5016
message = manager.get_metadata(shelf_id).get('message')
5018
message = '<no message>'
5019
self.outf.write('%3d: %s\n' % (shelf_id, message))
5025
class cmd_unshelve(Command):
5026
"""Restore shelved changes.
5028
By default, the most recently shelved changes are restored. However if you
5029
specify a patch by name those changes will be restored instead. This
5030
works best when the changes don't depend on each other.
5033
takes_args = ['shelf_id?']
5035
RegistryOption.from_kwargs(
5036
'action', help="The action to perform.",
5037
enum_switch=False, value_switches=True,
5038
apply="Apply changes and remove from the shelf.",
5039
dry_run="Show changes, but do not apply or remove them.",
5040
delete_only="Delete changes without applying them."
5043
_see_also = ['shelve']
5045
def run(self, shelf_id=None, action='apply'):
5046
from bzrlib.shelf_ui import Unshelver
5047
Unshelver.from_args(shelf_id, action).run()
5050
def _create_prefix(cur_transport):
5051
needed = [cur_transport]
5052
# Recurse upwards until we can create a directory successfully
5054
new_transport = cur_transport.clone('..')
5055
if new_transport.base == cur_transport.base:
5056
raise errors.BzrCommandError(
5057
"Failed to create path prefix for %s."
5058
% cur_transport.base)
5060
new_transport.mkdir('.')
5061
except errors.NoSuchFile:
5062
needed.append(new_transport)
5063
cur_transport = new_transport
5066
# Now we only need to create child directories
5068
cur_transport = needed.pop()
5069
cur_transport.ensure_base()
5072
# these get imported and then picked up by the scan for cmd_*
5073
# TODO: Some more consistent way to split command definitions across files;
5074
# we do need to load at least some information about them to know of
5075
# aliases. ideally we would avoid loading the implementation until the
5076
# details were needed.
5077
from bzrlib.cmd_version_info import cmd_version_info
5078
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5079
from bzrlib.bundle.commands import (
5082
from bzrlib.sign_my_commits import cmd_sign_my_commits
5083
from bzrlib.weave_commands import cmd_versionedfile_list, \
5084
cmd_weave_plan_merge, cmd_weave_merge_text