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,
51
from bzrlib.branch import Branch
52
from bzrlib.conflicts import ConflictList
53
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
54
from bzrlib.smtp_connection import SMTPConnection
55
from bzrlib.workingtree import WorkingTree
58
from bzrlib.commands import Command, display_command
59
from bzrlib.option import (
66
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
69
def tree_files(file_list, default_branch=u'.', canonicalize=True,
72
return internal_tree_files(file_list, default_branch, canonicalize,
74
except errors.FileInWrongBranch, e:
75
raise errors.BzrCommandError("%s is not in the same branch as %s" %
76
(e.path, file_list[0]))
79
def tree_files_for_add(file_list):
80
"""Add handles files a bit differently so it a custom implementation."""
82
tree = WorkingTree.open_containing(file_list[0])[0]
83
if tree.supports_views():
84
view_files = tree.views.lookup_view()
85
for filename in file_list:
86
if not osutils.is_inside_any(view_files, filename):
87
raise errors.FileOutsideView(filename, view_files)
89
tree = WorkingTree.open_containing(u'.')[0]
90
if tree.supports_views():
91
view_files = tree.views.lookup_view()
93
file_list = view_files
94
view_str = views.view_display_str(view_files)
95
note("ignoring files outside view: %s" % view_str)
96
return tree, file_list
99
def _get_one_revision(command_name, revisions):
100
if revisions is None:
102
if len(revisions) != 1:
103
raise errors.BzrCommandError(
104
'bzr %s --revision takes exactly one revision identifier' % (
109
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
112
if revisions is None:
114
rev_tree = tree.basis_tree()
116
rev_tree = branch.basis_tree()
118
revision = _get_one_revision(command_name, revisions)
119
rev_tree = revision.as_tree(branch)
123
# XXX: Bad function name; should possibly also be a class method of
124
# WorkingTree rather than a function.
125
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
127
"""Convert command-line paths to a WorkingTree and relative paths.
129
This is typically used for command-line processors that take one or
130
more filenames, and infer the workingtree that contains them.
132
The filenames given are not required to exist.
134
:param file_list: Filenames to convert.
136
:param default_branch: Fallback tree path to use if file_list is empty or
139
:param apply_view: if True and a view is set, apply it or check that
140
specified files are within it
142
:return: workingtree, [relative_paths]
144
if file_list is None or len(file_list) == 0:
145
tree = WorkingTree.open_containing(default_branch)[0]
146
if tree.supports_views() and apply_view:
147
view_files = tree.views.lookup_view()
149
file_list = view_files
150
view_str = views.view_display_str(view_files)
151
note("ignoring files outside view: %s" % view_str)
152
return tree, file_list
153
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
154
return tree, safe_relpath_files(tree, file_list, canonicalize,
155
apply_view=apply_view)
158
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
159
"""Convert file_list into a list of relpaths in tree.
161
:param tree: A tree to operate on.
162
:param file_list: A list of user provided paths or None.
163
:param apply_view: if True and a view is set, apply it or check that
164
specified files are within it
165
:return: A list of relative paths.
166
:raises errors.PathNotChild: When a provided path is in a different tree
169
if file_list is None:
171
if tree.supports_views() and apply_view:
172
view_files = tree.views.lookup_view()
176
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
177
# doesn't - fix that up here before we enter the loop.
179
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
182
for filename in file_list:
184
relpath = fixer(osutils.dereference_path(filename))
185
if view_files and not osutils.is_inside_any(view_files, relpath):
186
raise errors.FileOutsideView(filename, view_files)
187
new_list.append(relpath)
188
except errors.PathNotChild:
189
raise errors.FileInWrongBranch(tree.branch, filename)
193
def _get_view_info_for_change_reporter(tree):
194
"""Get the view information from a tree for change reporting."""
197
current_view = tree.views.get_view_info()[0]
198
if current_view is not None:
199
view_info = (current_view, tree.views.lookup_view())
200
except errors.ViewsNotSupported:
205
# TODO: Make sure no commands unconditionally use the working directory as a
206
# branch. If a filename argument is used, the first of them should be used to
207
# specify the branch. (Perhaps this can be factored out into some kind of
208
# Argument class, representing a file in a branch, where the first occurrence
211
class cmd_status(Command):
212
"""Display status summary.
214
This reports on versioned and unknown files, reporting them
215
grouped by state. Possible states are:
218
Versioned in the working copy but not in the previous revision.
221
Versioned in the previous revision but removed or deleted
225
Path of this file changed from the previous revision;
226
the text may also have changed. This includes files whose
227
parent directory was renamed.
230
Text has changed since the previous revision.
233
File kind has been changed (e.g. from file to directory).
236
Not versioned and not matching an ignore pattern.
238
To see ignored files use 'bzr ignored'. For details on the
239
changes to file texts, use 'bzr diff'.
241
Note that --short or -S gives status flags for each item, similar
242
to Subversion's status command. To get output similar to svn -q,
245
If no arguments are specified, the status of the entire working
246
directory is shown. Otherwise, only the status of the specified
247
files or directories is reported. If a directory is given, status
248
is reported for everything inside that directory.
250
Before merges are committed, the pending merge tip revisions are
251
shown. To see all pending merge revisions, use the -v option.
252
To skip the display of pending merge information altogether, use
253
the no-pending option or specify a file/directory.
255
If a revision argument is given, the status is calculated against
256
that revision, or between two revisions if two are provided.
259
# TODO: --no-recurse, --recurse options
261
takes_args = ['file*']
262
takes_options = ['show-ids', 'revision', 'change', 'verbose',
263
Option('short', help='Use short status indicators.',
265
Option('versioned', help='Only show versioned files.',
267
Option('no-pending', help='Don\'t show pending merges.',
270
aliases = ['st', 'stat']
272
encoding_type = 'replace'
273
_see_also = ['diff', 'revert', 'status-flags']
276
def run(self, show_ids=False, file_list=None, revision=None, short=False,
277
versioned=False, no_pending=False, verbose=False):
278
from bzrlib.status import show_tree_status
280
if revision and len(revision) > 2:
281
raise errors.BzrCommandError('bzr status --revision takes exactly'
282
' one or two revision specifiers')
284
tree, relfile_list = tree_files(file_list)
285
# Avoid asking for specific files when that is not needed.
286
if relfile_list == ['']:
288
# Don't disable pending merges for full trees other than '.'.
289
if file_list == ['.']:
291
# A specific path within a tree was given.
292
elif relfile_list is not None:
294
show_tree_status(tree, show_ids=show_ids,
295
specific_files=relfile_list, revision=revision,
296
to_file=self.outf, short=short, versioned=versioned,
297
show_pending=(not no_pending), verbose=verbose)
300
class cmd_cat_revision(Command):
301
"""Write out metadata for a revision.
303
The revision to print can either be specified by a specific
304
revision identifier, or you can use --revision.
308
takes_args = ['revision_id?']
309
takes_options = ['revision']
310
# cat-revision is more for frontends so should be exact
314
def run(self, revision_id=None, revision=None):
315
if revision_id is not None and revision is not None:
316
raise errors.BzrCommandError('You can only supply one of'
317
' revision_id or --revision')
318
if revision_id is None and revision is None:
319
raise errors.BzrCommandError('You must supply either'
320
' --revision or a revision_id')
321
b = WorkingTree.open_containing(u'.')[0].branch
323
# TODO: jam 20060112 should cat-revision always output utf-8?
324
if revision_id is not None:
325
revision_id = osutils.safe_revision_id(revision_id, warn=False)
327
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
328
except errors.NoSuchRevision:
329
msg = "The repository %s contains no revision %s." % (b.repository.base,
331
raise errors.BzrCommandError(msg)
332
elif revision is not None:
335
raise errors.BzrCommandError('You cannot specify a NULL'
337
rev_id = rev.as_revision_id(b)
338
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
341
class cmd_dump_btree(Command):
342
"""Dump the contents of a btree index file to stdout.
344
PATH is a btree index file, it can be any URL. This includes things like
345
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
347
By default, the tuples stored in the index file will be displayed. With
348
--raw, we will uncompress the pages, but otherwise display the raw bytes
352
# TODO: Do we want to dump the internal nodes as well?
353
# TODO: It would be nice to be able to dump the un-parsed information,
354
# rather than only going through iter_all_entries. However, this is
355
# good enough for a start
357
encoding_type = 'exact'
358
takes_args = ['path']
359
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
360
' rather than the parsed tuples.'),
363
def run(self, path, raw=False):
364
dirname, basename = osutils.split(path)
365
t = transport.get_transport(dirname)
367
self._dump_raw_bytes(t, basename)
369
self._dump_entries(t, basename)
371
def _get_index_and_bytes(self, trans, basename):
372
"""Create a BTreeGraphIndex and raw bytes."""
373
bt = btree_index.BTreeGraphIndex(trans, basename, None)
374
bytes = trans.get_bytes(basename)
375
bt._file = cStringIO.StringIO(bytes)
376
bt._size = len(bytes)
379
def _dump_raw_bytes(self, trans, basename):
382
# We need to parse at least the root node.
383
# This is because the first page of every row starts with an
384
# uncompressed header.
385
bt, bytes = self._get_index_and_bytes(trans, basename)
386
for page_idx, page_start in enumerate(xrange(0, len(bytes),
387
btree_index._PAGE_SIZE)):
388
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
389
page_bytes = bytes[page_start:page_end]
391
self.outf.write('Root node:\n')
392
header_end, data = bt._parse_header_from_bytes(page_bytes)
393
self.outf.write(page_bytes[:header_end])
395
self.outf.write('\nPage %d\n' % (page_idx,))
396
decomp_bytes = zlib.decompress(page_bytes)
397
self.outf.write(decomp_bytes)
398
self.outf.write('\n')
400
def _dump_entries(self, trans, basename):
402
st = trans.stat(basename)
403
except errors.TransportNotPossible:
404
# We can't stat, so we'll fake it because we have to do the 'get()'
406
bt, _ = self._get_index_and_bytes(trans, basename)
408
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
409
for node in bt.iter_all_entries():
410
# Node is made up of:
411
# (index, key, value, [references])
412
self.outf.write('%s\n' % (node[1:],))
415
class cmd_remove_tree(Command):
416
"""Remove the working tree from a given branch/checkout.
418
Since a lightweight checkout is little more than a working tree
419
this will refuse to run against one.
421
To re-create the working tree, use "bzr checkout".
423
_see_also = ['checkout', 'working-trees']
424
takes_args = ['location?']
427
help='Remove the working tree even if it has '
428
'uncommitted changes.'),
431
def run(self, location='.', force=False):
432
d = bzrdir.BzrDir.open(location)
435
working = d.open_workingtree()
436
except errors.NoWorkingTree:
437
raise errors.BzrCommandError("No working tree to remove")
438
except errors.NotLocalUrl:
439
raise errors.BzrCommandError("You cannot remove the working tree of a "
442
changes = working.changes_from(working.basis_tree())
443
if changes.has_changed():
444
raise errors.UncommittedChanges(working)
446
working_path = working.bzrdir.root_transport.base
447
branch_path = working.branch.bzrdir.root_transport.base
448
if working_path != branch_path:
449
raise errors.BzrCommandError("You cannot remove the working tree from "
450
"a lightweight checkout")
452
d.destroy_workingtree()
455
class cmd_revno(Command):
456
"""Show current revision number.
458
This is equal to the number of revisions on this branch.
462
takes_args = ['location?']
465
def run(self, location=u'.'):
466
self.outf.write(str(Branch.open_containing(location)[0].revno()))
467
self.outf.write('\n')
470
class cmd_revision_info(Command):
471
"""Show revision number and revision id for a given revision identifier.
474
takes_args = ['revision_info*']
478
help='Branch to examine, '
479
'rather than the one containing the working directory.',
486
def run(self, revision=None, directory=u'.', revision_info_list=[]):
489
if revision is not None:
490
revs.extend(revision)
491
if revision_info_list is not None:
492
for rev in revision_info_list:
493
revs.append(RevisionSpec.from_string(rev))
495
b = Branch.open_containing(directory)[0]
498
revs.append(RevisionSpec.from_string('-1'))
501
revision_id = rev.as_revision_id(b)
503
revno = '%4d' % (b.revision_id_to_revno(revision_id))
504
except errors.NoSuchRevision:
505
dotted_map = b.get_revision_id_to_revno_map()
506
revno = '.'.join(str(i) for i in dotted_map[revision_id])
507
print '%s %s' % (revno, revision_id)
510
class cmd_add(Command):
511
"""Add specified files or directories.
513
In non-recursive mode, all the named items are added, regardless
514
of whether they were previously ignored. A warning is given if
515
any of the named files are already versioned.
517
In recursive mode (the default), files are treated the same way
518
but the behaviour for directories is different. Directories that
519
are already versioned do not give a warning. All directories,
520
whether already versioned or not, are searched for files or
521
subdirectories that are neither versioned or ignored, and these
522
are added. This search proceeds recursively into versioned
523
directories. If no names are given '.' is assumed.
525
Therefore simply saying 'bzr add' will version all files that
526
are currently unknown.
528
Adding a file whose parent directory is not versioned will
529
implicitly add the parent, and so on up to the root. This means
530
you should never need to explicitly add a directory, they'll just
531
get added when you add a file in the directory.
533
--dry-run will show which files would be added, but not actually
536
--file-ids-from will try to use the file ids from the supplied path.
537
It looks up ids trying to find a matching parent directory with the
538
same filename, and then by pure path. This option is rarely needed
539
but can be useful when adding the same logical file into two
540
branches that will be merged later (without showing the two different
541
adds as a conflict). It is also useful when merging another project
542
into a subdirectory of this one.
544
takes_args = ['file*']
547
help="Don't recursively add the contents of directories."),
549
help="Show what would be done, but don't actually do anything."),
551
Option('file-ids-from',
553
help='Lookup file ids from this tree.'),
555
encoding_type = 'replace'
556
_see_also = ['remove']
558
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
563
if file_ids_from is not None:
565
base_tree, base_path = WorkingTree.open_containing(
567
except errors.NoWorkingTree:
568
base_branch, base_path = Branch.open_containing(
570
base_tree = base_branch.basis_tree()
572
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
573
to_file=self.outf, should_print=(not is_quiet()))
575
action = bzrlib.add.AddAction(to_file=self.outf,
576
should_print=(not is_quiet()))
579
base_tree.lock_read()
581
file_list = self._maybe_expand_globs(file_list)
582
tree, file_list = tree_files_for_add(file_list)
583
added, ignored = tree.smart_add(file_list, not
584
no_recurse, action=action, save=not dry_run)
586
if base_tree is not None:
588
if not is_quiet() and len(added) > 0:
589
self.outf.write('add completed\n')
592
for glob in sorted(ignored.keys()):
593
for path in ignored[glob]:
594
self.outf.write("ignored %s matching \"%s\"\n"
598
for glob, paths in ignored.items():
599
match_len += len(paths)
600
self.outf.write("ignored %d file(s).\n" % match_len)
601
self.outf.write("If you wish to add some of these files,"
602
" please add them by name.\n")
605
class cmd_mkdir(Command):
606
"""Create a new versioned directory.
608
This is equivalent to creating the directory and then adding it.
611
takes_args = ['dir+']
612
encoding_type = 'replace'
614
def run(self, dir_list):
617
wt, dd = WorkingTree.open_containing(d)
619
self.outf.write('added %s\n' % d)
622
class cmd_relpath(Command):
623
"""Show path of a file relative to root"""
625
takes_args = ['filename']
629
def run(self, filename):
630
# TODO: jam 20050106 Can relpath return a munged path if
631
# sys.stdout encoding cannot represent it?
632
tree, relpath = WorkingTree.open_containing(filename)
633
self.outf.write(relpath)
634
self.outf.write('\n')
637
class cmd_inventory(Command):
638
"""Show inventory of the current working copy or a revision.
640
It is possible to limit the output to a particular entry
641
type using the --kind option. For example: --kind file.
643
It is also possible to restrict the list of files to a specific
644
set. For example: bzr inventory --show-ids this/file
653
help='List entries of a particular kind: file, directory, symlink.',
656
takes_args = ['file*']
659
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
660
if kind and kind not in ['file', 'directory', 'symlink']:
661
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
663
revision = _get_one_revision('inventory', revision)
664
work_tree, file_list = tree_files(file_list)
665
work_tree.lock_read()
667
if revision is not None:
668
tree = revision.as_tree(work_tree.branch)
670
extra_trees = [work_tree]
676
if file_list is not None:
677
file_ids = tree.paths2ids(file_list, trees=extra_trees,
678
require_versioned=True)
679
# find_ids_across_trees may include some paths that don't
681
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
682
for file_id in file_ids if file_id in tree)
684
entries = tree.inventory.entries()
687
if tree is not work_tree:
690
for path, entry in entries:
691
if kind and kind != entry.kind:
694
self.outf.write('%-50s %s\n' % (path, entry.file_id))
696
self.outf.write(path)
697
self.outf.write('\n')
700
class cmd_mv(Command):
701
"""Move or rename a file.
704
bzr mv OLDNAME NEWNAME
706
bzr mv SOURCE... DESTINATION
708
If the last argument is a versioned directory, all the other names
709
are moved into it. Otherwise, there must be exactly two arguments
710
and the file is changed to a new name.
712
If OLDNAME does not exist on the filesystem but is versioned and
713
NEWNAME does exist on the filesystem but is not versioned, mv
714
assumes that the file has been manually moved and only updates
715
its internal inventory to reflect that change.
716
The same is valid when moving many SOURCE files to a DESTINATION.
718
Files cannot be moved between branches.
721
takes_args = ['names*']
722
takes_options = [Option("after", help="Move only the bzr identifier"
723
" of the file, because the file has already been moved."),
725
aliases = ['move', 'rename']
726
encoding_type = 'replace'
728
def run(self, names_list, after=False):
729
if names_list is None:
732
if len(names_list) < 2:
733
raise errors.BzrCommandError("missing file argument")
734
tree, rel_names = tree_files(names_list, canonicalize=False)
737
self._run(tree, names_list, rel_names, after)
741
def _run(self, tree, names_list, rel_names, after):
742
into_existing = osutils.isdir(names_list[-1])
743
if into_existing and len(names_list) == 2:
745
# a. case-insensitive filesystem and change case of dir
746
# b. move directory after the fact (if the source used to be
747
# a directory, but now doesn't exist in the working tree
748
# and the target is an existing directory, just rename it)
749
if (not tree.case_sensitive
750
and rel_names[0].lower() == rel_names[1].lower()):
751
into_existing = False
754
# 'fix' the case of a potential 'from'
755
from_id = tree.path2id(
756
tree.get_canonical_inventory_path(rel_names[0]))
757
if (not osutils.lexists(names_list[0]) and
758
from_id and inv.get_file_kind(from_id) == "directory"):
759
into_existing = False
762
# move into existing directory
763
# All entries reference existing inventory items, so fix them up
764
# for cicp file-systems.
765
rel_names = tree.get_canonical_inventory_paths(rel_names)
766
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
767
self.outf.write("%s => %s\n" % pair)
769
if len(names_list) != 2:
770
raise errors.BzrCommandError('to mv multiple files the'
771
' destination must be a versioned'
774
# for cicp file-systems: the src references an existing inventory
776
src = tree.get_canonical_inventory_path(rel_names[0])
777
# Find the canonical version of the destination: In all cases, the
778
# parent of the target must be in the inventory, so we fetch the
779
# canonical version from there (we do not always *use* the
780
# canonicalized tail portion - we may be attempting to rename the
782
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
783
dest_parent = osutils.dirname(canon_dest)
784
spec_tail = osutils.basename(rel_names[1])
785
# For a CICP file-system, we need to avoid creating 2 inventory
786
# entries that differ only by case. So regardless of the case
787
# we *want* to use (ie, specified by the user or the file-system),
788
# we must always choose to use the case of any existing inventory
789
# items. The only exception to this is when we are attempting a
790
# case-only rename (ie, canonical versions of src and dest are
792
dest_id = tree.path2id(canon_dest)
793
if dest_id is None or tree.path2id(src) == dest_id:
794
# No existing item we care about, so work out what case we
795
# are actually going to use.
797
# If 'after' is specified, the tail must refer to a file on disk.
799
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
801
# pathjoin with an empty tail adds a slash, which breaks
803
dest_parent_fq = tree.basedir
805
dest_tail = osutils.canonical_relpath(
807
osutils.pathjoin(dest_parent_fq, spec_tail))
809
# not 'after', so case as specified is used
810
dest_tail = spec_tail
812
# Use the existing item so 'mv' fails with AlreadyVersioned.
813
dest_tail = os.path.basename(canon_dest)
814
dest = osutils.pathjoin(dest_parent, dest_tail)
815
mutter("attempting to move %s => %s", src, dest)
816
tree.rename_one(src, dest, after=after)
817
self.outf.write("%s => %s\n" % (src, dest))
820
class cmd_pull(Command):
821
"""Turn this branch into a mirror of another branch.
823
This command only works on branches that have not diverged. Branches are
824
considered diverged if the destination branch's most recent commit is one
825
that has not been merged (directly or indirectly) into the parent.
827
If branches have diverged, you can use 'bzr merge' to integrate the changes
828
from one into the other. Once one branch has merged, the other should
829
be able to pull it again.
831
If you want to forget your local changes and just update your branch to
832
match the remote one, use pull --overwrite.
834
If there is no default location set, the first pull will set it. After
835
that, you can omit the location to use the default. To change the
836
default, use --remember. The value will only be saved if the remote
837
location can be accessed.
839
Note: The location can be specified either in the form of a branch,
840
or in the form of a path to a file containing a merge directive generated
844
_see_also = ['push', 'update', 'status-flags']
845
takes_options = ['remember', 'overwrite', 'revision',
846
custom_help('verbose',
847
help='Show logs of pulled revisions.'),
849
help='Branch to pull into, '
850
'rather than the one containing the working directory.',
855
takes_args = ['location?']
856
encoding_type = 'replace'
858
def run(self, location=None, remember=False, overwrite=False,
859
revision=None, verbose=False,
861
# FIXME: too much stuff is in the command class
864
if directory is None:
867
tree_to = WorkingTree.open_containing(directory)[0]
868
branch_to = tree_to.branch
869
except errors.NoWorkingTree:
871
branch_to = Branch.open_containing(directory)[0]
873
possible_transports = []
874
if location is not None:
876
mergeable = bundle.read_mergeable_from_url(location,
877
possible_transports=possible_transports)
878
except errors.NotABundle:
881
stored_loc = branch_to.get_parent()
883
if stored_loc is None:
884
raise errors.BzrCommandError("No pull location known or"
887
display_url = urlutils.unescape_for_display(stored_loc,
890
self.outf.write("Using saved parent location: %s\n" % display_url)
891
location = stored_loc
893
revision = _get_one_revision('pull', revision)
894
if mergeable is not None:
895
if revision is not None:
896
raise errors.BzrCommandError(
897
'Cannot use -r with merge directives or bundles')
898
mergeable.install_revisions(branch_to.repository)
899
base_revision_id, revision_id, verified = \
900
mergeable.get_merge_request(branch_to.repository)
901
branch_from = branch_to
903
branch_from = Branch.open(location,
904
possible_transports=possible_transports)
906
if branch_to.get_parent() is None or remember:
907
branch_to.set_parent(branch_from.base)
909
if revision is not None:
910
revision_id = revision.as_revision_id(branch_from)
912
branch_to.lock_write()
914
if tree_to is not None:
915
view_info = _get_view_info_for_change_reporter(tree_to)
916
change_reporter = delta._ChangeReporter(
917
unversioned_filter=tree_to.is_ignored, view_info=view_info)
918
result = tree_to.pull(branch_from, overwrite, revision_id,
920
possible_transports=possible_transports)
922
result = branch_to.pull(branch_from, overwrite, revision_id)
924
result.report(self.outf)
925
if verbose and result.old_revid != result.new_revid:
926
log.show_branch_change(branch_to, self.outf, result.old_revno,
932
class cmd_push(Command):
933
"""Update a mirror of this branch.
935
The target branch will not have its working tree populated because this
936
is both expensive, and is not supported on remote file systems.
938
Some smart servers or protocols *may* put the working tree in place in
941
This command only works on branches that have not diverged. Branches are
942
considered diverged if the destination branch's most recent commit is one
943
that has not been merged (directly or indirectly) by the source branch.
945
If branches have diverged, you can use 'bzr push --overwrite' to replace
946
the other branch completely, discarding its unmerged changes.
948
If you want to ensure you have the different changes in the other branch,
949
do a merge (see bzr help merge) from the other branch, and commit that.
950
After that you will be able to do a push without '--overwrite'.
952
If there is no default push location set, the first push will set it.
953
After that, you can omit the location to use the default. To change the
954
default, use --remember. The value will only be saved if the remote
955
location can be accessed.
958
_see_also = ['pull', 'update', 'working-trees']
959
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
960
Option('create-prefix',
961
help='Create the path leading up to the branch '
962
'if it does not already exist.'),
964
help='Branch to push from, '
965
'rather than the one containing the working directory.',
969
Option('use-existing-dir',
970
help='By default push will fail if the target'
971
' directory exists, but does not already'
972
' have a control directory. This flag will'
973
' allow push to proceed.'),
975
help='Create a stacked branch that references the public location '
976
'of the parent branch.'),
978
help='Create a stacked branch that refers to another branch '
979
'for the commit history. Only the work not present in the '
980
'referenced branch is included in the branch created.',
983
takes_args = ['location?']
984
encoding_type = 'replace'
986
def run(self, location=None, remember=False, overwrite=False,
987
create_prefix=False, verbose=False, revision=None,
988
use_existing_dir=False, directory=None, stacked_on=None,
990
from bzrlib.push import _show_push_branch
992
# Get the source branch and revision_id
993
if directory is None:
995
br_from = Branch.open_containing(directory)[0]
996
revision = _get_one_revision('push', revision)
997
if revision is not None:
998
revision_id = revision.in_history(br_from).rev_id
1000
revision_id = br_from.last_revision()
1002
# Get the stacked_on branch, if any
1003
if stacked_on is not None:
1004
stacked_on = urlutils.normalize_url(stacked_on)
1006
parent_url = br_from.get_parent()
1008
parent = Branch.open(parent_url)
1009
stacked_on = parent.get_public_branch()
1011
# I considered excluding non-http url's here, thus forcing
1012
# 'public' branches only, but that only works for some
1013
# users, so it's best to just depend on the user spotting an
1014
# error by the feedback given to them. RBC 20080227.
1015
stacked_on = parent_url
1017
raise errors.BzrCommandError(
1018
"Could not determine branch to refer to.")
1020
# Get the destination location
1021
if location is None:
1022
stored_loc = br_from.get_push_location()
1023
if stored_loc is None:
1024
raise errors.BzrCommandError(
1025
"No push location known or specified.")
1027
display_url = urlutils.unescape_for_display(stored_loc,
1029
self.outf.write("Using saved push location: %s\n" % display_url)
1030
location = stored_loc
1032
_show_push_branch(br_from, revision_id, location, self.outf,
1033
verbose=verbose, overwrite=overwrite, remember=remember,
1034
stacked_on=stacked_on, create_prefix=create_prefix,
1035
use_existing_dir=use_existing_dir)
1038
class cmd_branch(Command):
1039
"""Create a new copy of a branch.
1041
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1042
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1043
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
1044
is derived from the FROM_LOCATION by stripping a leading scheme or drive
1045
identifier, if any. For example, "branch lp:foo-bar" will attempt to
1048
To retrieve the branch as of a particular revision, supply the --revision
1049
parameter, as in "branch foo/bar -r 5".
1052
_see_also = ['checkout']
1053
takes_args = ['from_location', 'to_location?']
1054
takes_options = ['revision', Option('hardlink',
1055
help='Hard-link working tree files where possible.'),
1057
help="Create a branch without a working-tree."),
1059
help='Create a stacked branch referring to the source branch. '
1060
'The new branch will depend on the availability of the source '
1061
'branch for all operations.'),
1062
Option('standalone',
1063
help='Do not use a shared repository, even if available.'),
1065
aliases = ['get', 'clone']
1067
def run(self, from_location, to_location=None, revision=None,
1068
hardlink=False, stacked=False, standalone=False, no_tree=False):
1069
from bzrlib.tag import _merge_tags_if_possible
1071
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1073
revision = _get_one_revision('branch', revision)
1076
if revision is not None:
1077
revision_id = revision.as_revision_id(br_from)
1079
# FIXME - wt.last_revision, fallback to branch, fall back to
1080
# None or perhaps NULL_REVISION to mean copy nothing
1082
revision_id = br_from.last_revision()
1083
if to_location is None:
1084
to_location = urlutils.derive_to_location(from_location)
1085
to_transport = transport.get_transport(to_location)
1087
to_transport.mkdir('.')
1088
except errors.FileExists:
1089
raise errors.BzrCommandError('Target directory "%s" already'
1090
' exists.' % to_location)
1091
except errors.NoSuchFile:
1092
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1095
# preserve whatever source format we have.
1096
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1097
possible_transports=[to_transport],
1098
accelerator_tree=accelerator_tree,
1099
hardlink=hardlink, stacked=stacked,
1100
force_new_repo=standalone,
1101
create_tree_if_local=not no_tree,
1102
source_branch=br_from)
1103
branch = dir.open_branch()
1104
except errors.NoSuchRevision:
1105
to_transport.delete_tree('.')
1106
msg = "The branch %s has no revision %s." % (from_location,
1108
raise errors.BzrCommandError(msg)
1109
_merge_tags_if_possible(br_from, branch)
1110
# If the source branch is stacked, the new branch may
1111
# be stacked whether we asked for that explicitly or not.
1112
# We therefore need a try/except here and not just 'if stacked:'
1114
note('Created new stacked branch referring to %s.' %
1115
branch.get_stacked_on_url())
1116
except (errors.NotStacked, errors.UnstackableBranchFormat,
1117
errors.UnstackableRepositoryFormat), e:
1118
note('Branched %d revision(s).' % branch.revno())
1123
class cmd_checkout(Command):
1124
"""Create a new checkout of an existing branch.
1126
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1127
the branch found in '.'. This is useful if you have removed the working tree
1128
or if it was never created - i.e. if you pushed the branch to its current
1129
location using SFTP.
1131
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1132
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1133
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1134
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
1135
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
1138
To retrieve the branch as of a particular revision, supply the --revision
1139
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
1140
out of date [so you cannot commit] but it may be useful (i.e. to examine old
1144
_see_also = ['checkouts', 'branch']
1145
takes_args = ['branch_location?', 'to_location?']
1146
takes_options = ['revision',
1147
Option('lightweight',
1148
help="Perform a lightweight checkout. Lightweight "
1149
"checkouts depend on access to the branch for "
1150
"every operation. Normal checkouts can perform "
1151
"common operations like diff and status without "
1152
"such access, and also support local commits."
1154
Option('files-from', type=str,
1155
help="Get file contents from this tree."),
1157
help='Hard-link working tree files where possible.'
1162
def run(self, branch_location=None, to_location=None, revision=None,
1163
lightweight=False, files_from=None, hardlink=False):
1164
if branch_location is None:
1165
branch_location = osutils.getcwd()
1166
to_location = branch_location
1167
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1169
revision = _get_one_revision('checkout', revision)
1170
if files_from is not None:
1171
accelerator_tree = WorkingTree.open(files_from)
1172
if revision is not None:
1173
revision_id = revision.as_revision_id(source)
1176
if to_location is None:
1177
to_location = urlutils.derive_to_location(branch_location)
1178
# if the source and to_location are the same,
1179
# and there is no working tree,
1180
# then reconstitute a branch
1181
if (osutils.abspath(to_location) ==
1182
osutils.abspath(branch_location)):
1184
source.bzrdir.open_workingtree()
1185
except errors.NoWorkingTree:
1186
source.bzrdir.create_workingtree(revision_id)
1188
source.create_checkout(to_location, revision_id, lightweight,
1189
accelerator_tree, hardlink)
1192
class cmd_renames(Command):
1193
"""Show list of renamed files.
1195
# TODO: Option to show renames between two historical versions.
1197
# TODO: Only show renames under dir, rather than in the whole branch.
1198
_see_also = ['status']
1199
takes_args = ['dir?']
1202
def run(self, dir=u'.'):
1203
tree = WorkingTree.open_containing(dir)[0]
1206
new_inv = tree.inventory
1207
old_tree = tree.basis_tree()
1208
old_tree.lock_read()
1210
old_inv = old_tree.inventory
1212
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1213
for f, paths, c, v, p, n, k, e in iterator:
1214
if paths[0] == paths[1]:
1218
renames.append(paths)
1220
for old_name, new_name in renames:
1221
self.outf.write("%s => %s\n" % (old_name, new_name))
1228
class cmd_update(Command):
1229
"""Update a tree to have the latest code committed to its branch.
1231
This will perform a merge into the working tree, and may generate
1232
conflicts. If you have any local changes, you will still
1233
need to commit them after the update for the update to be complete.
1235
If you want to discard your local changes, you can just do a
1236
'bzr revert' instead of 'bzr commit' after the update.
1239
_see_also = ['pull', 'working-trees', 'status-flags']
1240
takes_args = ['dir?']
1243
def run(self, dir='.'):
1244
tree = WorkingTree.open_containing(dir)[0]
1245
possible_transports = []
1246
master = tree.branch.get_master_branch(
1247
possible_transports=possible_transports)
1248
if master is not None:
1251
tree.lock_tree_write()
1253
existing_pending_merges = tree.get_parent_ids()[1:]
1254
last_rev = _mod_revision.ensure_null(tree.last_revision())
1255
if last_rev == _mod_revision.ensure_null(
1256
tree.branch.last_revision()):
1257
# may be up to date, check master too.
1258
if master is None or last_rev == _mod_revision.ensure_null(
1259
master.last_revision()):
1260
revno = tree.branch.revision_id_to_revno(last_rev)
1261
note("Tree is up to date at revision %d." % (revno,))
1263
view_info = _get_view_info_for_change_reporter(tree)
1264
conflicts = tree.update(
1265
delta._ChangeReporter(unversioned_filter=tree.is_ignored,
1266
view_info=view_info), possible_transports=possible_transports)
1267
revno = tree.branch.revision_id_to_revno(
1268
_mod_revision.ensure_null(tree.last_revision()))
1269
note('Updated to revision %d.' % (revno,))
1270
if tree.get_parent_ids()[1:] != existing_pending_merges:
1271
note('Your local commits will now show as pending merges with '
1272
"'bzr status', and can be committed with 'bzr commit'.")
1281
class cmd_info(Command):
1282
"""Show information about a working tree, branch or repository.
1284
This command will show all known locations and formats associated to the
1285
tree, branch or repository. Statistical information is included with
1288
Branches and working trees will also report any missing revisions.
1290
_see_also = ['revno', 'working-trees', 'repositories']
1291
takes_args = ['location?']
1292
takes_options = ['verbose']
1293
encoding_type = 'replace'
1296
def run(self, location=None, verbose=False):
1301
from bzrlib.info import show_bzrdir_info
1302
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1303
verbose=noise_level, outfile=self.outf)
1306
class cmd_remove(Command):
1307
"""Remove files or directories.
1309
This makes bzr stop tracking changes to the specified files. bzr will delete
1310
them if they can easily be recovered using revert. If no options or
1311
parameters are given bzr will scan for files that are being tracked by bzr
1312
but missing in your tree and stop tracking them for you.
1314
takes_args = ['file*']
1315
takes_options = ['verbose',
1316
Option('new', help='Only remove files that have never been committed.'),
1317
RegistryOption.from_kwargs('file-deletion-strategy',
1318
'The file deletion mode to be used.',
1319
title='Deletion Strategy', value_switches=True, enum_switch=False,
1320
safe='Only delete files if they can be'
1321
' safely recovered (default).',
1322
keep="Don't delete any files.",
1323
force='Delete all the specified files, even if they can not be '
1324
'recovered and even if they are non-empty directories.')]
1325
aliases = ['rm', 'del']
1326
encoding_type = 'replace'
1328
def run(self, file_list, verbose=False, new=False,
1329
file_deletion_strategy='safe'):
1330
tree, file_list = tree_files(file_list)
1332
if file_list is not None:
1333
file_list = [f for f in file_list]
1337
# Heuristics should probably all move into tree.remove_smart or
1340
added = tree.changes_from(tree.basis_tree(),
1341
specific_files=file_list).added
1342
file_list = sorted([f[0] for f in added], reverse=True)
1343
if len(file_list) == 0:
1344
raise errors.BzrCommandError('No matching files.')
1345
elif file_list is None:
1346
# missing files show up in iter_changes(basis) as
1347
# versioned-with-no-kind.
1349
for change in tree.iter_changes(tree.basis_tree()):
1350
# Find paths in the working tree that have no kind:
1351
if change[1][1] is not None and change[6][1] is None:
1352
missing.append(change[1][1])
1353
file_list = sorted(missing, reverse=True)
1354
file_deletion_strategy = 'keep'
1355
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1356
keep_files=file_deletion_strategy=='keep',
1357
force=file_deletion_strategy=='force')
1362
class cmd_file_id(Command):
1363
"""Print file_id of a particular file or directory.
1365
The file_id is assigned when the file is first added and remains the
1366
same through all revisions where the file exists, even when it is
1371
_see_also = ['inventory', 'ls']
1372
takes_args = ['filename']
1375
def run(self, filename):
1376
tree, relpath = WorkingTree.open_containing(filename)
1377
i = tree.path2id(relpath)
1379
raise errors.NotVersionedError(filename)
1381
self.outf.write(i + '\n')
1384
class cmd_file_path(Command):
1385
"""Print path of file_ids to a file or directory.
1387
This prints one line for each directory down to the target,
1388
starting at the branch root.
1392
takes_args = ['filename']
1395
def run(self, filename):
1396
tree, relpath = WorkingTree.open_containing(filename)
1397
fid = tree.path2id(relpath)
1399
raise errors.NotVersionedError(filename)
1400
segments = osutils.splitpath(relpath)
1401
for pos in range(1, len(segments) + 1):
1402
path = osutils.joinpath(segments[:pos])
1403
self.outf.write("%s\n" % tree.path2id(path))
1406
class cmd_reconcile(Command):
1407
"""Reconcile bzr metadata in a branch.
1409
This can correct data mismatches that may have been caused by
1410
previous ghost operations or bzr upgrades. You should only
1411
need to run this command if 'bzr check' or a bzr developer
1412
advises you to run it.
1414
If a second branch is provided, cross-branch reconciliation is
1415
also attempted, which will check that data like the tree root
1416
id which was not present in very early bzr versions is represented
1417
correctly in both branches.
1419
At the same time it is run it may recompress data resulting in
1420
a potential saving in disk space or performance gain.
1422
The branch *MUST* be on a listable system such as local disk or sftp.
1425
_see_also = ['check']
1426
takes_args = ['branch?']
1428
def run(self, branch="."):
1429
from bzrlib.reconcile import reconcile
1430
dir = bzrdir.BzrDir.open(branch)
1434
class cmd_revision_history(Command):
1435
"""Display the list of revision ids on a branch."""
1438
takes_args = ['location?']
1443
def run(self, location="."):
1444
branch = Branch.open_containing(location)[0]
1445
for revid in branch.revision_history():
1446
self.outf.write(revid)
1447
self.outf.write('\n')
1450
class cmd_ancestry(Command):
1451
"""List all revisions merged into this branch."""
1453
_see_also = ['log', 'revision-history']
1454
takes_args = ['location?']
1459
def run(self, location="."):
1461
wt = WorkingTree.open_containing(location)[0]
1462
except errors.NoWorkingTree:
1463
b = Branch.open(location)
1464
last_revision = b.last_revision()
1467
last_revision = wt.last_revision()
1469
revision_ids = b.repository.get_ancestry(last_revision)
1471
for revision_id in revision_ids:
1472
self.outf.write(revision_id + '\n')
1475
class cmd_init(Command):
1476
"""Make a directory into a versioned branch.
1478
Use this to create an empty branch, or before importing an
1481
If there is a repository in a parent directory of the location, then
1482
the history of the branch will be stored in the repository. Otherwise
1483
init creates a standalone branch which carries its own history
1484
in the .bzr directory.
1486
If there is already a branch at the location but it has no working tree,
1487
the tree can be populated with 'bzr checkout'.
1489
Recipe for importing a tree of files::
1495
bzr commit -m "imported project"
1498
_see_also = ['init-repository', 'branch', 'checkout']
1499
takes_args = ['location?']
1501
Option('create-prefix',
1502
help='Create the path leading up to the branch '
1503
'if it does not already exist.'),
1504
RegistryOption('format',
1505
help='Specify a format for this branch. '
1506
'See "help formats".',
1507
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1508
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1509
value_switches=True,
1510
title="Branch Format",
1512
Option('append-revisions-only',
1513
help='Never change revnos or the existing log.'
1514
' Append revisions to it only.')
1516
def run(self, location=None, format=None, append_revisions_only=False,
1517
create_prefix=False):
1519
format = bzrdir.format_registry.make_bzrdir('default')
1520
if location is None:
1523
to_transport = transport.get_transport(location)
1525
# The path has to exist to initialize a
1526
# branch inside of it.
1527
# Just using os.mkdir, since I don't
1528
# believe that we want to create a bunch of
1529
# locations if the user supplies an extended path
1531
to_transport.ensure_base()
1532
except errors.NoSuchFile:
1533
if not create_prefix:
1534
raise errors.BzrCommandError("Parent directory of %s"
1536
"\nYou may supply --create-prefix to create all"
1537
" leading parent directories."
1539
_create_prefix(to_transport)
1542
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1543
except errors.NotBranchError:
1544
# really a NotBzrDir error...
1545
create_branch = bzrdir.BzrDir.create_branch_convenience
1546
branch = create_branch(to_transport.base, format=format,
1547
possible_transports=[to_transport])
1548
a_bzrdir = branch.bzrdir
1550
from bzrlib.transport.local import LocalTransport
1551
if a_bzrdir.has_branch():
1552
if (isinstance(to_transport, LocalTransport)
1553
and not a_bzrdir.has_workingtree()):
1554
raise errors.BranchExistsWithoutWorkingTree(location)
1555
raise errors.AlreadyBranchError(location)
1556
branch = a_bzrdir.create_branch()
1557
a_bzrdir.create_workingtree()
1558
if append_revisions_only:
1560
branch.set_append_revisions_only(True)
1561
except errors.UpgradeRequired:
1562
raise errors.BzrCommandError('This branch format cannot be set'
1563
' to append-revisions-only. Try --experimental-branch6')
1565
from bzrlib.info import describe_layout, describe_format
1567
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1568
except (errors.NoWorkingTree, errors.NotLocalUrl):
1570
repository = branch.repository
1571
layout = describe_layout(repository, branch, tree).lower()
1572
format = describe_format(a_bzrdir, repository, branch, tree)
1573
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1574
if repository.is_shared():
1575
#XXX: maybe this can be refactored into transport.path_or_url()
1576
url = repository.bzrdir.root_transport.external_url()
1578
url = urlutils.local_path_from_url(url)
1579
except errors.InvalidURL:
1581
self.outf.write("Using shared repository: %s\n" % url)
1584
class cmd_init_repository(Command):
1585
"""Create a shared repository to hold branches.
1587
New branches created under the repository directory will store their
1588
revisions in the repository, not in the branch directory.
1590
If the --no-trees option is used then the branches in the repository
1591
will not have working trees by default.
1594
Create a shared repositories holding just branches::
1596
bzr init-repo --no-trees repo
1599
Make a lightweight checkout elsewhere::
1601
bzr checkout --lightweight repo/trunk trunk-checkout
1606
_see_also = ['init', 'branch', 'checkout', 'repositories']
1607
takes_args = ["location"]
1608
takes_options = [RegistryOption('format',
1609
help='Specify a format for this repository. See'
1610
' "bzr help formats" for details.',
1611
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1612
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1613
value_switches=True, title='Repository format'),
1615
help='Branches in the repository will default to'
1616
' not having a working tree.'),
1618
aliases = ["init-repo"]
1620
def run(self, location, format=None, no_trees=False):
1622
format = bzrdir.format_registry.make_bzrdir('default')
1624
if location is None:
1627
to_transport = transport.get_transport(location)
1628
to_transport.ensure_base()
1630
newdir = format.initialize_on_transport(to_transport)
1631
repo = newdir.create_repository(shared=True)
1632
repo.set_make_working_trees(not no_trees)
1634
from bzrlib.info import show_bzrdir_info
1635
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1638
class cmd_diff(Command):
1639
"""Show differences in the working tree, between revisions or branches.
1641
If no arguments are given, all changes for the current tree are listed.
1642
If files are given, only the changes in those files are listed.
1643
Remote and multiple branches can be compared by using the --old and
1644
--new options. If not provided, the default for both is derived from
1645
the first argument, if any, or the current tree if no arguments are
1648
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1649
produces patches suitable for "patch -p1".
1653
2 - unrepresentable changes
1658
Shows the difference in the working tree versus the last commit::
1662
Difference between the working tree and revision 1::
1666
Difference between revision 2 and revision 1::
1670
Difference between revision 2 and revision 1 for branch xxx::
1674
Show just the differences for file NEWS::
1678
Show the differences in working tree xxx for file NEWS::
1682
Show the differences from branch xxx to this working tree:
1686
Show the differences between two branches for file NEWS::
1688
bzr diff --old xxx --new yyy NEWS
1690
Same as 'bzr diff' but prefix paths with old/ and new/::
1692
bzr diff --prefix old/:new/
1694
_see_also = ['status']
1695
takes_args = ['file*']
1697
Option('diff-options', type=str,
1698
help='Pass these options to the external diff program.'),
1699
Option('prefix', type=str,
1701
help='Set prefixes added to old and new filenames, as '
1702
'two values separated by a colon. (eg "old/:new/").'),
1704
help='Branch/tree to compare from.',
1708
help='Branch/tree to compare to.',
1714
help='Use this command to compare files.',
1718
aliases = ['di', 'dif']
1719
encoding_type = 'exact'
1722
def run(self, revision=None, file_list=None, diff_options=None,
1723
prefix=None, old=None, new=None, using=None):
1724
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1726
if (prefix is None) or (prefix == '0'):
1734
old_label, new_label = prefix.split(":")
1736
raise errors.BzrCommandError(
1737
'--prefix expects two values separated by a colon'
1738
' (eg "old/:new/")')
1740
if revision and len(revision) > 2:
1741
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1742
' one or two revision specifiers')
1744
old_tree, new_tree, specific_files, extra_trees = \
1745
_get_trees_to_diff(file_list, revision, old, new,
1747
return show_diff_trees(old_tree, new_tree, sys.stdout,
1748
specific_files=specific_files,
1749
external_diff_options=diff_options,
1750
old_label=old_label, new_label=new_label,
1751
extra_trees=extra_trees, using=using)
1754
class cmd_deleted(Command):
1755
"""List files deleted in the working tree.
1757
# TODO: Show files deleted since a previous revision, or
1758
# between two revisions.
1759
# TODO: Much more efficient way to do this: read in new
1760
# directories with readdir, rather than stating each one. Same
1761
# level of effort but possibly much less IO. (Or possibly not,
1762
# if the directories are very large...)
1763
_see_also = ['status', 'ls']
1764
takes_options = ['show-ids']
1767
def run(self, show_ids=False):
1768
tree = WorkingTree.open_containing(u'.')[0]
1771
old = tree.basis_tree()
1774
for path, ie in old.inventory.iter_entries():
1775
if not tree.has_id(ie.file_id):
1776
self.outf.write(path)
1778
self.outf.write(' ')
1779
self.outf.write(ie.file_id)
1780
self.outf.write('\n')
1787
class cmd_modified(Command):
1788
"""List files modified in working tree.
1792
_see_also = ['status', 'ls']
1795
help='Write an ascii NUL (\\0) separator '
1796
'between files rather than a newline.')
1800
def run(self, null=False):
1801
tree = WorkingTree.open_containing(u'.')[0]
1802
td = tree.changes_from(tree.basis_tree())
1803
for path, id, kind, text_modified, meta_modified in td.modified:
1805
self.outf.write(path + '\0')
1807
self.outf.write(osutils.quotefn(path) + '\n')
1810
class cmd_added(Command):
1811
"""List files added in working tree.
1815
_see_also = ['status', 'ls']
1818
help='Write an ascii NUL (\\0) separator '
1819
'between files rather than a newline.')
1823
def run(self, null=False):
1824
wt = WorkingTree.open_containing(u'.')[0]
1827
basis = wt.basis_tree()
1830
basis_inv = basis.inventory
1833
if file_id in basis_inv:
1835
if inv.is_root(file_id) and len(basis_inv) == 0:
1837
path = inv.id2path(file_id)
1838
if not os.access(osutils.abspath(path), os.F_OK):
1841
self.outf.write(path + '\0')
1843
self.outf.write(osutils.quotefn(path) + '\n')
1850
class cmd_root(Command):
1851
"""Show the tree root directory.
1853
The root is the nearest enclosing directory with a .bzr control
1856
takes_args = ['filename?']
1858
def run(self, filename=None):
1859
"""Print the branch root."""
1860
tree = WorkingTree.open_containing(filename)[0]
1861
self.outf.write(tree.basedir + '\n')
1864
def _parse_limit(limitstring):
1866
return int(limitstring)
1868
msg = "The limit argument must be an integer."
1869
raise errors.BzrCommandError(msg)
1872
def _parse_levels(s):
1876
msg = "The levels argument must be an integer."
1877
raise errors.BzrCommandError(msg)
1880
class cmd_log(Command):
1881
"""Show historical log for a branch or subset of a branch.
1883
log is bzr's default tool for exploring the history of a branch.
1884
The branch to use is taken from the first parameter. If no parameters
1885
are given, the branch containing the working directory is logged.
1886
Here are some simple examples::
1888
bzr log log the current branch
1889
bzr log foo.py log a file in its branch
1890
bzr log http://server/branch log a branch on a server
1892
The filtering, ordering and information shown for each revision can
1893
be controlled as explained below. By default, all revisions are
1894
shown sorted (topologically) so that newer revisions appear before
1895
older ones and descendants always appear before ancestors. If displayed,
1896
merged revisions are shown indented under the revision in which they
1901
The log format controls how information about each revision is
1902
displayed. The standard log formats are called ``long``, ``short``
1903
and ``line``. The default is long. See ``bzr help log-formats``
1904
for more details on log formats.
1906
The following options can be used to control what information is
1909
-l N display a maximum of N revisions
1910
-n N display N levels of revisions (0 for all, 1 for collapsed)
1911
-v display a status summary (delta) for each revision
1912
-p display a diff (patch) for each revision
1913
--show-ids display revision-ids (and file-ids), not just revnos
1915
Note that the default number of levels to display is a function of the
1916
log format. If the -n option is not used, ``short`` and ``line`` show
1917
just the top level (mainline) while ``long`` shows all levels of merged
1920
Status summaries are shown using status flags like A, M, etc. To see
1921
the changes explained using words like ``added`` and ``modified``
1922
instead, use the -vv option.
1926
To display revisions from oldest to newest, use the --forward option.
1927
In most cases, using this option will have little impact on the total
1928
time taken to produce a log, though --forward does not incrementally
1929
display revisions like --reverse does when it can.
1931
:Revision filtering:
1933
The -r option can be used to specify what revision or range of revisions
1934
to filter against. The various forms are shown below::
1936
-rX display revision X
1937
-rX.. display revision X and later
1938
-r..Y display up to and including revision Y
1939
-rX..Y display from X to Y inclusive
1941
See ``bzr help revisionspec`` for details on how to specify X and Y.
1942
Some common examples are given below::
1944
-r-1 show just the tip
1945
-r-10.. show the last 10 mainline revisions
1946
-rsubmit:.. show what's new on this branch
1947
-rancestor:path.. show changes since the common ancestor of this
1948
branch and the one at location path
1949
-rdate:yesterday.. show changes since yesterday
1951
When logging a range of revisions using -rX..Y, log starts at
1952
revision Y and searches back in history through the primary
1953
("left-hand") parents until it finds X. When logging just the
1954
top level (using -n1), an error is reported if X is not found
1955
along the way. If multi-level logging is used (-n0), X may be
1956
a nested merge revision and the log will be truncated accordingly.
1960
If a parameter is given and it's not a branch, the log will be filtered
1961
to show only those revisions that changed the nominated file or
1964
Filenames are interpreted within their historical context. To log a
1965
deleted file, specify a revision range so that the file existed at
1966
the end or start of the range.
1968
Historical context is also important when interpreting pathnames of
1969
renamed files/directories. Consider the following example:
1971
* revision 1: add tutorial.txt
1972
* revision 2: modify tutorial.txt
1973
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
1977
* ``bzr log guide.txt`` will log the file added in revision 1
1979
* ``bzr log tutorial.txt`` will log the new file added in revision 3
1981
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
1982
the original file in revision 2.
1984
* ``bzr log -r2 -p guide.txt`` will display an error message as there
1985
was no file called guide.txt in revision 2.
1987
Renames are always followed by log. By design, there is no need to
1988
explicitly ask for this (and no way to stop logging a file back
1989
until it was last renamed).
1991
Note: If the path is a directory, only revisions that directly changed
1992
that directory object are currently shown. This is considered a bug.
1993
(Support for filtering against multiple files and for files within a
1994
directory is under development.)
1998
The --message option can be used for finding revisions that match a
1999
regular expression in a commit message.
2003
GUI tools and IDEs are often better at exploring history than command
2004
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2005
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2006
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2008
Web interfaces are often better at exploring history than command line
2009
tools, particularly for branches on servers. You may prefer Loggerhead
2010
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2012
You may find it useful to add the aliases below to ``bazaar.conf``::
2016
top = log -r-10.. --short --forward
2017
show = log -v -p -n1 --long
2019
``bzr tip`` will then show the latest revision while ``bzr top``
2020
will show the last 10 mainline revisions. To see the details of a
2021
particular revision X, ``bzr show -rX``.
2023
As many GUI tools and Web interfaces do, you may prefer viewing
2024
history collapsed initially. If you are interested in looking deeper
2025
into a particular merge X, use ``bzr log -n0 -rX``. If you like
2026
working this way, you may wish to either:
2028
* change your default log format to short (or line)
2029
* add this alias: log = log -n1
2031
``bzr log -v`` on a branch with lots of history is currently
2032
very slow. A fix for this issue is currently under development.
2033
With or without that fix, it is recommended that a revision range
2034
be given when using the -v option.
2036
bzr has a generic full-text matching plugin, bzr-search, that can be
2037
used to find revisions matching user names, commit messages, etc.
2038
Among other features, this plugin can find all revisions containing
2039
a list of words but not others.
2041
When exploring non-mainline history on large projects with deep
2042
history, the performance of log can be greatly improved by installing
2043
the revnocache plugin. This plugin buffers historical information
2044
trading disk space for faster speed.
2046
takes_args = ['location?']
2047
_see_also = ['log-formats', 'revisionspec']
2050
help='Show from oldest to newest.'),
2052
custom_help('verbose',
2053
help='Show files changed in each revision.'),
2057
type=bzrlib.option._parse_revision_str,
2059
help='Show just the specified revision.'
2060
' See also "help revisionspec".'),
2064
help='Number of levels to display - 0 for all, 1 for flat.',
2066
type=_parse_levels),
2069
help='Show revisions whose message matches this '
2070
'regular expression.',
2074
help='Limit the output to the first N revisions.',
2079
help='Show changes made in each revision as a patch.'),
2081
encoding_type = 'replace'
2084
def run(self, location=None, timezone='original',
2095
from bzrlib.log import show_log, _get_fileid_to_log
2096
direction = (forward and 'forward') or 'reverse'
2098
if change is not None:
2100
raise errors.RangeInChangeOption()
2101
if revision is not None:
2102
raise errors.BzrCommandError(
2103
'--revision and --change are mutually exclusive')
2110
# find the file id to log:
2112
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
2115
file_id = _get_fileid_to_log(revision, tree, b, fp)
2117
raise errors.BzrCommandError(
2118
"Path unknown at end or start of revision range: %s" %
2122
# FIXME ? log the current subdir only RBC 20060203
2123
if revision is not None \
2124
and len(revision) > 0 and revision[0].get_branch():
2125
location = revision[0].get_branch()
2128
dir, relpath = bzrdir.BzrDir.open_containing(location)
2129
b = dir.open_branch()
2133
rev1, rev2 = _get_revision_range(revision, b, self.name())
2134
if log_format is None:
2135
log_format = log.log_formatter_registry.get_default(b)
2137
lf = log_format(show_ids=show_ids, to_file=self.outf,
2138
show_timezone=timezone,
2139
delta_format=get_verbosity_level(),
2146
direction=direction,
2147
start_revision=rev1,
2151
show_diff=show_diff)
2156
def _get_revision_range(revisionspec_list, branch, command_name):
2157
"""Take the input of a revision option and turn it into a revision range.
2159
It returns RevisionInfo objects which can be used to obtain the rev_id's
2160
of the desired revisons. It does some user input validations.
2162
if revisionspec_list is None:
2165
elif len(revisionspec_list) == 1:
2166
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2167
elif len(revisionspec_list) == 2:
2168
start_spec = revisionspec_list[0]
2169
end_spec = revisionspec_list[1]
2170
if end_spec.get_branch() != start_spec.get_branch():
2171
# b is taken from revision[0].get_branch(), and
2172
# show_log will use its revision_history. Having
2173
# different branches will lead to weird behaviors.
2174
raise errors.BzrCommandError(
2175
"bzr %s doesn't accept two revisions in different"
2176
" branches." % command_name)
2177
rev1 = start_spec.in_history(branch)
2178
# Avoid loading all of history when we know a missing
2179
# end of range means the last revision ...
2180
if end_spec.spec is None:
2181
last_revno, last_revision_id = branch.last_revision_info()
2182
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2184
rev2 = end_spec.in_history(branch)
2186
raise errors.BzrCommandError(
2187
'bzr %s --revision takes one or two values.' % command_name)
2191
def _revision_range_to_revid_range(revision_range):
2194
if revision_range[0] is not None:
2195
rev_id1 = revision_range[0].rev_id
2196
if revision_range[1] is not None:
2197
rev_id2 = revision_range[1].rev_id
2198
return rev_id1, rev_id2
2200
def get_log_format(long=False, short=False, line=False, default='long'):
2201
log_format = default
2205
log_format = 'short'
2211
class cmd_touching_revisions(Command):
2212
"""Return revision-ids which affected a particular file.
2214
A more user-friendly interface is "bzr log FILE".
2218
takes_args = ["filename"]
2221
def run(self, filename):
2222
tree, relpath = WorkingTree.open_containing(filename)
2224
file_id = tree.path2id(relpath)
2225
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2226
self.outf.write("%6d %s\n" % (revno, what))
2229
class cmd_ls(Command):
2230
"""List files in a tree.
2233
_see_also = ['status', 'cat']
2234
takes_args = ['path?']
2235
# TODO: Take a revision or remote path and list that tree instead.
2239
Option('non-recursive',
2240
help='Don\'t recurse into subdirectories.'),
2242
help='Print paths relative to the root of the branch.'),
2243
Option('unknown', help='Print unknown files.'),
2244
Option('versioned', help='Print versioned files.',
2246
Option('ignored', help='Print ignored files.'),
2248
help='Write an ascii NUL (\\0) separator '
2249
'between files rather than a newline.'),
2251
help='List entries of a particular kind: file, directory, symlink.',
2256
def run(self, revision=None, verbose=False,
2257
non_recursive=False, from_root=False,
2258
unknown=False, versioned=False, ignored=False,
2259
null=False, kind=None, show_ids=False, path=None):
2261
if kind and kind not in ('file', 'directory', 'symlink'):
2262
raise errors.BzrCommandError('invalid kind specified')
2264
if verbose and null:
2265
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2266
all = not (unknown or versioned or ignored)
2268
selection = {'I':ignored, '?':unknown, 'V':versioned}
2275
raise errors.BzrCommandError('cannot specify both --from-root'
2279
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2285
if revision is not None or tree is None:
2286
tree = _get_one_revision_tree('ls', revision, branch=branch)
2290
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2291
if fp.startswith(relpath):
2292
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2293
if non_recursive and '/' in fp:
2295
if not all and not selection[fc]:
2297
if kind is not None and fkind != kind:
2299
kindch = entry.kind_character()
2300
outstring = fp + kindch
2302
outstring = '%-8s %s' % (fc, outstring)
2303
if show_ids and fid is not None:
2304
outstring = "%-50s %s" % (outstring, fid)
2305
self.outf.write(outstring + '\n')
2307
self.outf.write(fp + '\0')
2310
self.outf.write(fid)
2311
self.outf.write('\0')
2319
self.outf.write('%-50s %s\n' % (outstring, my_id))
2321
self.outf.write(outstring + '\n')
2326
class cmd_unknowns(Command):
2327
"""List unknown files.
2335
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2336
self.outf.write(osutils.quotefn(f) + '\n')
2339
class cmd_ignore(Command):
2340
"""Ignore specified files or patterns.
2342
See ``bzr help patterns`` for details on the syntax of patterns.
2344
To remove patterns from the ignore list, edit the .bzrignore file.
2345
After adding, editing or deleting that file either indirectly by
2346
using this command or directly by using an editor, be sure to commit
2349
Note: ignore patterns containing shell wildcards must be quoted from
2353
Ignore the top level Makefile::
2355
bzr ignore ./Makefile
2357
Ignore class files in all directories::
2359
bzr ignore "*.class"
2361
Ignore .o files under the lib directory::
2363
bzr ignore "lib/**/*.o"
2365
Ignore .o files under the lib directory::
2367
bzr ignore "RE:lib/.*\.o"
2369
Ignore everything but the "debian" toplevel directory::
2371
bzr ignore "RE:(?!debian/).*"
2374
_see_also = ['status', 'ignored', 'patterns']
2375
takes_args = ['name_pattern*']
2377
Option('old-default-rules',
2378
help='Write out the ignore rules bzr < 0.9 always used.')
2381
def run(self, name_pattern_list=None, old_default_rules=None):
2382
from bzrlib import ignores
2383
if old_default_rules is not None:
2384
# dump the rules and exit
2385
for pattern in ignores.OLD_DEFAULTS:
2388
if not name_pattern_list:
2389
raise errors.BzrCommandError("ignore requires at least one "
2390
"NAME_PATTERN or --old-default-rules")
2391
name_pattern_list = [globbing.normalize_pattern(p)
2392
for p in name_pattern_list]
2393
for name_pattern in name_pattern_list:
2394
if (name_pattern[0] == '/' or
2395
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2396
raise errors.BzrCommandError(
2397
"NAME_PATTERN should not be an absolute path")
2398
tree, relpath = WorkingTree.open_containing(u'.')
2399
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2400
ignored = globbing.Globster(name_pattern_list)
2403
for entry in tree.list_files():
2407
if ignored.match(filename):
2408
matches.append(filename.encode('utf-8'))
2410
if len(matches) > 0:
2411
print "Warning: the following files are version controlled and" \
2412
" match your ignore pattern:\n%s" % ("\n".join(matches),)
2415
class cmd_ignored(Command):
2416
"""List ignored files and the patterns that matched them.
2418
List all the ignored files and the ignore pattern that caused the file to
2421
Alternatively, to list just the files::
2426
encoding_type = 'replace'
2427
_see_also = ['ignore', 'ls']
2431
tree = WorkingTree.open_containing(u'.')[0]
2434
for path, file_class, kind, file_id, entry in tree.list_files():
2435
if file_class != 'I':
2437
## XXX: Slightly inefficient since this was already calculated
2438
pat = tree.is_ignored(path)
2439
self.outf.write('%-50s %s\n' % (path, pat))
2444
class cmd_lookup_revision(Command):
2445
"""Lookup the revision-id from a revision-number
2448
bzr lookup-revision 33
2451
takes_args = ['revno']
2454
def run(self, revno):
2458
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2460
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2463
class cmd_export(Command):
2464
"""Export current or past revision to a destination directory or archive.
2466
If no revision is specified this exports the last committed revision.
2468
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
2469
given, try to find the format with the extension. If no extension
2470
is found exports to a directory (equivalent to --format=dir).
2472
If root is supplied, it will be used as the root directory inside
2473
container formats (tar, zip, etc). If it is not supplied it will default
2474
to the exported filename. The root option has no effect for 'dir' format.
2476
If branch is omitted then the branch containing the current working
2477
directory will be used.
2479
Note: Export of tree with non-ASCII filenames to zip is not supported.
2481
================= =========================
2482
Supported formats Autodetected by extension
2483
================= =========================
2486
tbz2 .tar.bz2, .tbz2
2489
================= =========================
2491
takes_args = ['dest', 'branch_or_subdir?']
2494
help="Type of file to export to.",
2499
help="Name of the root directory inside the exported file."),
2501
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2503
from bzrlib.export import export
2505
if branch_or_subdir is None:
2506
tree = WorkingTree.open_containing(u'.')[0]
2510
b, subdir = Branch.open_containing(branch_or_subdir)
2513
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2515
export(rev_tree, dest, format, root, subdir)
2516
except errors.NoSuchExportFormat, e:
2517
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2520
class cmd_cat(Command):
2521
"""Write the contents of a file as of a given revision to standard output.
2523
If no revision is nominated, the last revision is used.
2525
Note: Take care to redirect standard output when using this command on a
2531
Option('name-from-revision', help='The path name in the old tree.'),
2534
takes_args = ['filename']
2535
encoding_type = 'exact'
2538
def run(self, filename, revision=None, name_from_revision=False):
2539
if revision is not None and len(revision) != 1:
2540
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2541
" one revision specifier")
2542
tree, branch, relpath = \
2543
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2546
return self._run(tree, branch, relpath, filename, revision,
2551
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2553
tree = b.basis_tree()
2554
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2556
cur_file_id = tree.path2id(relpath)
2557
old_file_id = rev_tree.path2id(relpath)
2559
if name_from_revision:
2560
if old_file_id is None:
2561
raise errors.BzrCommandError(
2562
"%r is not present in revision %s" % (
2563
filename, rev_tree.get_revision_id()))
2565
content = rev_tree.get_file_text(old_file_id)
2566
elif cur_file_id is not None:
2567
content = rev_tree.get_file_text(cur_file_id)
2568
elif old_file_id is not None:
2569
content = rev_tree.get_file_text(old_file_id)
2571
raise errors.BzrCommandError(
2572
"%r is not present in revision %s" % (
2573
filename, rev_tree.get_revision_id()))
2574
self.outf.write(content)
2577
class cmd_local_time_offset(Command):
2578
"""Show the offset in seconds from GMT to local time."""
2582
print osutils.local_time_offset()
2586
class cmd_commit(Command):
2587
"""Commit changes into a new revision.
2589
If no arguments are given, the entire tree is committed.
2591
If selected files are specified, only changes to those files are
2592
committed. If a directory is specified then the directory and everything
2593
within it is committed.
2595
When excludes are given, they take precedence over selected files.
2596
For example, too commit only changes within foo, but not changes within
2599
bzr commit foo -x foo/bar
2601
If author of the change is not the same person as the committer, you can
2602
specify the author's name using the --author option. The name should be
2603
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2605
A selected-file commit may fail in some cases where the committed
2606
tree would be invalid. Consider::
2611
bzr commit foo -m "committing foo"
2612
bzr mv foo/bar foo/baz
2615
bzr commit foo/bar -m "committing bar but not baz"
2617
In the example above, the last commit will fail by design. This gives
2618
the user the opportunity to decide whether they want to commit the
2619
rename at the same time, separately first, or not at all. (As a general
2620
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2622
Note: A selected-file commit after a merge is not yet supported.
2624
# TODO: Run hooks on tree to-be-committed, and after commit.
2626
# TODO: Strict commit that fails if there are deleted files.
2627
# (what does "deleted files" mean ??)
2629
# TODO: Give better message for -s, --summary, used by tla people
2631
# XXX: verbose currently does nothing
2633
_see_also = ['bugs', 'uncommit']
2634
takes_args = ['selected*']
2636
ListOption('exclude', type=str, short_name='x',
2637
help="Do not consider changes made to a given path."),
2638
Option('message', type=unicode,
2640
help="Description of the new revision."),
2643
help='Commit even if nothing has changed.'),
2644
Option('file', type=str,
2647
help='Take commit message from this file.'),
2649
help="Refuse to commit if there are unknown "
2650
"files in the working tree."),
2651
ListOption('fixes', type=str,
2652
help="Mark a bug as being fixed by this revision."),
2653
Option('author', type=unicode,
2654
help="Set the author's name, if it's different "
2655
"from the committer."),
2657
help="Perform a local commit in a bound "
2658
"branch. Local commits are not pushed to "
2659
"the master branch until a normal commit "
2663
help='When no message is supplied, show the diff along'
2664
' with the status summary in the message editor.'),
2666
aliases = ['ci', 'checkin']
2668
def _get_bug_fix_properties(self, fixes, branch):
2670
# Configure the properties for bug fixing attributes.
2671
for fixed_bug in fixes:
2672
tokens = fixed_bug.split(':')
2673
if len(tokens) != 2:
2674
raise errors.BzrCommandError(
2675
"Invalid bug %s. Must be in the form of 'tag:id'. "
2676
"Commit refused." % fixed_bug)
2677
tag, bug_id = tokens
2679
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2680
except errors.UnknownBugTrackerAbbreviation:
2681
raise errors.BzrCommandError(
2682
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2683
except errors.MalformedBugIdentifier:
2684
raise errors.BzrCommandError(
2685
"Invalid bug identifier for %s. Commit refused."
2687
properties.append('%s fixed' % bug_url)
2688
return '\n'.join(properties)
2690
def run(self, message=None, file=None, verbose=False, selected_list=None,
2691
unchanged=False, strict=False, local=False, fixes=None,
2692
author=None, show_diff=False, exclude=None):
2693
from bzrlib.errors import (
2698
from bzrlib.msgeditor import (
2699
edit_commit_message_encoded,
2700
generate_commit_message_template,
2701
make_commit_message_template_encoded
2704
# TODO: Need a blackbox test for invoking the external editor; may be
2705
# slightly problematic to run this cross-platform.
2707
# TODO: do more checks that the commit will succeed before
2708
# spending the user's valuable time typing a commit message.
2712
tree, selected_list = tree_files(selected_list)
2713
if selected_list == ['']:
2714
# workaround - commit of root of tree should be exactly the same
2715
# as just default commit in that tree, and succeed even though
2716
# selected-file merge commit is not done yet
2721
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2723
properties['bugs'] = bug_property
2725
if local and not tree.branch.get_bound_location():
2726
raise errors.LocalRequiresBoundBranch()
2728
def get_message(commit_obj):
2729
"""Callback to get commit message"""
2730
my_message = message
2731
if my_message is None and not file:
2732
t = make_commit_message_template_encoded(tree,
2733
selected_list, diff=show_diff,
2734
output_encoding=osutils.get_user_encoding())
2735
start_message = generate_commit_message_template(commit_obj)
2736
my_message = edit_commit_message_encoded(t,
2737
start_message=start_message)
2738
if my_message is None:
2739
raise errors.BzrCommandError("please specify a commit"
2740
" message with either --message or --file")
2741
elif my_message and file:
2742
raise errors.BzrCommandError(
2743
"please specify either --message or --file")
2745
my_message = codecs.open(file, 'rt',
2746
osutils.get_user_encoding()).read()
2747
if my_message == "":
2748
raise errors.BzrCommandError("empty commit message specified")
2752
tree.commit(message_callback=get_message,
2753
specific_files=selected_list,
2754
allow_pointless=unchanged, strict=strict, local=local,
2755
reporter=None, verbose=verbose, revprops=properties,
2757
exclude=safe_relpath_files(tree, exclude))
2758
except PointlessCommit:
2759
# FIXME: This should really happen before the file is read in;
2760
# perhaps prepare the commit; get the message; then actually commit
2761
raise errors.BzrCommandError("no changes to commit."
2762
" use --unchanged to commit anyhow")
2763
except ConflictsInTree:
2764
raise errors.BzrCommandError('Conflicts detected in working '
2765
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2767
except StrictCommitFailed:
2768
raise errors.BzrCommandError("Commit refused because there are"
2769
" unknown files in the working tree.")
2770
except errors.BoundBranchOutOfDate, e:
2771
raise errors.BzrCommandError(str(e) + "\n"
2772
'To commit to master branch, run update and then commit.\n'
2773
'You can also pass --local to commit to continue working '
2777
class cmd_check(Command):
2778
"""Validate working tree structure, branch consistency and repository history.
2780
This command checks various invariants about branch and repository storage
2781
to detect data corruption or bzr bugs.
2783
The working tree and branch checks will only give output if a problem is
2784
detected. The output fields of the repository check are:
2786
revisions: This is just the number of revisions checked. It doesn't
2788
versionedfiles: This is just the number of versionedfiles checked. It
2789
doesn't indicate a problem.
2790
unreferenced ancestors: Texts that are ancestors of other texts, but
2791
are not properly referenced by the revision ancestry. This is a
2792
subtle problem that Bazaar can work around.
2793
unique file texts: This is the total number of unique file contents
2794
seen in the checked revisions. It does not indicate a problem.
2795
repeated file texts: This is the total number of repeated texts seen
2796
in the checked revisions. Texts can be repeated when their file
2797
entries are modified, but the file contents are not. It does not
2800
If no restrictions are specified, all Bazaar data that is found at the given
2801
location will be checked.
2805
Check the tree and branch at 'foo'::
2807
bzr check --tree --branch foo
2809
Check only the repository at 'bar'::
2811
bzr check --repo bar
2813
Check everything at 'baz'::
2818
_see_also = ['reconcile']
2819
takes_args = ['path?']
2820
takes_options = ['verbose',
2821
Option('branch', help="Check the branch related to the"
2822
" current directory."),
2823
Option('repo', help="Check the repository related to the"
2824
" current directory."),
2825
Option('tree', help="Check the working tree related to"
2826
" the current directory.")]
2828
def run(self, path=None, verbose=False, branch=False, repo=False,
2830
from bzrlib.check import check_dwim
2833
if not branch and not repo and not tree:
2834
branch = repo = tree = True
2835
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2838
class cmd_upgrade(Command):
2839
"""Upgrade branch storage to current format.
2841
The check command or bzr developers may sometimes advise you to run
2842
this command. When the default format has changed you may also be warned
2843
during other operations to upgrade.
2846
_see_also = ['check']
2847
takes_args = ['url?']
2849
RegistryOption('format',
2850
help='Upgrade to a specific format. See "bzr help'
2851
' formats" for details.',
2852
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
2853
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2854
value_switches=True, title='Branch format'),
2857
def run(self, url='.', format=None):
2858
from bzrlib.upgrade import upgrade
2860
format = bzrdir.format_registry.make_bzrdir('default')
2861
upgrade(url, format)
2864
class cmd_whoami(Command):
2865
"""Show or set bzr user id.
2868
Show the email of the current user::
2872
Set the current user::
2874
bzr whoami "Frank Chu <fchu@example.com>"
2876
takes_options = [ Option('email',
2877
help='Display email address only.'),
2879
help='Set identity for the current branch instead of '
2882
takes_args = ['name?']
2883
encoding_type = 'replace'
2886
def run(self, email=False, branch=False, name=None):
2888
# use branch if we're inside one; otherwise global config
2890
c = Branch.open_containing('.')[0].get_config()
2891
except errors.NotBranchError:
2892
c = config.GlobalConfig()
2894
self.outf.write(c.user_email() + '\n')
2896
self.outf.write(c.username() + '\n')
2899
# display a warning if an email address isn't included in the given name.
2901
config.extract_email_address(name)
2902
except errors.NoEmailInUsername, e:
2903
warning('"%s" does not seem to contain an email address. '
2904
'This is allowed, but not recommended.', name)
2906
# use global config unless --branch given
2908
c = Branch.open_containing('.')[0].get_config()
2910
c = config.GlobalConfig()
2911
c.set_user_option('email', name)
2914
class cmd_nick(Command):
2915
"""Print or set the branch nickname.
2917
If unset, the tree root directory name is used as the nickname.
2918
To print the current nickname, execute with no argument.
2920
Bound branches use the nickname of its master branch unless it is set
2924
_see_also = ['info']
2925
takes_args = ['nickname?']
2926
def run(self, nickname=None):
2927
branch = Branch.open_containing(u'.')[0]
2928
if nickname is None:
2929
self.printme(branch)
2931
branch.nick = nickname
2934
def printme(self, branch):
2938
class cmd_alias(Command):
2939
"""Set/unset and display aliases.
2942
Show the current aliases::
2946
Show the alias specified for 'll'::
2950
Set an alias for 'll'::
2952
bzr alias ll="log --line -r-10..-1"
2954
To remove an alias for 'll'::
2956
bzr alias --remove ll
2959
takes_args = ['name?']
2961
Option('remove', help='Remove the alias.'),
2964
def run(self, name=None, remove=False):
2966
self.remove_alias(name)
2968
self.print_aliases()
2970
equal_pos = name.find('=')
2972
self.print_alias(name)
2974
self.set_alias(name[:equal_pos], name[equal_pos+1:])
2976
def remove_alias(self, alias_name):
2977
if alias_name is None:
2978
raise errors.BzrCommandError(
2979
'bzr alias --remove expects an alias to remove.')
2980
# If alias is not found, print something like:
2981
# unalias: foo: not found
2982
c = config.GlobalConfig()
2983
c.unset_alias(alias_name)
2986
def print_aliases(self):
2987
"""Print out the defined aliases in a similar format to bash."""
2988
aliases = config.GlobalConfig().get_aliases()
2989
for key, value in sorted(aliases.iteritems()):
2990
self.outf.write('bzr alias %s="%s"\n' % (key, value))
2993
def print_alias(self, alias_name):
2994
from bzrlib.commands import get_alias
2995
alias = get_alias(alias_name)
2997
self.outf.write("bzr alias: %s: not found\n" % alias_name)
3000
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3002
def set_alias(self, alias_name, alias_command):
3003
"""Save the alias in the global config."""
3004
c = config.GlobalConfig()
3005
c.set_alias(alias_name, alias_command)
3008
class cmd_selftest(Command):
3009
"""Run internal test suite.
3011
If arguments are given, they are regular expressions that say which tests
3012
should run. Tests matching any expression are run, and other tests are
3015
Alternatively if --first is given, matching tests are run first and then
3016
all other tests are run. This is useful if you have been working in a
3017
particular area, but want to make sure nothing else was broken.
3019
If --exclude is given, tests that match that regular expression are
3020
excluded, regardless of whether they match --first or not.
3022
To help catch accidential dependencies between tests, the --randomize
3023
option is useful. In most cases, the argument used is the word 'now'.
3024
Note that the seed used for the random number generator is displayed
3025
when this option is used. The seed can be explicitly passed as the
3026
argument to this option if required. This enables reproduction of the
3027
actual ordering used if and when an order sensitive problem is encountered.
3029
If --list-only is given, the tests that would be run are listed. This is
3030
useful when combined with --first, --exclude and/or --randomize to
3031
understand their impact. The test harness reports "Listed nn tests in ..."
3032
instead of "Ran nn tests in ..." when list mode is enabled.
3034
If the global option '--no-plugins' is given, plugins are not loaded
3035
before running the selftests. This has two effects: features provided or
3036
modified by plugins will not be tested, and tests provided by plugins will
3039
Tests that need working space on disk use a common temporary directory,
3040
typically inside $TMPDIR or /tmp.
3043
Run only tests relating to 'ignore'::
3047
Disable plugins and list tests as they're run::
3049
bzr --no-plugins selftest -v
3051
# NB: this is used from the class without creating an instance, which is
3052
# why it does not have a self parameter.
3053
def get_transport_type(typestring):
3054
"""Parse and return a transport specifier."""
3055
if typestring == "sftp":
3056
from bzrlib.transport.sftp import SFTPAbsoluteServer
3057
return SFTPAbsoluteServer
3058
if typestring == "memory":
3059
from bzrlib.transport.memory import MemoryServer
3061
if typestring == "fakenfs":
3062
from bzrlib.transport.fakenfs import FakeNFSServer
3063
return FakeNFSServer
3064
msg = "No known transport type %s. Supported types are: sftp\n" %\
3066
raise errors.BzrCommandError(msg)
3069
takes_args = ['testspecs*']
3070
takes_options = ['verbose',
3072
help='Stop when one test fails.',
3076
help='Use a different transport by default '
3077
'throughout the test suite.',
3078
type=get_transport_type),
3080
help='Run the benchmarks rather than selftests.'),
3081
Option('lsprof-timed',
3082
help='Generate lsprof output for benchmarked'
3083
' sections of code.'),
3084
Option('cache-dir', type=str,
3085
help='Cache intermediate benchmark output in this '
3088
help='Run all tests, but run specified tests first.',
3092
help='List the tests instead of running them.'),
3093
Option('randomize', type=str, argname="SEED",
3094
help='Randomize the order of tests using the given'
3095
' seed or "now" for the current time.'),
3096
Option('exclude', type=str, argname="PATTERN",
3098
help='Exclude tests that match this regular'
3100
Option('strict', help='Fail on missing dependencies or '
3102
Option('load-list', type=str, argname='TESTLISTFILE',
3103
help='Load a test id list from a text file.'),
3104
ListOption('debugflag', type=str, short_name='E',
3105
help='Turn on a selftest debug flag.'),
3106
ListOption('starting-with', type=str, argname='TESTID',
3107
param_name='starting_with', short_name='s',
3109
'Load only the tests starting with TESTID.'),
3111
encoding_type = 'replace'
3114
Command.__init__(self)
3115
self.additional_selftest_args = {}
3117
def run(self, testspecs_list=None, verbose=False, one=False,
3118
transport=None, benchmark=None,
3119
lsprof_timed=None, cache_dir=None,
3120
first=False, list_only=False,
3121
randomize=None, exclude=None, strict=False,
3122
load_list=None, debugflag=None, starting_with=None):
3123
from bzrlib.tests import selftest
3124
import bzrlib.benchmarks as benchmarks
3125
from bzrlib.benchmarks import tree_creator
3127
# Make deprecation warnings visible, unless -Werror is set
3128
symbol_versioning.activate_deprecation_warnings(override=False)
3130
if cache_dir is not None:
3131
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3133
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
3134
print ' %s (%s python%s)' % (
3136
bzrlib.version_string,
3137
bzrlib._format_version_tuple(sys.version_info),
3140
if testspecs_list is not None:
3141
pattern = '|'.join(testspecs_list)
3145
test_suite_factory = benchmarks.test_suite
3146
# Unless user explicitly asks for quiet, be verbose in benchmarks
3147
verbose = not is_quiet()
3148
# TODO: should possibly lock the history file...
3149
benchfile = open(".perf_history", "at", buffering=1)
3151
test_suite_factory = None
3154
selftest_kwargs = {"verbose": verbose,
3156
"stop_on_failure": one,
3157
"transport": transport,
3158
"test_suite_factory": test_suite_factory,
3159
"lsprof_timed": lsprof_timed,
3160
"bench_history": benchfile,
3161
"matching_tests_first": first,
3162
"list_only": list_only,
3163
"random_seed": randomize,
3164
"exclude_pattern": exclude,
3166
"load_list": load_list,
3167
"debug_flags": debugflag,
3168
"starting_with": starting_with
3170
selftest_kwargs.update(self.additional_selftest_args)
3171
result = selftest(**selftest_kwargs)
3173
if benchfile is not None:
3176
note('tests passed')
3178
note('tests failed')
3179
return int(not result)
3182
class cmd_version(Command):
3183
"""Show version of bzr."""
3185
encoding_type = 'replace'
3187
Option("short", help="Print just the version number."),
3191
def run(self, short=False):
3192
from bzrlib.version import show_version
3194
self.outf.write(bzrlib.version_string + '\n')
3196
show_version(to_file=self.outf)
3199
class cmd_rocks(Command):
3200
"""Statement of optimism."""
3206
print "It sure does!"
3209
class cmd_find_merge_base(Command):
3210
"""Find and print a base revision for merging two branches."""
3211
# TODO: Options to specify revisions on either side, as if
3212
# merging only part of the history.
3213
takes_args = ['branch', 'other']
3217
def run(self, branch, other):
3218
from bzrlib.revision import ensure_null
3220
branch1 = Branch.open_containing(branch)[0]
3221
branch2 = Branch.open_containing(other)[0]
3226
last1 = ensure_null(branch1.last_revision())
3227
last2 = ensure_null(branch2.last_revision())
3229
graph = branch1.repository.get_graph(branch2.repository)
3230
base_rev_id = graph.find_unique_lca(last1, last2)
3232
print 'merge base is revision %s' % base_rev_id
3239
class cmd_merge(Command):
3240
"""Perform a three-way merge.
3242
The source of the merge can be specified either in the form of a branch,
3243
or in the form of a path to a file containing a merge directive generated
3244
with bzr send. If neither is specified, the default is the upstream branch
3245
or the branch most recently merged using --remember.
3247
When merging a branch, by default the tip will be merged. To pick a different
3248
revision, pass --revision. If you specify two values, the first will be used as
3249
BASE and the second one as OTHER. Merging individual revisions, or a subset of
3250
available revisions, like this is commonly referred to as "cherrypicking".
3252
Revision numbers are always relative to the branch being merged.
3254
By default, bzr will try to merge in all new work from the other
3255
branch, automatically determining an appropriate base. If this
3256
fails, you may need to give an explicit base.
3258
Merge will do its best to combine the changes in two branches, but there
3259
are some kinds of problems only a human can fix. When it encounters those,
3260
it will mark a conflict. A conflict means that you need to fix something,
3261
before you should commit.
3263
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3265
If there is no default branch set, the first merge will set it. After
3266
that, you can omit the branch to use the default. To change the
3267
default, use --remember. The value will only be saved if the remote
3268
location can be accessed.
3270
The results of the merge are placed into the destination working
3271
directory, where they can be reviewed (with bzr diff), tested, and then
3272
committed to record the result of the merge.
3274
merge refuses to run if there are any uncommitted changes, unless
3278
To merge the latest revision from bzr.dev::
3280
bzr merge ../bzr.dev
3282
To merge changes up to and including revision 82 from bzr.dev::
3284
bzr merge -r 82 ../bzr.dev
3286
To merge the changes introduced by 82, without previous changes::
3288
bzr merge -r 81..82 ../bzr.dev
3290
To apply a merge directive contained in in /tmp/merge:
3292
bzr merge /tmp/merge
3295
encoding_type = 'exact'
3296
_see_also = ['update', 'remerge', 'status-flags']
3297
takes_args = ['location?']
3302
help='Merge even if the destination tree has uncommitted changes.'),
3306
Option('show-base', help="Show base revision text in "
3308
Option('uncommitted', help='Apply uncommitted changes'
3309
' from a working copy, instead of branch changes.'),
3310
Option('pull', help='If the destination is already'
3311
' completely merged into the source, pull from the'
3312
' source rather than merging. When this happens,'
3313
' you do not need to commit the result.'),
3315
help='Branch to merge into, '
3316
'rather than the one containing the working directory.',
3320
Option('preview', help='Instead of merging, show a diff of the merge.')
3323
def run(self, location=None, revision=None, force=False,
3324
merge_type=None, show_base=False, reprocess=None, remember=False,
3325
uncommitted=False, pull=False,
3329
if merge_type is None:
3330
merge_type = _mod_merge.Merge3Merger
3332
if directory is None: directory = u'.'
3333
possible_transports = []
3335
allow_pending = True
3336
verified = 'inapplicable'
3337
tree = WorkingTree.open_containing(directory)[0]
3338
view_info = _get_view_info_for_change_reporter(tree)
3339
change_reporter = delta._ChangeReporter(
3340
unversioned_filter=tree.is_ignored, view_info=view_info)
3343
pb = ui.ui_factory.nested_progress_bar()
3344
cleanups.append(pb.finished)
3346
cleanups.append(tree.unlock)
3347
if location is not None:
3349
mergeable = bundle.read_mergeable_from_url(location,
3350
possible_transports=possible_transports)
3351
except errors.NotABundle:
3355
raise errors.BzrCommandError('Cannot use --uncommitted'
3356
' with bundles or merge directives.')
3358
if revision is not None:
3359
raise errors.BzrCommandError(
3360
'Cannot use -r with merge directives or bundles')
3361
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3364
if merger is None and uncommitted:
3365
if revision is not None and len(revision) > 0:
3366
raise errors.BzrCommandError('Cannot use --uncommitted and'
3367
' --revision at the same time.')
3368
location = self._select_branch_location(tree, location)[0]
3369
other_tree, other_path = WorkingTree.open_containing(location)
3370
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3372
allow_pending = False
3373
if other_path != '':
3374
merger.interesting_files = [other_path]
3377
merger, allow_pending = self._get_merger_from_branch(tree,
3378
location, revision, remember, possible_transports, pb)
3380
merger.merge_type = merge_type
3381
merger.reprocess = reprocess
3382
merger.show_base = show_base
3383
self.sanity_check_merger(merger)
3384
if (merger.base_rev_id == merger.other_rev_id and
3385
merger.other_rev_id is not None):
3386
note('Nothing to do.')
3389
if merger.interesting_files is not None:
3390
raise errors.BzrCommandError('Cannot pull individual files')
3391
if (merger.base_rev_id == tree.last_revision()):
3392
result = tree.pull(merger.other_branch, False,
3393
merger.other_rev_id)
3394
result.report(self.outf)
3396
merger.check_basis(not force)
3398
return self._do_preview(merger)
3400
return self._do_merge(merger, change_reporter, allow_pending,
3403
for cleanup in reversed(cleanups):
3406
def _do_preview(self, merger):
3407
from bzrlib.diff import show_diff_trees
3408
tree_merger = merger.make_merger()
3409
tt = tree_merger.make_preview_transform()
3411
result_tree = tt.get_preview_tree()
3412
show_diff_trees(merger.this_tree, result_tree, self.outf,
3413
old_label='', new_label='')
3417
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3418
merger.change_reporter = change_reporter
3419
conflict_count = merger.do_merge()
3421
merger.set_pending()
3422
if verified == 'failed':
3423
warning('Preview patch does not match changes')
3424
if conflict_count != 0:
3429
def sanity_check_merger(self, merger):
3430
if (merger.show_base and
3431
not merger.merge_type is _mod_merge.Merge3Merger):
3432
raise errors.BzrCommandError("Show-base is not supported for this"
3433
" merge type. %s" % merger.merge_type)
3434
if merger.reprocess is None:
3435
if merger.show_base:
3436
merger.reprocess = False
3438
# Use reprocess if the merger supports it
3439
merger.reprocess = merger.merge_type.supports_reprocess
3440
if merger.reprocess and not merger.merge_type.supports_reprocess:
3441
raise errors.BzrCommandError("Conflict reduction is not supported"
3442
" for merge type %s." %
3444
if merger.reprocess and merger.show_base:
3445
raise errors.BzrCommandError("Cannot do conflict reduction and"
3448
def _get_merger_from_branch(self, tree, location, revision, remember,
3449
possible_transports, pb):
3450
"""Produce a merger from a location, assuming it refers to a branch."""
3451
from bzrlib.tag import _merge_tags_if_possible
3452
# find the branch locations
3453
other_loc, user_location = self._select_branch_location(tree, location,
3455
if revision is not None and len(revision) == 2:
3456
base_loc, _unused = self._select_branch_location(tree,
3457
location, revision, 0)
3459
base_loc = other_loc
3461
other_branch, other_path = Branch.open_containing(other_loc,
3462
possible_transports)
3463
if base_loc == other_loc:
3464
base_branch = other_branch
3466
base_branch, base_path = Branch.open_containing(base_loc,
3467
possible_transports)
3468
# Find the revision ids
3469
if revision is None or len(revision) < 1 or revision[-1] is None:
3470
other_revision_id = _mod_revision.ensure_null(
3471
other_branch.last_revision())
3473
other_revision_id = revision[-1].as_revision_id(other_branch)
3474
if (revision is not None and len(revision) == 2
3475
and revision[0] is not None):
3476
base_revision_id = revision[0].as_revision_id(base_branch)
3478
base_revision_id = None
3479
# Remember where we merge from
3480
if ((remember or tree.branch.get_submit_branch() is None) and
3481
user_location is not None):
3482
tree.branch.set_submit_branch(other_branch.base)
3483
_merge_tags_if_possible(other_branch, tree.branch)
3484
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3485
other_revision_id, base_revision_id, other_branch, base_branch)
3486
if other_path != '':
3487
allow_pending = False
3488
merger.interesting_files = [other_path]
3490
allow_pending = True
3491
return merger, allow_pending
3493
def _select_branch_location(self, tree, user_location, revision=None,
3495
"""Select a branch location, according to possible inputs.
3497
If provided, branches from ``revision`` are preferred. (Both
3498
``revision`` and ``index`` must be supplied.)
3500
Otherwise, the ``location`` parameter is used. If it is None, then the
3501
``submit`` or ``parent`` location is used, and a note is printed.
3503
:param tree: The working tree to select a branch for merging into
3504
:param location: The location entered by the user
3505
:param revision: The revision parameter to the command
3506
:param index: The index to use for the revision parameter. Negative
3507
indices are permitted.
3508
:return: (selected_location, user_location). The default location
3509
will be the user-entered location.
3511
if (revision is not None and index is not None
3512
and revision[index] is not None):
3513
branch = revision[index].get_branch()
3514
if branch is not None:
3515
return branch, branch
3516
if user_location is None:
3517
location = self._get_remembered(tree, 'Merging from')
3519
location = user_location
3520
return location, user_location
3522
def _get_remembered(self, tree, verb_string):
3523
"""Use tree.branch's parent if none was supplied.
3525
Report if the remembered location was used.
3527
stored_location = tree.branch.get_submit_branch()
3528
stored_location_type = "submit"
3529
if stored_location is None:
3530
stored_location = tree.branch.get_parent()
3531
stored_location_type = "parent"
3532
mutter("%s", stored_location)
3533
if stored_location is None:
3534
raise errors.BzrCommandError("No location specified or remembered")
3535
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3536
note(u"%s remembered %s location %s", verb_string,
3537
stored_location_type, display_url)
3538
return stored_location
3541
class cmd_remerge(Command):
3544
Use this if you want to try a different merge technique while resolving
3545
conflicts. Some merge techniques are better than others, and remerge
3546
lets you try different ones on different files.
3548
The options for remerge have the same meaning and defaults as the ones for
3549
merge. The difference is that remerge can (only) be run when there is a
3550
pending merge, and it lets you specify particular files.
3553
Re-do the merge of all conflicted files, and show the base text in
3554
conflict regions, in addition to the usual THIS and OTHER texts::
3556
bzr remerge --show-base
3558
Re-do the merge of "foobar", using the weave merge algorithm, with
3559
additional processing to reduce the size of conflict regions::
3561
bzr remerge --merge-type weave --reprocess foobar
3563
takes_args = ['file*']
3568
help="Show base revision text in conflicts."),
3571
def run(self, file_list=None, merge_type=None, show_base=False,
3573
if merge_type is None:
3574
merge_type = _mod_merge.Merge3Merger
3575
tree, file_list = tree_files(file_list)
3578
parents = tree.get_parent_ids()
3579
if len(parents) != 2:
3580
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3581
" merges. Not cherrypicking or"
3583
repository = tree.branch.repository
3584
interesting_ids = None
3586
conflicts = tree.conflicts()
3587
if file_list is not None:
3588
interesting_ids = set()
3589
for filename in file_list:
3590
file_id = tree.path2id(filename)
3592
raise errors.NotVersionedError(filename)
3593
interesting_ids.add(file_id)
3594
if tree.kind(file_id) != "directory":
3597
for name, ie in tree.inventory.iter_entries(file_id):
3598
interesting_ids.add(ie.file_id)
3599
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3601
# Remerge only supports resolving contents conflicts
3602
allowed_conflicts = ('text conflict', 'contents conflict')
3603
restore_files = [c.path for c in conflicts
3604
if c.typestring in allowed_conflicts]
3605
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3606
tree.set_conflicts(ConflictList(new_conflicts))
3607
if file_list is not None:
3608
restore_files = file_list
3609
for filename in restore_files:
3611
restore(tree.abspath(filename))
3612
except errors.NotConflicted:
3614
# Disable pending merges, because the file texts we are remerging
3615
# have not had those merges performed. If we use the wrong parents
3616
# list, we imply that the working tree text has seen and rejected
3617
# all the changes from the other tree, when in fact those changes
3618
# have not yet been seen.
3619
pb = ui.ui_factory.nested_progress_bar()
3620
tree.set_parent_ids(parents[:1])
3622
merger = _mod_merge.Merger.from_revision_ids(pb,
3624
merger.interesting_ids = interesting_ids
3625
merger.merge_type = merge_type
3626
merger.show_base = show_base
3627
merger.reprocess = reprocess
3628
conflicts = merger.do_merge()
3630
tree.set_parent_ids(parents)
3640
class cmd_revert(Command):
3641
"""Revert files to a previous revision.
3643
Giving a list of files will revert only those files. Otherwise, all files
3644
will be reverted. If the revision is not specified with '--revision', the
3645
last committed revision is used.
3647
To remove only some changes, without reverting to a prior version, use
3648
merge instead. For example, "merge . --revision -2..-3" will remove the
3649
changes introduced by -2, without affecting the changes introduced by -1.
3650
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3652
By default, any files that have been manually changed will be backed up
3653
first. (Files changed only by merge are not backed up.) Backup files have
3654
'.~#~' appended to their name, where # is a number.
3656
When you provide files, you can use their current pathname or the pathname
3657
from the target revision. So you can use revert to "undelete" a file by
3658
name. If you name a directory, all the contents of that directory will be
3661
Any files that have been newly added since that revision will be deleted,
3662
with a backup kept if appropriate. Directories containing unknown files
3663
will not be deleted.
3665
The working tree contains a list of pending merged revisions, which will
3666
be included as parents in the next commit. Normally, revert clears that
3667
list as well as reverting the files. If any files are specified, revert
3668
leaves the pending merge list alone and reverts only the files. Use "bzr
3669
revert ." in the tree root to revert all files but keep the merge record,
3670
and "bzr revert --forget-merges" to clear the pending merge list without
3671
reverting any files.
3674
_see_also = ['cat', 'export']
3677
Option('no-backup', "Do not save backups of reverted files."),
3678
Option('forget-merges',
3679
'Remove pending merge marker, without changing any files.'),
3681
takes_args = ['file*']
3683
def run(self, revision=None, no_backup=False, file_list=None,
3684
forget_merges=None):
3685
tree, file_list = tree_files(file_list)
3689
tree.set_parent_ids(tree.get_parent_ids()[:1])
3691
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3696
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3697
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
3698
pb = ui.ui_factory.nested_progress_bar()
3700
tree.revert(file_list, rev_tree, not no_backup, pb,
3701
report_changes=True)
3706
class cmd_assert_fail(Command):
3707
"""Test reporting of assertion failures"""
3708
# intended just for use in testing
3713
raise AssertionError("always fails")
3716
class cmd_help(Command):
3717
"""Show help on a command or other topic.
3720
_see_also = ['topics']
3722
Option('long', 'Show help on all commands.'),
3724
takes_args = ['topic?']
3725
aliases = ['?', '--help', '-?', '-h']
3728
def run(self, topic=None, long=False):
3730
if topic is None and long:
3732
bzrlib.help.help(topic)
3735
class cmd_shell_complete(Command):
3736
"""Show appropriate completions for context.
3738
For a list of all available commands, say 'bzr shell-complete'.
3740
takes_args = ['context?']
3745
def run(self, context=None):
3746
import shellcomplete
3747
shellcomplete.shellcomplete(context)
3750
class cmd_missing(Command):
3751
"""Show unmerged/unpulled revisions between two branches.
3753
OTHER_BRANCH may be local or remote.
3755
To filter on a range of revirions, you can use the command -r begin..end
3756
-r revision requests a specific revision, -r ..end or -r begin.. are
3761
Determine the missing revisions between this and the branch at the
3762
remembered pull location::
3766
Determine the missing revisions between this and another branch::
3768
bzr missing http://server/branch
3770
Determine the missing revisions up to a specific revision on the other
3773
bzr missing -r ..-10
3775
Determine the missing revisions up to a specific revision on this
3778
bzr missing --my-revision ..-10
3781
_see_also = ['merge', 'pull']
3782
takes_args = ['other_branch?']
3784
Option('reverse', 'Reverse the order of revisions.'),
3786
'Display changes in the local branch only.'),
3787
Option('this' , 'Same as --mine-only.'),
3788
Option('theirs-only',
3789
'Display changes in the remote branch only.'),
3790
Option('other', 'Same as --theirs-only.'),
3794
custom_help('revision',
3795
help='Filter on other branch revisions (inclusive). '
3796
'See "help revisionspec" for details.'),
3797
Option('my-revision',
3798
type=_parse_revision_str,
3799
help='Filter on local branch revisions (inclusive). '
3800
'See "help revisionspec" for details.'),
3801
Option('include-merges', 'Show merged revisions.'),
3803
encoding_type = 'replace'
3806
def run(self, other_branch=None, reverse=False, mine_only=False,
3808
log_format=None, long=False, short=False, line=False,
3809
show_ids=False, verbose=False, this=False, other=False,
3810
include_merges=False, revision=None, my_revision=None):
3811
from bzrlib.missing import find_unmerged, iter_log_revisions
3820
# TODO: We should probably check that we don't have mine-only and
3821
# theirs-only set, but it gets complicated because we also have
3822
# this and other which could be used.
3829
local_branch = Branch.open_containing(u".")[0]
3830
parent = local_branch.get_parent()
3831
if other_branch is None:
3832
other_branch = parent
3833
if other_branch is None:
3834
raise errors.BzrCommandError("No peer location known"
3836
display_url = urlutils.unescape_for_display(parent,
3838
message("Using saved parent location: "
3839
+ display_url + "\n")
3841
remote_branch = Branch.open(other_branch)
3842
if remote_branch.base == local_branch.base:
3843
remote_branch = local_branch
3845
local_revid_range = _revision_range_to_revid_range(
3846
_get_revision_range(my_revision, local_branch,
3849
remote_revid_range = _revision_range_to_revid_range(
3850
_get_revision_range(revision,
3851
remote_branch, self.name()))
3853
local_branch.lock_read()
3855
remote_branch.lock_read()
3857
local_extra, remote_extra = find_unmerged(
3858
local_branch, remote_branch, restrict,
3859
backward=not reverse,
3860
include_merges=include_merges,
3861
local_revid_range=local_revid_range,
3862
remote_revid_range=remote_revid_range)
3864
if log_format is None:
3865
registry = log.log_formatter_registry
3866
log_format = registry.get_default(local_branch)
3867
lf = log_format(to_file=self.outf,
3869
show_timezone='original')
3872
if local_extra and not theirs_only:
3873
message("You have %d extra revision(s):\n" %
3875
for revision in iter_log_revisions(local_extra,
3876
local_branch.repository,
3878
lf.log_revision(revision)
3879
printed_local = True
3882
printed_local = False
3884
if remote_extra and not mine_only:
3885
if printed_local is True:
3887
message("You are missing %d revision(s):\n" %
3889
for revision in iter_log_revisions(remote_extra,
3890
remote_branch.repository,
3892
lf.log_revision(revision)
3895
if mine_only and not local_extra:
3896
# We checked local, and found nothing extra
3897
message('This branch is up to date.\n')
3898
elif theirs_only and not remote_extra:
3899
# We checked remote, and found nothing extra
3900
message('Other branch is up to date.\n')
3901
elif not (mine_only or theirs_only or local_extra or
3903
# We checked both branches, and neither one had extra
3905
message("Branches are up to date.\n")
3907
remote_branch.unlock()
3909
local_branch.unlock()
3910
if not status_code and parent is None and other_branch is not None:
3911
local_branch.lock_write()
3913
# handle race conditions - a parent might be set while we run.
3914
if local_branch.get_parent() is None:
3915
local_branch.set_parent(remote_branch.base)
3917
local_branch.unlock()
3921
class cmd_pack(Command):
3922
"""Compress the data within a repository."""
3924
_see_also = ['repositories']
3925
takes_args = ['branch_or_repo?']
3927
def run(self, branch_or_repo='.'):
3928
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3930
branch = dir.open_branch()
3931
repository = branch.repository
3932
except errors.NotBranchError:
3933
repository = dir.open_repository()
3937
class cmd_plugins(Command):
3938
"""List the installed plugins.
3940
This command displays the list of installed plugins including
3941
version of plugin and a short description of each.
3943
--verbose shows the path where each plugin is located.
3945
A plugin is an external component for Bazaar that extends the
3946
revision control system, by adding or replacing code in Bazaar.
3947
Plugins can do a variety of things, including overriding commands,
3948
adding new commands, providing additional network transports and
3949
customizing log output.
3951
See the Bazaar web site, http://bazaar-vcs.org, for further
3952
information on plugins including where to find them and how to
3953
install them. Instructions are also provided there on how to
3954
write new plugins using the Python programming language.
3956
takes_options = ['verbose']
3959
def run(self, verbose=False):
3960
import bzrlib.plugin
3961
from inspect import getdoc
3963
for name, plugin in bzrlib.plugin.plugins().items():
3964
version = plugin.__version__
3965
if version == 'unknown':
3967
name_ver = '%s %s' % (name, version)
3968
d = getdoc(plugin.module)
3970
doc = d.split('\n')[0]
3972
doc = '(no description)'
3973
result.append((name_ver, doc, plugin.path()))
3974
for name_ver, doc, path in sorted(result):
3982
class cmd_testament(Command):
3983
"""Show testament (signing-form) of a revision."""
3986
Option('long', help='Produce long-format testament.'),
3988
help='Produce a strict-format testament.')]
3989
takes_args = ['branch?']
3991
def run(self, branch=u'.', revision=None, long=False, strict=False):
3992
from bzrlib.testament import Testament, StrictTestament
3994
testament_class = StrictTestament
3996
testament_class = Testament
3998
b = Branch.open_containing(branch)[0]
4000
b = Branch.open(branch)
4003
if revision is None:
4004
rev_id = b.last_revision()
4006
rev_id = revision[0].as_revision_id(b)
4007
t = testament_class.from_revision(b.repository, rev_id)
4009
sys.stdout.writelines(t.as_text_lines())
4011
sys.stdout.write(t.as_short_text())
4016
class cmd_annotate(Command):
4017
"""Show the origin of each line in a file.
4019
This prints out the given file with an annotation on the left side
4020
indicating which revision, author and date introduced the change.
4022
If the origin is the same for a run of consecutive lines, it is
4023
shown only at the top, unless the --all option is given.
4025
# TODO: annotate directories; showing when each file was last changed
4026
# TODO: if the working copy is modified, show annotations on that
4027
# with new uncommitted lines marked
4028
aliases = ['ann', 'blame', 'praise']
4029
takes_args = ['filename']
4030
takes_options = [Option('all', help='Show annotations on all lines.'),
4031
Option('long', help='Show commit date in annotations.'),
4035
encoding_type = 'exact'
4038
def run(self, filename, all=False, long=False, revision=None,
4040
from bzrlib.annotate import annotate_file, annotate_file_tree
4041
wt, branch, relpath = \
4042
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4048
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4050
file_id = wt.path2id(relpath)
4052
file_id = tree.path2id(relpath)
4054
raise errors.NotVersionedError(filename)
4055
file_version = tree.inventory[file_id].revision
4056
if wt is not None and revision is None:
4057
# If there is a tree and we're not annotating historical
4058
# versions, annotate the working tree's content.
4059
annotate_file_tree(wt, file_id, self.outf, long, all,
4062
annotate_file(branch, file_version, file_id, long, all, self.outf,
4071
class cmd_re_sign(Command):
4072
"""Create a digital signature for an existing revision."""
4073
# TODO be able to replace existing ones.
4075
hidden = True # is this right ?
4076
takes_args = ['revision_id*']
4077
takes_options = ['revision']
4079
def run(self, revision_id_list=None, revision=None):
4080
if revision_id_list is not None and revision is not None:
4081
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4082
if revision_id_list is None and revision is None:
4083
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4084
b = WorkingTree.open_containing(u'.')[0].branch
4087
return self._run(b, revision_id_list, revision)
4091
def _run(self, b, revision_id_list, revision):
4092
import bzrlib.gpg as gpg
4093
gpg_strategy = gpg.GPGStrategy(b.get_config())
4094
if revision_id_list is not None:
4095
b.repository.start_write_group()
4097
for revision_id in revision_id_list:
4098
b.repository.sign_revision(revision_id, gpg_strategy)
4100
b.repository.abort_write_group()
4103
b.repository.commit_write_group()
4104
elif revision is not None:
4105
if len(revision) == 1:
4106
revno, rev_id = revision[0].in_history(b)
4107
b.repository.start_write_group()
4109
b.repository.sign_revision(rev_id, gpg_strategy)
4111
b.repository.abort_write_group()
4114
b.repository.commit_write_group()
4115
elif len(revision) == 2:
4116
# are they both on rh- if so we can walk between them
4117
# might be nice to have a range helper for arbitrary
4118
# revision paths. hmm.
4119
from_revno, from_revid = revision[0].in_history(b)
4120
to_revno, to_revid = revision[1].in_history(b)
4121
if to_revid is None:
4122
to_revno = b.revno()
4123
if from_revno is None or to_revno is None:
4124
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
4125
b.repository.start_write_group()
4127
for revno in range(from_revno, to_revno + 1):
4128
b.repository.sign_revision(b.get_rev_id(revno),
4131
b.repository.abort_write_group()
4134
b.repository.commit_write_group()
4136
raise errors.BzrCommandError('Please supply either one revision, or a range.')
4139
class cmd_bind(Command):
4140
"""Convert the current branch into a checkout of the supplied branch.
4142
Once converted into a checkout, commits must succeed on the master branch
4143
before they will be applied to the local branch.
4145
Bound branches use the nickname of its master branch unless it is set
4146
locally, in which case binding will update the the local nickname to be
4150
_see_also = ['checkouts', 'unbind']
4151
takes_args = ['location?']
4154
def run(self, location=None):
4155
b, relpath = Branch.open_containing(u'.')
4156
if location is None:
4158
location = b.get_old_bound_location()
4159
except errors.UpgradeRequired:
4160
raise errors.BzrCommandError('No location supplied. '
4161
'This format does not remember old locations.')
4163
if location is None:
4164
raise errors.BzrCommandError('No location supplied and no '
4165
'previous location known')
4166
b_other = Branch.open(location)
4169
except errors.DivergedBranches:
4170
raise errors.BzrCommandError('These branches have diverged.'
4171
' Try merging, and then bind again.')
4172
if b.get_config().has_explicit_nickname():
4173
b.nick = b_other.nick
4176
class cmd_unbind(Command):
4177
"""Convert the current checkout into a regular branch.
4179
After unbinding, the local branch is considered independent and subsequent
4180
commits will be local only.
4183
_see_also = ['checkouts', 'bind']
4188
b, relpath = Branch.open_containing(u'.')
4190
raise errors.BzrCommandError('Local branch is not bound')
4193
class cmd_uncommit(Command):
4194
"""Remove the last committed revision.
4196
--verbose will print out what is being removed.
4197
--dry-run will go through all the motions, but not actually
4200
If --revision is specified, uncommit revisions to leave the branch at the
4201
specified revision. For example, "bzr uncommit -r 15" will leave the
4202
branch at revision 15.
4204
Uncommit leaves the working tree ready for a new commit. The only change
4205
it may make is to restore any pending merges that were present before
4209
# TODO: jam 20060108 Add an option to allow uncommit to remove
4210
# unreferenced information in 'branch-as-repository' branches.
4211
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
4212
# information in shared branches as well.
4213
_see_also = ['commit']
4214
takes_options = ['verbose', 'revision',
4215
Option('dry-run', help='Don\'t actually make changes.'),
4216
Option('force', help='Say yes to all questions.'),
4218
help="Only remove the commits from the local branch"
4219
" when in a checkout."
4222
takes_args = ['location?']
4224
encoding_type = 'replace'
4226
def run(self, location=None,
4227
dry_run=False, verbose=False,
4228
revision=None, force=False, local=False):
4229
if location is None:
4231
control, relpath = bzrdir.BzrDir.open_containing(location)
4233
tree = control.open_workingtree()
4235
except (errors.NoWorkingTree, errors.NotLocalUrl):
4237
b = control.open_branch()
4239
if tree is not None:
4244
return self._run(b, tree, dry_run, verbose, revision, force,
4247
if tree is not None:
4252
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4253
from bzrlib.log import log_formatter, show_log
4254
from bzrlib.uncommit import uncommit
4256
last_revno, last_rev_id = b.last_revision_info()
4259
if revision is None:
4261
rev_id = last_rev_id
4263
# 'bzr uncommit -r 10' actually means uncommit
4264
# so that the final tree is at revno 10.
4265
# but bzrlib.uncommit.uncommit() actually uncommits
4266
# the revisions that are supplied.
4267
# So we need to offset it by one
4268
revno = revision[0].in_history(b).revno + 1
4269
if revno <= last_revno:
4270
rev_id = b.get_rev_id(revno)
4272
if rev_id is None or _mod_revision.is_null(rev_id):
4273
self.outf.write('No revisions to uncommit.\n')
4276
lf = log_formatter('short',
4278
show_timezone='original')
4283
direction='forward',
4284
start_revision=revno,
4285
end_revision=last_revno)
4288
print 'Dry-run, pretending to remove the above revisions.'
4290
val = raw_input('Press <enter> to continue')
4292
print 'The above revision(s) will be removed.'
4294
val = raw_input('Are you sure [y/N]? ')
4295
if val.lower() not in ('y', 'yes'):
4299
mutter('Uncommitting from {%s} to {%s}',
4300
last_rev_id, rev_id)
4301
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4302
revno=revno, local=local)
4303
note('You can restore the old tip by running:\n'
4304
' bzr pull . -r revid:%s', last_rev_id)
4307
class cmd_break_lock(Command):
4308
"""Break a dead lock on a repository, branch or working directory.
4310
CAUTION: Locks should only be broken when you are sure that the process
4311
holding the lock has been stopped.
4313
You can get information on what locks are open via the 'bzr info' command.
4318
takes_args = ['location?']
4320
def run(self, location=None, show=False):
4321
if location is None:
4323
control, relpath = bzrdir.BzrDir.open_containing(location)
4325
control.break_lock()
4326
except NotImplementedError:
4330
class cmd_wait_until_signalled(Command):
4331
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4333
This just prints a line to signal when it is ready, then blocks on stdin.
4339
sys.stdout.write("running\n")
4341
sys.stdin.readline()
4344
class cmd_serve(Command):
4345
"""Run the bzr server."""
4347
aliases = ['server']
4351
help='Serve on stdin/out for use from inetd or sshd.'),
4353
help='Listen for connections on nominated port of the form '
4354
'[hostname:]portnumber. Passing 0 as the port number will '
4355
'result in a dynamically allocated port. The default port is '
4359
help='Serve contents of this directory.',
4361
Option('allow-writes',
4362
help='By default the server is a readonly server. Supplying '
4363
'--allow-writes enables write access to the contents of '
4364
'the served directory and below.'
4368
def run_smart_server(self, smart_server):
4369
"""Run 'smart_server' forever, with no UI output at all."""
4370
# For the duration of this server, no UI output is permitted. note
4371
# that this may cause problems with blackbox tests. This should be
4372
# changed with care though, as we dont want to use bandwidth sending
4373
# progress over stderr to smart server clients!
4374
from bzrlib import lockdir
4375
old_factory = ui.ui_factory
4376
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4378
ui.ui_factory = ui.SilentUIFactory()
4379
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4380
smart_server.serve()
4382
ui.ui_factory = old_factory
4383
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4385
def get_host_and_port(self, port):
4386
"""Return the host and port to run the smart server on.
4388
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4389
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4391
If 'port' has a colon in it, the string before the colon will be
4392
interpreted as the host.
4394
:param port: A string of the port to run the server on.
4395
:return: A tuple of (host, port), where 'host' is a host name or IP,
4396
and port is an integer TCP/IP port.
4398
from bzrlib.smart import medium
4399
host = medium.BZR_DEFAULT_INTERFACE
4401
port = medium.BZR_DEFAULT_PORT
4404
host, port = port.split(':')
4408
def get_smart_server(self, transport, inet, port):
4409
"""Construct a smart server.
4411
:param transport: The base transport from which branches will be
4413
:param inet: If True, serve over stdin and stdout. Used for running
4415
:param port: The port to listen on. By default, it's `
4416
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4418
:return: A smart server.
4420
from bzrlib.smart import medium, server
4422
smart_server = medium.SmartServerPipeStreamMedium(
4423
sys.stdin, sys.stdout, transport)
4425
host, port = self.get_host_and_port(port)
4426
smart_server = server.SmartTCPServer(
4427
transport, host=host, port=port)
4428
note('listening on port: %s' % smart_server.port)
4431
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4432
from bzrlib.transport import get_transport
4433
from bzrlib.transport.chroot import ChrootServer
4434
if directory is None:
4435
directory = os.getcwd()
4436
url = urlutils.local_path_to_url(directory)
4437
if not allow_writes:
4438
url = 'readonly+' + url
4439
chroot_server = ChrootServer(get_transport(url))
4440
chroot_server.setUp()
4441
t = get_transport(chroot_server.get_url())
4442
smart_server = self.get_smart_server(t, inet, port)
4443
self.run_smart_server(smart_server)
4446
class cmd_join(Command):
4447
"""Combine a subtree into its containing tree.
4449
This command is for experimental use only. It requires the target tree
4450
to be in dirstate-with-subtree format, which cannot be converted into
4453
The TREE argument should be an independent tree, inside another tree, but
4454
not part of it. (Such trees can be produced by "bzr split", but also by
4455
running "bzr branch" with the target inside a tree.)
4457
The result is a combined tree, with the subtree no longer an independant
4458
part. This is marked as a merge of the subtree into the containing tree,
4459
and all history is preserved.
4461
If --reference is specified, the subtree retains its independence. It can
4462
be branched by itself, and can be part of multiple projects at the same
4463
time. But operations performed in the containing tree, such as commit
4464
and merge, will recurse into the subtree.
4467
_see_also = ['split']
4468
takes_args = ['tree']
4470
Option('reference', help='Join by reference.'),
4474
def run(self, tree, reference=False):
4475
sub_tree = WorkingTree.open(tree)
4476
parent_dir = osutils.dirname(sub_tree.basedir)
4477
containing_tree = WorkingTree.open_containing(parent_dir)[0]
4478
repo = containing_tree.branch.repository
4479
if not repo.supports_rich_root():
4480
raise errors.BzrCommandError(
4481
"Can't join trees because %s doesn't support rich root data.\n"
4482
"You can use bzr upgrade on the repository."
4486
containing_tree.add_reference(sub_tree)
4487
except errors.BadReferenceTarget, e:
4488
# XXX: Would be better to just raise a nicely printable
4489
# exception from the real origin. Also below. mbp 20070306
4490
raise errors.BzrCommandError("Cannot join %s. %s" %
4494
containing_tree.subsume(sub_tree)
4495
except errors.BadSubsumeSource, e:
4496
raise errors.BzrCommandError("Cannot join %s. %s" %
4500
class cmd_split(Command):
4501
"""Split a subdirectory of a tree into a separate tree.
4503
This command will produce a target tree in a format that supports
4504
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4505
converted into earlier formats like 'dirstate-tags'.
4507
The TREE argument should be a subdirectory of a working tree. That
4508
subdirectory will be converted into an independent tree, with its own
4509
branch. Commits in the top-level tree will not apply to the new subtree.
4512
# join is not un-hidden yet
4513
#_see_also = ['join']
4514
takes_args = ['tree']
4516
def run(self, tree):
4517
containing_tree, subdir = WorkingTree.open_containing(tree)
4518
sub_id = containing_tree.path2id(subdir)
4520
raise errors.NotVersionedError(subdir)
4522
containing_tree.extract(sub_id)
4523
except errors.RootNotRich:
4524
raise errors.UpgradeRequired(containing_tree.branch.base)
4527
class cmd_merge_directive(Command):
4528
"""Generate a merge directive for auto-merge tools.
4530
A directive requests a merge to be performed, and also provides all the
4531
information necessary to do so. This means it must either include a
4532
revision bundle, or the location of a branch containing the desired
4535
A submit branch (the location to merge into) must be supplied the first
4536
time the command is issued. After it has been supplied once, it will
4537
be remembered as the default.
4539
A public branch is optional if a revision bundle is supplied, but required
4540
if --diff or --plain is specified. It will be remembered as the default
4541
after the first use.
4544
takes_args = ['submit_branch?', 'public_branch?']
4548
_see_also = ['send']
4551
RegistryOption.from_kwargs('patch-type',
4552
'The type of patch to include in the directive.',
4554
value_switches=True,
4556
bundle='Bazaar revision bundle (default).',
4557
diff='Normal unified diff.',
4558
plain='No patch, just directive.'),
4559
Option('sign', help='GPG-sign the directive.'), 'revision',
4560
Option('mail-to', type=str,
4561
help='Instead of printing the directive, email to this address.'),
4562
Option('message', type=str, short_name='m',
4563
help='Message to use when committing this merge.')
4566
encoding_type = 'exact'
4568
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4569
sign=False, revision=None, mail_to=None, message=None):
4570
from bzrlib.revision import ensure_null, NULL_REVISION
4571
include_patch, include_bundle = {
4572
'plain': (False, False),
4573
'diff': (True, False),
4574
'bundle': (True, True),
4576
branch = Branch.open('.')
4577
stored_submit_branch = branch.get_submit_branch()
4578
if submit_branch is None:
4579
submit_branch = stored_submit_branch
4581
if stored_submit_branch is None:
4582
branch.set_submit_branch(submit_branch)
4583
if submit_branch is None:
4584
submit_branch = branch.get_parent()
4585
if submit_branch is None:
4586
raise errors.BzrCommandError('No submit branch specified or known')
4588
stored_public_branch = branch.get_public_branch()
4589
if public_branch is None:
4590
public_branch = stored_public_branch
4591
elif stored_public_branch is None:
4592
branch.set_public_branch(public_branch)
4593
if not include_bundle and public_branch is None:
4594
raise errors.BzrCommandError('No public branch specified or'
4596
base_revision_id = None
4597
if revision is not None:
4598
if len(revision) > 2:
4599
raise errors.BzrCommandError('bzr merge-directive takes '
4600
'at most two one revision identifiers')
4601
revision_id = revision[-1].as_revision_id(branch)
4602
if len(revision) == 2:
4603
base_revision_id = revision[0].as_revision_id(branch)
4605
revision_id = branch.last_revision()
4606
revision_id = ensure_null(revision_id)
4607
if revision_id == NULL_REVISION:
4608
raise errors.BzrCommandError('No revisions to bundle.')
4609
directive = merge_directive.MergeDirective2.from_objects(
4610
branch.repository, revision_id, time.time(),
4611
osutils.local_time_offset(), submit_branch,
4612
public_branch=public_branch, include_patch=include_patch,
4613
include_bundle=include_bundle, message=message,
4614
base_revision_id=base_revision_id)
4617
self.outf.write(directive.to_signed(branch))
4619
self.outf.writelines(directive.to_lines())
4621
message = directive.to_email(mail_to, branch, sign)
4622
s = SMTPConnection(branch.get_config())
4623
s.send_email(message)
4626
class cmd_send(Command):
4627
"""Mail or create a merge-directive for submitting changes.
4629
A merge directive provides many things needed for requesting merges:
4631
* A machine-readable description of the merge to perform
4633
* An optional patch that is a preview of the changes requested
4635
* An optional bundle of revision data, so that the changes can be applied
4636
directly from the merge directive, without retrieving data from a
4639
If --no-bundle is specified, then public_branch is needed (and must be
4640
up-to-date), so that the receiver can perform the merge using the
4641
public_branch. The public_branch is always included if known, so that
4642
people can check it later.
4644
The submit branch defaults to the parent, but can be overridden. Both
4645
submit branch and public branch will be remembered if supplied.
4647
If a public_branch is known for the submit_branch, that public submit
4648
branch is used in the merge instructions. This means that a local mirror
4649
can be used as your actual submit branch, once you have set public_branch
4652
Mail is sent using your preferred mail program. This should be transparent
4653
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4654
If the preferred client can't be found (or used), your editor will be used.
4656
To use a specific mail program, set the mail_client configuration option.
4657
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4658
specific clients are "claws", "evolution", "kmail", "mutt", and
4659
"thunderbird"; generic options are "default", "editor", "emacsclient",
4660
"mapi", and "xdg-email". Plugins may also add supported clients.
4662
If mail is being sent, a to address is required. This can be supplied
4663
either on the commandline, by setting the submit_to configuration
4664
option in the branch itself or the child_submit_to configuration option
4665
in the submit branch.
4667
Two formats are currently supported: "4" uses revision bundle format 4 and
4668
merge directive format 2. It is significantly faster and smaller than
4669
older formats. It is compatible with Bazaar 0.19 and later. It is the
4670
default. "0.9" uses revision bundle format 0.9 and merge directive
4671
format 1. It is compatible with Bazaar 0.12 - 0.18.
4673
Merge directives are applied using the merge command or the pull command.
4676
encoding_type = 'exact'
4678
_see_also = ['merge', 'pull']
4680
takes_args = ['submit_branch?', 'public_branch?']
4684
help='Do not include a bundle in the merge directive.'),
4685
Option('no-patch', help='Do not include a preview patch in the merge'
4688
help='Remember submit and public branch.'),
4690
help='Branch to generate the submission from, '
4691
'rather than the one containing the working directory.',
4694
Option('output', short_name='o',
4695
help='Write merge directive to this file; '
4696
'use - for stdout.',
4698
Option('mail-to', help='Mail the request to this address.',
4702
RegistryOption.from_kwargs('format',
4703
'Use the specified output format.',
4704
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4705
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4708
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4709
no_patch=False, revision=None, remember=False, output=None,
4710
format='4', mail_to=None, message=None, **kwargs):
4711
return self._run(submit_branch, revision, public_branch, remember,
4712
format, no_bundle, no_patch, output,
4713
kwargs.get('from', '.'), mail_to, message)
4715
def _run(self, submit_branch, revision, public_branch, remember, format,
4716
no_bundle, no_patch, output, from_, mail_to, message):
4717
from bzrlib.revision import NULL_REVISION
4718
branch = Branch.open_containing(from_)[0]
4720
outfile = cStringIO.StringIO()
4724
outfile = open(output, 'wb')
4725
# we may need to write data into branch's repository to calculate
4730
config = branch.get_config()
4732
mail_to = config.get_user_option('submit_to')
4733
mail_client = config.get_mail_client()
4734
if remember and submit_branch is None:
4735
raise errors.BzrCommandError(
4736
'--remember requires a branch to be specified.')
4737
stored_submit_branch = branch.get_submit_branch()
4738
remembered_submit_branch = None
4739
if submit_branch is None:
4740
submit_branch = stored_submit_branch
4741
remembered_submit_branch = "submit"
4743
if stored_submit_branch is None or remember:
4744
branch.set_submit_branch(submit_branch)
4745
if submit_branch is None:
4746
submit_branch = branch.get_parent()
4747
remembered_submit_branch = "parent"
4748
if submit_branch is None:
4749
raise errors.BzrCommandError('No submit branch known or'
4751
if remembered_submit_branch is not None:
4752
note('Using saved %s location "%s" to determine what '
4753
'changes to submit.', remembered_submit_branch,
4757
submit_config = Branch.open(submit_branch).get_config()
4758
mail_to = submit_config.get_user_option("child_submit_to")
4760
stored_public_branch = branch.get_public_branch()
4761
if public_branch is None:
4762
public_branch = stored_public_branch
4763
elif stored_public_branch is None or remember:
4764
branch.set_public_branch(public_branch)
4765
if no_bundle and public_branch is None:
4766
raise errors.BzrCommandError('No public branch specified or'
4768
base_revision_id = None
4770
if revision is not None:
4771
if len(revision) > 2:
4772
raise errors.BzrCommandError('bzr send takes '
4773
'at most two one revision identifiers')
4774
revision_id = revision[-1].as_revision_id(branch)
4775
if len(revision) == 2:
4776
base_revision_id = revision[0].as_revision_id(branch)
4777
if revision_id is None:
4778
revision_id = branch.last_revision()
4779
if revision_id == NULL_REVISION:
4780
raise errors.BzrCommandError('No revisions to submit.')
4782
directive = merge_directive.MergeDirective2.from_objects(
4783
branch.repository, revision_id, time.time(),
4784
osutils.local_time_offset(), submit_branch,
4785
public_branch=public_branch, include_patch=not no_patch,
4786
include_bundle=not no_bundle, message=message,
4787
base_revision_id=base_revision_id)
4788
elif format == '0.9':
4791
patch_type = 'bundle'
4793
raise errors.BzrCommandError('Format 0.9 does not'
4794
' permit bundle with no patch')
4800
directive = merge_directive.MergeDirective.from_objects(
4801
branch.repository, revision_id, time.time(),
4802
osutils.local_time_offset(), submit_branch,
4803
public_branch=public_branch, patch_type=patch_type,
4806
outfile.writelines(directive.to_lines())
4808
subject = '[MERGE] '
4809
if message is not None:
4812
revision = branch.repository.get_revision(revision_id)
4813
subject += revision.get_summary()
4814
basename = directive.get_disk_name(branch)
4815
mail_client.compose_merge_request(mail_to, subject,
4816
outfile.getvalue(), basename)
4823
class cmd_bundle_revisions(cmd_send):
4825
"""Create a merge-directive for submitting changes.
4827
A merge directive provides many things needed for requesting merges:
4829
* A machine-readable description of the merge to perform
4831
* An optional patch that is a preview of the changes requested
4833
* An optional bundle of revision data, so that the changes can be applied
4834
directly from the merge directive, without retrieving data from a
4837
If --no-bundle is specified, then public_branch is needed (and must be
4838
up-to-date), so that the receiver can perform the merge using the
4839
public_branch. The public_branch is always included if known, so that
4840
people can check it later.
4842
The submit branch defaults to the parent, but can be overridden. Both
4843
submit branch and public branch will be remembered if supplied.
4845
If a public_branch is known for the submit_branch, that public submit
4846
branch is used in the merge instructions. This means that a local mirror
4847
can be used as your actual submit branch, once you have set public_branch
4850
Two formats are currently supported: "4" uses revision bundle format 4 and
4851
merge directive format 2. It is significantly faster and smaller than
4852
older formats. It is compatible with Bazaar 0.19 and later. It is the
4853
default. "0.9" uses revision bundle format 0.9 and merge directive
4854
format 1. It is compatible with Bazaar 0.12 - 0.18.
4859
help='Do not include a bundle in the merge directive.'),
4860
Option('no-patch', help='Do not include a preview patch in the merge'
4863
help='Remember submit and public branch.'),
4865
help='Branch to generate the submission from, '
4866
'rather than the one containing the working directory.',
4869
Option('output', short_name='o', help='Write directive to this file.',
4872
RegistryOption.from_kwargs('format',
4873
'Use the specified output format.',
4874
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4875
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4877
aliases = ['bundle']
4879
_see_also = ['send', 'merge']
4883
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4884
no_patch=False, revision=None, remember=False, output=None,
4885
format='4', **kwargs):
4888
return self._run(submit_branch, revision, public_branch, remember,
4889
format, no_bundle, no_patch, output,
4890
kwargs.get('from', '.'), None, None)
4893
class cmd_tag(Command):
4894
"""Create, remove or modify a tag naming a revision.
4896
Tags give human-meaningful names to revisions. Commands that take a -r
4897
(--revision) option can be given -rtag:X, where X is any previously
4900
Tags are stored in the branch. Tags are copied from one branch to another
4901
along when you branch, push, pull or merge.
4903
It is an error to give a tag name that already exists unless you pass
4904
--force, in which case the tag is moved to point to the new revision.
4906
To rename a tag (change the name but keep it on the same revsion), run ``bzr
4907
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4910
_see_also = ['commit', 'tags']
4911
takes_args = ['tag_name']
4914
help='Delete this tag rather than placing it.',
4917
help='Branch in which to place the tag.',
4922
help='Replace existing tags.',
4927
def run(self, tag_name,
4933
branch, relpath = Branch.open_containing(directory)
4937
branch.tags.delete_tag(tag_name)
4938
self.outf.write('Deleted tag %s.\n' % tag_name)
4941
if len(revision) != 1:
4942
raise errors.BzrCommandError(
4943
"Tags can only be placed on a single revision, "
4945
revision_id = revision[0].as_revision_id(branch)
4947
revision_id = branch.last_revision()
4948
if (not force) and branch.tags.has_tag(tag_name):
4949
raise errors.TagAlreadyExists(tag_name)
4950
branch.tags.set_tag(tag_name, revision_id)
4951
self.outf.write('Created tag %s.\n' % tag_name)
4956
class cmd_tags(Command):
4959
This command shows a table of tag names and the revisions they reference.
4965
help='Branch whose tags should be displayed.',
4969
RegistryOption.from_kwargs('sort',
4970
'Sort tags by different criteria.', title='Sorting',
4971
alpha='Sort tags lexicographically (default).',
4972
time='Sort tags chronologically.',
4985
branch, relpath = Branch.open_containing(directory)
4987
tags = branch.tags.get_tag_dict().items()
4994
graph = branch.repository.get_graph()
4995
rev1, rev2 = _get_revision_range(revision, branch, self.name())
4996
revid1, revid2 = rev1.rev_id, rev2.rev_id
4997
# only show revisions between revid1 and revid2 (inclusive)
4998
tags = [(tag, revid) for tag, revid in tags if
4999
graph.is_between(revid, revid1, revid2)]
5004
elif sort == 'time':
5006
for tag, revid in tags:
5008
revobj = branch.repository.get_revision(revid)
5009
except errors.NoSuchRevision:
5010
timestamp = sys.maxint # place them at the end
5012
timestamp = revobj.timestamp
5013
timestamps[revid] = timestamp
5014
tags.sort(key=lambda x: timestamps[x[1]])
5016
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5017
revno_map = branch.get_revision_id_to_revno_map()
5018
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5019
for tag, revid in tags ]
5020
for tag, revspec in tags:
5021
self.outf.write('%-20s %s\n' % (tag, revspec))
5024
class cmd_reconfigure(Command):
5025
"""Reconfigure the type of a bzr directory.
5027
A target configuration must be specified.
5029
For checkouts, the bind-to location will be auto-detected if not specified.
5030
The order of preference is
5031
1. For a lightweight checkout, the current bound location.
5032
2. For branches that used to be checkouts, the previously-bound location.
5033
3. The push location.
5034
4. The parent location.
5035
If none of these is available, --bind-to must be specified.
5038
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5039
takes_args = ['location?']
5041
RegistryOption.from_kwargs(
5043
title='Target type',
5044
help='The type to reconfigure the directory to.',
5045
value_switches=True, enum_switch=False,
5046
branch='Reconfigure to be an unbound branch with no working tree.',
5047
tree='Reconfigure to be an unbound branch with a working tree.',
5048
checkout='Reconfigure to be a bound branch with a working tree.',
5049
lightweight_checkout='Reconfigure to be a lightweight'
5050
' checkout (with no local history).',
5051
standalone='Reconfigure to be a standalone branch '
5052
'(i.e. stop using shared repository).',
5053
use_shared='Reconfigure to use a shared repository.',
5054
with_trees='Reconfigure repository to create '
5055
'working trees on branches by default.',
5056
with_no_trees='Reconfigure repository to not create '
5057
'working trees on branches by default.'
5059
Option('bind-to', help='Branch to bind checkout to.', type=str),
5061
help='Perform reconfiguration even if local changes'
5065
def run(self, location=None, target_type=None, bind_to=None, force=False):
5066
directory = bzrdir.BzrDir.open(location)
5067
if target_type is None:
5068
raise errors.BzrCommandError('No target configuration specified')
5069
elif target_type == 'branch':
5070
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5071
elif target_type == 'tree':
5072
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5073
elif target_type == 'checkout':
5074
reconfiguration = reconfigure.Reconfigure.to_checkout(
5076
elif target_type == 'lightweight-checkout':
5077
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5079
elif target_type == 'use-shared':
5080
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5081
elif target_type == 'standalone':
5082
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5083
elif target_type == 'with-trees':
5084
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5086
elif target_type == 'with-no-trees':
5087
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5089
reconfiguration.apply(force)
5092
class cmd_switch(Command):
5093
"""Set the branch of a checkout and update.
5095
For lightweight checkouts, this changes the branch being referenced.
5096
For heavyweight checkouts, this checks that there are no local commits
5097
versus the current bound branch, then it makes the local branch a mirror
5098
of the new location and binds to it.
5100
In both cases, the working tree is updated and uncommitted changes
5101
are merged. The user can commit or revert these as they desire.
5103
Pending merges need to be committed or reverted before using switch.
5105
The path to the branch to switch to can be specified relative to the parent
5106
directory of the current branch. For example, if you are currently in a
5107
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5110
Bound branches use the nickname of its master branch unless it is set
5111
locally, in which case switching will update the the local nickname to be
5115
takes_args = ['to_location']
5116
takes_options = [Option('force',
5117
help='Switch even if local commits will be lost.')
5120
def run(self, to_location, force=False):
5121
from bzrlib import switch
5123
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5124
branch = control_dir.open_branch()
5126
to_branch = Branch.open(to_location)
5127
except errors.NotBranchError:
5128
this_branch = control_dir.open_branch()
5129
# This may be a heavy checkout, where we want the master branch
5130
this_url = this_branch.get_bound_location()
5131
# If not, use a local sibling
5132
if this_url is None:
5133
this_url = this_branch.base
5134
to_branch = Branch.open(
5135
urlutils.join(this_url, '..', to_location))
5136
switch.switch(control_dir, to_branch, force)
5137
if branch.get_config().has_explicit_nickname():
5138
branch = control_dir.open_branch() #get the new branch!
5139
branch.nick = to_branch.nick
5140
note('Switched to branch: %s',
5141
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5144
class cmd_view(Command):
5145
"""Manage filtered views.
5147
Views provide a mask over the tree so that users can focus on
5148
a subset of a tree when doing their work. After creating a view,
5149
commands that support a list of files - status, diff, commit, etc -
5150
effectively have that list of files implicitly given each time.
5151
An explicit list of files can still be given but those files
5152
must be within the current view.
5154
In most cases, a view has a short life-span: it is created to make
5155
a selected change and is deleted once that change is committed.
5156
At other times, you may wish to create one or more named views
5157
and switch between them.
5159
To disable the current view without deleting it, you can switch to
5160
the pseudo view called ``off``. This can be useful when you need
5161
to see the whole tree for an operation or two (e.g. merge) but
5162
want to switch back to your view after that.
5165
To define the current view::
5167
bzr view file1 dir1 ...
5169
To list the current view::
5173
To delete the current view::
5177
To disable the current view without deleting it::
5179
bzr view --switch off
5181
To define a named view and switch to it::
5183
bzr view --name view-name file1 dir1 ...
5185
To list a named view::
5187
bzr view --name view-name
5189
To delete a named view::
5191
bzr view --name view-name --delete
5193
To switch to a named view::
5195
bzr view --switch view-name
5197
To list all views defined::
5201
To delete all views::
5203
bzr view --delete --all
5207
takes_args = ['file*']
5210
help='Apply list or delete action to all views.',
5213
help='Delete the view.',
5216
help='Name of the view to define, list or delete.',
5220
help='Name of the view to switch to.',
5225
def run(self, file_list,
5231
tree, file_list = tree_files(file_list, apply_view=False)
5232
current_view, view_dict = tree.views.get_view_info()
5237
raise errors.BzrCommandError(
5238
"Both --delete and a file list specified")
5240
raise errors.BzrCommandError(
5241
"Both --delete and --switch specified")
5243
tree.views.set_view_info(None, {})
5244
self.outf.write("Deleted all views.\n")
5246
raise errors.BzrCommandError("No current view to delete")
5248
tree.views.delete_view(name)
5249
self.outf.write("Deleted '%s' view.\n" % name)
5252
raise errors.BzrCommandError(
5253
"Both --switch and a file list specified")
5255
raise errors.BzrCommandError(
5256
"Both --switch and --all specified")
5257
elif switch == 'off':
5258
if current_view is None:
5259
raise errors.BzrCommandError("No current view to disable")
5260
tree.views.set_view_info(None, view_dict)
5261
self.outf.write("Disabled '%s' view.\n" % (current_view))
5263
tree.views.set_view_info(switch, view_dict)
5264
view_str = views.view_display_str(tree.views.lookup_view())
5265
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5268
self.outf.write('Views defined:\n')
5269
for view in sorted(view_dict):
5270
if view == current_view:
5274
view_str = views.view_display_str(view_dict[view])
5275
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5277
self.outf.write('No views defined.\n')
5280
# No name given and no current view set
5283
raise errors.BzrCommandError(
5284
"Cannot change the 'off' pseudo view")
5285
tree.views.set_view(name, sorted(file_list))
5286
view_str = views.view_display_str(tree.views.lookup_view())
5287
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5291
# No name given and no current view set
5292
self.outf.write('No current view.\n')
5294
view_str = views.view_display_str(tree.views.lookup_view(name))
5295
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5298
class cmd_hooks(Command):
5299
"""Show a branch's currently registered hooks.
5303
takes_args = ['path?']
5305
def run(self, path=None):
5308
branch_hooks = Branch.open(path).hooks
5309
for hook_type in branch_hooks:
5310
hooks = branch_hooks[hook_type]
5311
self.outf.write("%s:\n" % (hook_type,))
5314
self.outf.write(" %s\n" %
5315
(branch_hooks.get_hook_name(hook),))
5317
self.outf.write(" <no hooks installed>\n")
5320
class cmd_shelve(Command):
5321
"""Temporarily set aside some changes from the current tree.
5323
Shelve allows you to temporarily put changes you've made "on the shelf",
5324
ie. out of the way, until a later time when you can bring them back from
5325
the shelf with the 'unshelve' command. The changes are stored alongside
5326
your working tree, and so they aren't propagated along with your branch nor
5327
will they survive its deletion.
5329
If shelve --list is specified, previously-shelved changes are listed.
5331
Shelve is intended to help separate several sets of changes that have
5332
been inappropriately mingled. If you just want to get rid of all changes
5333
and you don't need to restore them later, use revert. If you want to
5334
shelve all text changes at once, use shelve --all.
5336
If filenames are specified, only the changes to those files will be
5337
shelved. Other files will be left untouched.
5339
If a revision is specified, changes since that revision will be shelved.
5341
You can put multiple items on the shelf, and by default, 'unshelve' will
5342
restore the most recently shelved changes.
5345
takes_args = ['file*']
5349
Option('all', help='Shelve all changes.'),
5351
RegistryOption('writer', 'Method to use for writing diffs.',
5352
bzrlib.option.diff_writer_registry,
5353
value_switches=True, enum_switch=False),
5355
Option('list', help='List shelved changes.'),
5357
_see_also = ['unshelve']
5359
def run(self, revision=None, all=False, file_list=None, message=None,
5360
writer=None, list=False):
5362
return self.run_for_list()
5363
from bzrlib.shelf_ui import Shelver
5365
writer = bzrlib.option.diff_writer_registry.get()
5367
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5369
except errors.UserAbort:
5372
def run_for_list(self):
5373
tree = WorkingTree.open_containing('.')[0]
5376
manager = tree.get_shelf_manager()
5377
shelves = manager.active_shelves()
5378
if len(shelves) == 0:
5379
note('No shelved changes.')
5381
for shelf_id in reversed(shelves):
5382
message = manager.get_metadata(shelf_id).get('message')
5384
message = '<no message>'
5385
self.outf.write('%3d: %s\n' % (shelf_id, message))
5391
class cmd_unshelve(Command):
5392
"""Restore shelved changes.
5394
By default, the most recently shelved changes are restored. However if you
5395
specify a shelf by id those changes will be restored instead. This works
5396
best when the changes don't depend on each other.
5399
takes_args = ['shelf_id?']
5401
RegistryOption.from_kwargs(
5402
'action', help="The action to perform.",
5403
enum_switch=False, value_switches=True,
5404
apply="Apply changes and remove from the shelf.",
5405
dry_run="Show changes, but do not apply or remove them.",
5406
delete_only="Delete changes without applying them."
5409
_see_also = ['shelve']
5411
def run(self, shelf_id=None, action='apply'):
5412
from bzrlib.shelf_ui import Unshelver
5413
Unshelver.from_args(shelf_id, action).run()
5416
def _create_prefix(cur_transport):
5417
needed = [cur_transport]
5418
# Recurse upwards until we can create a directory successfully
5420
new_transport = cur_transport.clone('..')
5421
if new_transport.base == cur_transport.base:
5422
raise errors.BzrCommandError(
5423
"Failed to create path prefix for %s."
5424
% cur_transport.base)
5426
new_transport.mkdir('.')
5427
except errors.NoSuchFile:
5428
needed.append(new_transport)
5429
cur_transport = new_transport
5432
# Now we only need to create child directories
5434
cur_transport = needed.pop()
5435
cur_transport.ensure_base()
5438
# these get imported and then picked up by the scan for cmd_*
5439
# TODO: Some more consistent way to split command definitions across files;
5440
# we do need to load at least some information about them to know of
5441
# aliases. ideally we would avoid loading the implementation until the
5442
# details were needed.
5443
from bzrlib.cmd_version_info import cmd_version_info
5444
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5445
from bzrlib.bundle.commands import (
5448
from bzrlib.sign_my_commits import cmd_sign_my_commits
5449
from bzrlib.weave_commands import cmd_versionedfile_list, \
5450
cmd_weave_plan_merge, cmd_weave_merge_text