1
# Copyright (C) 2004, 2005, 2006, 2007, 2008 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""builtin bzr commands"""
20
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
43
revision as _mod_revision,
50
from bzrlib.branch import Branch
51
from bzrlib.conflicts import ConflictList
52
from bzrlib.revisionspec import RevisionSpec
53
from bzrlib.smtp_connection import SMTPConnection
54
from bzrlib.workingtree import WorkingTree
57
from bzrlib.commands import Command, display_command
58
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
from bzrlib.trace import mutter, note, warning, is_quiet, info
62
def tree_files(file_list, default_branch=u'.'):
64
return internal_tree_files(file_list, default_branch)
65
except errors.FileInWrongBranch, e:
66
raise errors.BzrCommandError("%s is not in the same branch as %s" %
67
(e.path, file_list[0]))
70
# XXX: Bad function name; should possibly also be a class method of
71
# WorkingTree rather than a function.
72
def internal_tree_files(file_list, default_branch=u'.'):
73
"""Convert command-line paths to a WorkingTree and relative paths.
75
This is typically used for command-line processors that take one or
76
more filenames, and infer the workingtree that contains them.
78
The filenames given are not required to exist.
80
:param file_list: Filenames to convert.
82
:param default_branch: Fallback tree path to use if file_list is empty or
85
:return: workingtree, [relative_paths]
87
if file_list is None or len(file_list) == 0:
88
return WorkingTree.open_containing(default_branch)[0], file_list
89
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
90
return tree, safe_relpath_files(tree, file_list)
93
def safe_relpath_files(tree, file_list):
94
"""Convert file_list into a list of relpaths in tree.
96
:param tree: A tree to operate on.
97
:param file_list: A list of user provided paths or None.
98
:return: A list of relative paths.
99
:raises errors.PathNotChild: When a provided path is in a different tree
102
if file_list is None:
105
for filename in file_list:
107
new_list.append(tree.relpath(osutils.dereference_path(filename)))
108
except errors.PathNotChild:
109
raise errors.FileInWrongBranch(tree.branch, filename)
113
# TODO: Make sure no commands unconditionally use the working directory as a
114
# branch. If a filename argument is used, the first of them should be used to
115
# specify the branch. (Perhaps this can be factored out into some kind of
116
# Argument class, representing a file in a branch, where the first occurrence
119
class cmd_status(Command):
120
"""Display status summary.
122
This reports on versioned and unknown files, reporting them
123
grouped by state. Possible states are:
126
Versioned in the working copy but not in the previous revision.
129
Versioned in the previous revision but removed or deleted
133
Path of this file changed from the previous revision;
134
the text may also have changed. This includes files whose
135
parent directory was renamed.
138
Text has changed since the previous revision.
141
File kind has been changed (e.g. from file to directory).
144
Not versioned and not matching an ignore pattern.
146
To see ignored files use 'bzr ignored'. For details on the
147
changes to file texts, use 'bzr diff'.
149
Note that --short or -S gives status flags for each item, similar
150
to Subversion's status command. To get output similar to svn -q,
153
If no arguments are specified, the status of the entire working
154
directory is shown. Otherwise, only the status of the specified
155
files or directories is reported. If a directory is given, status
156
is reported for everything inside that directory.
158
If a revision argument is given, the status is calculated against
159
that revision, or between two revisions if two are provided.
162
# TODO: --no-recurse, --recurse options
164
takes_args = ['file*']
165
takes_options = ['show-ids', 'revision', 'change',
166
Option('short', help='Use short status indicators.',
168
Option('versioned', help='Only show versioned files.',
170
Option('no-pending', help='Don\'t show pending merges.',
173
aliases = ['st', 'stat']
175
encoding_type = 'replace'
176
_see_also = ['diff', 'revert', 'status-flags']
179
def run(self, show_ids=False, file_list=None, revision=None, short=False,
180
versioned=False, no_pending=False):
181
from bzrlib.status import show_tree_status
183
if revision and len(revision) > 2:
184
raise errors.BzrCommandError('bzr status --revision takes exactly'
185
' one or two revision specifiers')
187
tree, relfile_list = tree_files(file_list)
188
# Avoid asking for specific files when that is not needed.
189
if relfile_list == ['']:
191
# Don't disable pending merges for full trees other than '.'.
192
if file_list == ['.']:
194
# A specific path within a tree was given.
195
elif relfile_list is not None:
197
show_tree_status(tree, show_ids=show_ids,
198
specific_files=relfile_list, revision=revision,
199
to_file=self.outf, short=short, versioned=versioned,
200
show_pending=(not no_pending))
203
class cmd_cat_revision(Command):
204
"""Write out metadata for a revision.
206
The revision to print can either be specified by a specific
207
revision identifier, or you can use --revision.
211
takes_args = ['revision_id?']
212
takes_options = ['revision']
213
# cat-revision is more for frontends so should be exact
217
def run(self, revision_id=None, revision=None):
218
if revision_id is not None and revision is not None:
219
raise errors.BzrCommandError('You can only supply one of'
220
' revision_id or --revision')
221
if revision_id is None and revision is None:
222
raise errors.BzrCommandError('You must supply either'
223
' --revision or a revision_id')
224
b = WorkingTree.open_containing(u'.')[0].branch
226
# TODO: jam 20060112 should cat-revision always output utf-8?
227
if revision_id is not None:
228
revision_id = osutils.safe_revision_id(revision_id, warn=False)
230
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
231
except errors.NoSuchRevision:
232
msg = "The repository %s contains no revision %s." % (b.repository.base,
234
raise errors.BzrCommandError(msg)
235
elif revision is not None:
238
raise errors.BzrCommandError('You cannot specify a NULL'
240
rev_id = rev.as_revision_id(b)
241
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
244
class cmd_remove_tree(Command):
245
"""Remove the working tree from a given branch/checkout.
247
Since a lightweight checkout is little more than a working tree
248
this will refuse to run against one.
250
To re-create the working tree, use "bzr checkout".
252
_see_also = ['checkout', 'working-trees']
254
takes_args = ['location?']
256
def run(self, location='.'):
257
d = bzrdir.BzrDir.open(location)
260
working = d.open_workingtree()
261
except errors.NoWorkingTree:
262
raise errors.BzrCommandError("No working tree to remove")
263
except errors.NotLocalUrl:
264
raise errors.BzrCommandError("You cannot remove the working tree of a "
267
working_path = working.bzrdir.root_transport.base
268
branch_path = working.branch.bzrdir.root_transport.base
269
if working_path != branch_path:
270
raise errors.BzrCommandError("You cannot remove the working tree from "
271
"a lightweight checkout")
273
d.destroy_workingtree()
276
class cmd_revno(Command):
277
"""Show current revision number.
279
This is equal to the number of revisions on this branch.
283
takes_args = ['location?']
286
def run(self, location=u'.'):
287
self.outf.write(str(Branch.open_containing(location)[0].revno()))
288
self.outf.write('\n')
291
class cmd_revision_info(Command):
292
"""Show revision number and revision id for a given revision identifier.
295
takes_args = ['revision_info*']
296
takes_options = ['revision']
299
def run(self, revision=None, revision_info_list=[]):
302
if revision is not None:
303
revs.extend(revision)
304
if revision_info_list is not None:
305
for rev in revision_info_list:
306
revs.append(RevisionSpec.from_string(rev))
308
b = Branch.open_containing(u'.')[0]
311
revs.append(RevisionSpec.from_string('-1'))
314
revision_id = rev.as_revision_id(b)
316
revno = '%4d' % (b.revision_id_to_revno(revision_id))
317
except errors.NoSuchRevision:
318
dotted_map = b.get_revision_id_to_revno_map()
319
revno = '.'.join(str(i) for i in dotted_map[revision_id])
320
print '%s %s' % (revno, revision_id)
323
class cmd_add(Command):
324
"""Add specified files or directories.
326
In non-recursive mode, all the named items are added, regardless
327
of whether they were previously ignored. A warning is given if
328
any of the named files are already versioned.
330
In recursive mode (the default), files are treated the same way
331
but the behaviour for directories is different. Directories that
332
are already versioned do not give a warning. All directories,
333
whether already versioned or not, are searched for files or
334
subdirectories that are neither versioned or ignored, and these
335
are added. This search proceeds recursively into versioned
336
directories. If no names are given '.' is assumed.
338
Therefore simply saying 'bzr add' will version all files that
339
are currently unknown.
341
Adding a file whose parent directory is not versioned will
342
implicitly add the parent, and so on up to the root. This means
343
you should never need to explicitly add a directory, they'll just
344
get added when you add a file in the directory.
346
--dry-run will show which files would be added, but not actually
349
--file-ids-from will try to use the file ids from the supplied path.
350
It looks up ids trying to find a matching parent directory with the
351
same filename, and then by pure path. This option is rarely needed
352
but can be useful when adding the same logical file into two
353
branches that will be merged later (without showing the two different
354
adds as a conflict). It is also useful when merging another project
355
into a subdirectory of this one.
357
takes_args = ['file*']
360
help="Don't recursively add the contents of directories."),
362
help="Show what would be done, but don't actually do anything."),
364
Option('file-ids-from',
366
help='Lookup file ids from this tree.'),
368
encoding_type = 'replace'
369
_see_also = ['remove']
371
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
376
if file_ids_from is not None:
378
base_tree, base_path = WorkingTree.open_containing(
380
except errors.NoWorkingTree:
381
base_branch, base_path = Branch.open_containing(
383
base_tree = base_branch.basis_tree()
385
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
386
to_file=self.outf, should_print=(not is_quiet()))
388
action = bzrlib.add.AddAction(to_file=self.outf,
389
should_print=(not is_quiet()))
392
base_tree.lock_read()
394
file_list = self._maybe_expand_globs(file_list)
396
tree = WorkingTree.open_containing(file_list[0])[0]
398
tree = WorkingTree.open_containing(u'.')[0]
399
added, ignored = tree.smart_add(file_list, not
400
no_recurse, action=action, save=not dry_run)
402
if base_tree is not None:
406
for glob in sorted(ignored.keys()):
407
for path in ignored[glob]:
408
self.outf.write("ignored %s matching \"%s\"\n"
412
for glob, paths in ignored.items():
413
match_len += len(paths)
414
self.outf.write("ignored %d file(s).\n" % match_len)
415
self.outf.write("If you wish to add some of these files,"
416
" please add them by name.\n")
419
class cmd_mkdir(Command):
420
"""Create a new versioned directory.
422
This is equivalent to creating the directory and then adding it.
425
takes_args = ['dir+']
426
encoding_type = 'replace'
428
def run(self, dir_list):
431
wt, dd = WorkingTree.open_containing(d)
433
self.outf.write('added %s\n' % d)
436
class cmd_relpath(Command):
437
"""Show path of a file relative to root"""
439
takes_args = ['filename']
443
def run(self, filename):
444
# TODO: jam 20050106 Can relpath return a munged path if
445
# sys.stdout encoding cannot represent it?
446
tree, relpath = WorkingTree.open_containing(filename)
447
self.outf.write(relpath)
448
self.outf.write('\n')
451
class cmd_inventory(Command):
452
"""Show inventory of the current working copy or a revision.
454
It is possible to limit the output to a particular entry
455
type using the --kind option. For example: --kind file.
457
It is also possible to restrict the list of files to a specific
458
set. For example: bzr inventory --show-ids this/file
467
help='List entries of a particular kind: file, directory, symlink.',
470
takes_args = ['file*']
473
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
474
if kind and kind not in ['file', 'directory', 'symlink']:
475
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
477
work_tree, file_list = tree_files(file_list)
478
work_tree.lock_read()
480
if revision is not None:
481
if len(revision) > 1:
482
raise errors.BzrCommandError(
483
'bzr inventory --revision takes exactly one revision'
485
revision_id = revision[0].as_revision_id(work_tree.branch)
486
tree = work_tree.branch.repository.revision_tree(revision_id)
488
extra_trees = [work_tree]
494
if file_list is not None:
495
file_ids = tree.paths2ids(file_list, trees=extra_trees,
496
require_versioned=True)
497
# find_ids_across_trees may include some paths that don't
499
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
500
for file_id in file_ids if file_id in tree)
502
entries = tree.inventory.entries()
505
if tree is not work_tree:
508
for path, entry in entries:
509
if kind and kind != entry.kind:
512
self.outf.write('%-50s %s\n' % (path, entry.file_id))
514
self.outf.write(path)
515
self.outf.write('\n')
518
class cmd_mv(Command):
519
"""Move or rename a file.
522
bzr mv OLDNAME NEWNAME
524
bzr mv SOURCE... DESTINATION
526
If the last argument is a versioned directory, all the other names
527
are moved into it. Otherwise, there must be exactly two arguments
528
and the file is changed to a new name.
530
If OLDNAME does not exist on the filesystem but is versioned and
531
NEWNAME does exist on the filesystem but is not versioned, mv
532
assumes that the file has been manually moved and only updates
533
its internal inventory to reflect that change.
534
The same is valid when moving many SOURCE files to a DESTINATION.
536
Files cannot be moved between branches.
539
takes_args = ['names*']
540
takes_options = [Option("after", help="Move only the bzr identifier"
541
" of the file, because the file has already been moved."),
543
aliases = ['move', 'rename']
544
encoding_type = 'replace'
546
def run(self, names_list, after=False):
547
if names_list is None:
550
if len(names_list) < 2:
551
raise errors.BzrCommandError("missing file argument")
552
tree, rel_names = tree_files(names_list)
555
self._run(tree, names_list, rel_names, after)
559
def _run(self, tree, names_list, rel_names, after):
560
into_existing = osutils.isdir(names_list[-1])
561
if into_existing and len(names_list) == 2:
563
# a. case-insensitive filesystem and change case of dir
564
# b. move directory after the fact (if the source used to be
565
# a directory, but now doesn't exist in the working tree
566
# and the target is an existing directory, just rename it)
567
if (not tree.case_sensitive
568
and rel_names[0].lower() == rel_names[1].lower()):
569
into_existing = False
572
from_id = tree.path2id(rel_names[0])
573
if (not osutils.lexists(names_list[0]) and
574
from_id and inv.get_file_kind(from_id) == "directory"):
575
into_existing = False
578
# move into existing directory
579
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
580
self.outf.write("%s => %s\n" % pair)
582
if len(names_list) != 2:
583
raise errors.BzrCommandError('to mv multiple files the'
584
' destination must be a versioned'
586
tree.rename_one(rel_names[0], rel_names[1], after=after)
587
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
590
class cmd_pull(Command):
591
"""Turn this branch into a mirror of another branch.
593
This command only works on branches that have not diverged. Branches are
594
considered diverged if the destination branch's most recent commit is one
595
that has not been merged (directly or indirectly) into the parent.
597
If branches have diverged, you can use 'bzr merge' to integrate the changes
598
from one into the other. Once one branch has merged, the other should
599
be able to pull it again.
601
If you want to forget your local changes and just update your branch to
602
match the remote one, use pull --overwrite.
604
If there is no default location set, the first pull will set it. After
605
that, you can omit the location to use the default. To change the
606
default, use --remember. The value will only be saved if the remote
607
location can be accessed.
609
Note: The location can be specified either in the form of a branch,
610
or in the form of a path to a file containing a merge directive generated
614
_see_also = ['push', 'update', 'status-flags']
615
takes_options = ['remember', 'overwrite', 'revision',
616
custom_help('verbose',
617
help='Show logs of pulled revisions.'),
619
help='Branch to pull into, '
620
'rather than the one containing the working directory.',
625
takes_args = ['location?']
626
encoding_type = 'replace'
628
def run(self, location=None, remember=False, overwrite=False,
629
revision=None, verbose=False,
631
# FIXME: too much stuff is in the command class
634
if directory is None:
637
tree_to = WorkingTree.open_containing(directory)[0]
638
branch_to = tree_to.branch
639
except errors.NoWorkingTree:
641
branch_to = Branch.open_containing(directory)[0]
643
possible_transports = []
644
if location is not None:
646
mergeable = bundle.read_mergeable_from_url(location,
647
possible_transports=possible_transports)
648
except errors.NotABundle:
651
stored_loc = branch_to.get_parent()
653
if stored_loc is None:
654
raise errors.BzrCommandError("No pull location known or"
657
display_url = urlutils.unescape_for_display(stored_loc,
660
self.outf.write("Using saved parent location: %s\n" % display_url)
661
location = stored_loc
663
if mergeable is not None:
664
if revision is not None:
665
raise errors.BzrCommandError(
666
'Cannot use -r with merge directives or bundles')
667
mergeable.install_revisions(branch_to.repository)
668
base_revision_id, revision_id, verified = \
669
mergeable.get_merge_request(branch_to.repository)
670
branch_from = branch_to
672
branch_from = Branch.open(location,
673
possible_transports=possible_transports)
675
if branch_to.get_parent() is None or remember:
676
branch_to.set_parent(branch_from.base)
678
if revision is not None:
679
if len(revision) == 1:
680
revision_id = revision[0].as_revision_id(branch_from)
682
raise errors.BzrCommandError(
683
'bzr pull --revision takes one value.')
685
branch_to.lock_write()
687
if tree_to is not None:
688
change_reporter = delta._ChangeReporter(
689
unversioned_filter=tree_to.is_ignored)
690
result = tree_to.pull(branch_from, overwrite, revision_id,
692
possible_transports=possible_transports)
694
result = branch_to.pull(branch_from, overwrite, revision_id)
696
result.report(self.outf)
697
if verbose and result.old_revid != result.new_revid:
699
branch_to.repository.iter_reverse_revision_history(
702
new_rh = branch_to.revision_history()
703
log.show_changed_revisions(branch_to, old_rh, new_rh,
709
class cmd_push(Command):
710
"""Update a mirror of this branch.
712
The target branch will not have its working tree populated because this
713
is both expensive, and is not supported on remote file systems.
715
Some smart servers or protocols *may* put the working tree in place in
718
This command only works on branches that have not diverged. Branches are
719
considered diverged if the destination branch's most recent commit is one
720
that has not been merged (directly or indirectly) by the source branch.
722
If branches have diverged, you can use 'bzr push --overwrite' to replace
723
the other branch completely, discarding its unmerged changes.
725
If you want to ensure you have the different changes in the other branch,
726
do a merge (see bzr help merge) from the other branch, and commit that.
727
After that you will be able to do a push without '--overwrite'.
729
If there is no default push location set, the first push will set it.
730
After that, you can omit the location to use the default. To change the
731
default, use --remember. The value will only be saved if the remote
732
location can be accessed.
735
_see_also = ['pull', 'update', 'working-trees']
736
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
737
Option('create-prefix',
738
help='Create the path leading up to the branch '
739
'if it does not already exist.'),
741
help='Branch to push from, '
742
'rather than the one containing the working directory.',
746
Option('use-existing-dir',
747
help='By default push will fail if the target'
748
' directory exists, but does not already'
749
' have a control directory. This flag will'
750
' allow push to proceed.'),
752
help='Create a stacked branch that references the public location '
753
'of the parent branch.'),
755
help='Create a stacked branch that refers to another branch '
756
'for the commit history. Only the work not present in the '
757
'referenced branch is included in the branch created.',
760
takes_args = ['location?']
761
encoding_type = 'replace'
763
def run(self, location=None, remember=False, overwrite=False,
764
create_prefix=False, verbose=False, revision=None,
765
use_existing_dir=False, directory=None, stacked_on=None,
767
from bzrlib.push import _show_push_branch
769
# Get the source branch and revision_id
770
if directory is None:
772
br_from = Branch.open_containing(directory)[0]
773
if revision is not None:
774
if len(revision) == 1:
775
revision_id = revision[0].in_history(br_from).rev_id
777
raise errors.BzrCommandError(
778
'bzr push --revision takes one value.')
780
revision_id = br_from.last_revision()
782
# Get the stacked_on branch, if any
783
if stacked_on is not None:
784
stacked_on = urlutils.normalize_url(stacked_on)
786
parent_url = br_from.get_parent()
788
parent = Branch.open(parent_url)
789
stacked_on = parent.get_public_branch()
791
# I considered excluding non-http url's here, thus forcing
792
# 'public' branches only, but that only works for some
793
# users, so it's best to just depend on the user spotting an
794
# error by the feedback given to them. RBC 20080227.
795
stacked_on = parent_url
797
raise errors.BzrCommandError(
798
"Could not determine branch to refer to.")
800
# Get the destination location
802
stored_loc = br_from.get_push_location()
803
if stored_loc is None:
804
raise errors.BzrCommandError(
805
"No push location known or specified.")
807
display_url = urlutils.unescape_for_display(stored_loc,
809
self.outf.write("Using saved push location: %s\n" % display_url)
810
location = stored_loc
812
_show_push_branch(br_from, revision_id, location, self.outf,
813
verbose=verbose, overwrite=overwrite, remember=remember,
814
stacked_on=stacked_on, create_prefix=create_prefix,
815
use_existing_dir=use_existing_dir)
818
class cmd_branch(Command):
819
"""Create a new copy of a branch.
821
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
822
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
823
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
824
is derived from the FROM_LOCATION by stripping a leading scheme or drive
825
identifier, if any. For example, "branch lp:foo-bar" will attempt to
828
To retrieve the branch as of a particular revision, supply the --revision
829
parameter, as in "branch foo/bar -r 5".
832
_see_also = ['checkout']
833
takes_args = ['from_location', 'to_location?']
834
takes_options = ['revision', Option('hardlink',
835
help='Hard-link working tree files where possible.'),
837
help='Create a stacked branch referring to the source branch. '
838
'The new branch will depend on the availability of the source '
839
'branch for all operations.'),
841
help='Do not use a shared repository, even if available.'),
843
aliases = ['get', 'clone']
845
def run(self, from_location, to_location=None, revision=None,
846
hardlink=False, stacked=False, standalone=False):
847
from bzrlib.tag import _merge_tags_if_possible
850
elif len(revision) > 1:
851
raise errors.BzrCommandError(
852
'bzr branch --revision takes exactly 1 revision value')
854
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
858
if len(revision) == 1 and revision[0] is not None:
859
revision_id = revision[0].as_revision_id(br_from)
861
# FIXME - wt.last_revision, fallback to branch, fall back to
862
# None or perhaps NULL_REVISION to mean copy nothing
864
revision_id = br_from.last_revision()
865
if to_location is None:
866
to_location = urlutils.derive_to_location(from_location)
867
to_transport = transport.get_transport(to_location)
869
to_transport.mkdir('.')
870
except errors.FileExists:
871
raise errors.BzrCommandError('Target directory "%s" already'
872
' exists.' % to_location)
873
except errors.NoSuchFile:
874
raise errors.BzrCommandError('Parent of "%s" does not exist.'
877
# preserve whatever source format we have.
878
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
879
possible_transports=[to_transport],
880
accelerator_tree=accelerator_tree,
881
hardlink=hardlink, stacked=stacked,
882
force_new_repo=standalone)
883
branch = dir.open_branch()
884
except errors.NoSuchRevision:
885
to_transport.delete_tree('.')
886
msg = "The branch %s has no revision %s." % (from_location,
888
raise errors.BzrCommandError(msg)
889
_merge_tags_if_possible(br_from, branch)
890
# If the source branch is stacked, the new branch may
891
# be stacked whether we asked for that explicitly or not.
892
# We therefore need a try/except here and not just 'if stacked:'
894
note('Created new stacked branch referring to %s.' %
895
branch.get_stacked_on_url())
896
except (errors.NotStacked, errors.UnstackableBranchFormat,
897
errors.UnstackableRepositoryFormat), e:
898
note('Branched %d revision(s).' % branch.revno())
903
class cmd_checkout(Command):
904
"""Create a new checkout of an existing branch.
906
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
907
the branch found in '.'. This is useful if you have removed the working tree
908
or if it was never created - i.e. if you pushed the branch to its current
911
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
912
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
913
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
914
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
915
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
918
To retrieve the branch as of a particular revision, supply the --revision
919
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
920
out of date [so you cannot commit] but it may be useful (i.e. to examine old
924
_see_also = ['checkouts', 'branch']
925
takes_args = ['branch_location?', 'to_location?']
926
takes_options = ['revision',
927
Option('lightweight',
928
help="Perform a lightweight checkout. Lightweight "
929
"checkouts depend on access to the branch for "
930
"every operation. Normal checkouts can perform "
931
"common operations like diff and status without "
932
"such access, and also support local commits."
934
Option('files-from', type=str,
935
help="Get file contents from this tree."),
937
help='Hard-link working tree files where possible.'
942
def run(self, branch_location=None, to_location=None, revision=None,
943
lightweight=False, files_from=None, hardlink=False):
946
elif len(revision) > 1:
947
raise errors.BzrCommandError(
948
'bzr checkout --revision takes exactly 1 revision value')
949
if branch_location is None:
950
branch_location = osutils.getcwd()
951
to_location = branch_location
952
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
954
if files_from is not None:
955
accelerator_tree = WorkingTree.open(files_from)
956
if len(revision) == 1 and revision[0] is not None:
957
revision_id = revision[0].as_revision_id(source)
960
if to_location is None:
961
to_location = urlutils.derive_to_location(branch_location)
962
# if the source and to_location are the same,
963
# and there is no working tree,
964
# then reconstitute a branch
965
if (osutils.abspath(to_location) ==
966
osutils.abspath(branch_location)):
968
source.bzrdir.open_workingtree()
969
except errors.NoWorkingTree:
970
source.bzrdir.create_workingtree(revision_id)
972
source.create_checkout(to_location, revision_id, lightweight,
973
accelerator_tree, hardlink)
976
class cmd_renames(Command):
977
"""Show list of renamed files.
979
# TODO: Option to show renames between two historical versions.
981
# TODO: Only show renames under dir, rather than in the whole branch.
982
_see_also = ['status']
983
takes_args = ['dir?']
986
def run(self, dir=u'.'):
987
tree = WorkingTree.open_containing(dir)[0]
990
new_inv = tree.inventory
991
old_tree = tree.basis_tree()
994
old_inv = old_tree.inventory
995
renames = list(_mod_tree.find_renames(old_inv, new_inv))
997
for old_name, new_name in renames:
998
self.outf.write("%s => %s\n" % (old_name, new_name))
1005
class cmd_update(Command):
1006
"""Update a tree to have the latest code committed to its branch.
1008
This will perform a merge into the working tree, and may generate
1009
conflicts. If you have any local changes, you will still
1010
need to commit them after the update for the update to be complete.
1012
If you want to discard your local changes, you can just do a
1013
'bzr revert' instead of 'bzr commit' after the update.
1016
_see_also = ['pull', 'working-trees', 'status-flags']
1017
takes_args = ['dir?']
1020
def run(self, dir='.'):
1021
tree = WorkingTree.open_containing(dir)[0]
1022
possible_transports = []
1023
master = tree.branch.get_master_branch(
1024
possible_transports=possible_transports)
1025
if master is not None:
1028
tree.lock_tree_write()
1030
existing_pending_merges = tree.get_parent_ids()[1:]
1031
last_rev = _mod_revision.ensure_null(tree.last_revision())
1032
if last_rev == _mod_revision.ensure_null(
1033
tree.branch.last_revision()):
1034
# may be up to date, check master too.
1035
if master is None or last_rev == _mod_revision.ensure_null(
1036
master.last_revision()):
1037
revno = tree.branch.revision_id_to_revno(last_rev)
1038
note("Tree is up to date at revision %d." % (revno,))
1040
conflicts = tree.update(
1041
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1042
possible_transports=possible_transports)
1043
revno = tree.branch.revision_id_to_revno(
1044
_mod_revision.ensure_null(tree.last_revision()))
1045
note('Updated to revision %d.' % (revno,))
1046
if tree.get_parent_ids()[1:] != existing_pending_merges:
1047
note('Your local commits will now show as pending merges with '
1048
"'bzr status', and can be committed with 'bzr commit'.")
1057
class cmd_info(Command):
1058
"""Show information about a working tree, branch or repository.
1060
This command will show all known locations and formats associated to the
1061
tree, branch or repository. Statistical information is included with
1064
Branches and working trees will also report any missing revisions.
1066
_see_also = ['revno', 'working-trees', 'repositories']
1067
takes_args = ['location?']
1068
takes_options = ['verbose']
1069
encoding_type = 'replace'
1072
def run(self, location=None, verbose=False):
1077
from bzrlib.info import show_bzrdir_info
1078
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1079
verbose=noise_level, outfile=self.outf)
1082
class cmd_remove(Command):
1083
"""Remove files or directories.
1085
This makes bzr stop tracking changes to the specified files. bzr will delete
1086
them if they can easily be recovered using revert. If no options or
1087
parameters are given bzr will scan for files that are being tracked by bzr
1088
but missing in your tree and stop tracking them for you.
1090
takes_args = ['file*']
1091
takes_options = ['verbose',
1092
Option('new', help='Only remove files that have never been committed.'),
1093
RegistryOption.from_kwargs('file-deletion-strategy',
1094
'The file deletion mode to be used.',
1095
title='Deletion Strategy', value_switches=True, enum_switch=False,
1096
safe='Only delete files if they can be'
1097
' safely recovered (default).',
1098
keep="Don't delete any files.",
1099
force='Delete all the specified files, even if they can not be '
1100
'recovered and even if they are non-empty directories.')]
1101
aliases = ['rm', 'del']
1102
encoding_type = 'replace'
1104
def run(self, file_list, verbose=False, new=False,
1105
file_deletion_strategy='safe'):
1106
tree, file_list = tree_files(file_list)
1108
if file_list is not None:
1109
file_list = [f for f in file_list]
1113
# Heuristics should probably all move into tree.remove_smart or
1116
added = tree.changes_from(tree.basis_tree(),
1117
specific_files=file_list).added
1118
file_list = sorted([f[0] for f in added], reverse=True)
1119
if len(file_list) == 0:
1120
raise errors.BzrCommandError('No matching files.')
1121
elif file_list is None:
1122
# missing files show up in iter_changes(basis) as
1123
# versioned-with-no-kind.
1125
for change in tree.iter_changes(tree.basis_tree()):
1126
# Find paths in the working tree that have no kind:
1127
if change[1][1] is not None and change[6][1] is None:
1128
missing.append(change[1][1])
1129
file_list = sorted(missing, reverse=True)
1130
file_deletion_strategy = 'keep'
1131
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1132
keep_files=file_deletion_strategy=='keep',
1133
force=file_deletion_strategy=='force')
1138
class cmd_file_id(Command):
1139
"""Print file_id of a particular file or directory.
1141
The file_id is assigned when the file is first added and remains the
1142
same through all revisions where the file exists, even when it is
1147
_see_also = ['inventory', 'ls']
1148
takes_args = ['filename']
1151
def run(self, filename):
1152
tree, relpath = WorkingTree.open_containing(filename)
1153
i = tree.path2id(relpath)
1155
raise errors.NotVersionedError(filename)
1157
self.outf.write(i + '\n')
1160
class cmd_file_path(Command):
1161
"""Print path of file_ids to a file or directory.
1163
This prints one line for each directory down to the target,
1164
starting at the branch root.
1168
takes_args = ['filename']
1171
def run(self, filename):
1172
tree, relpath = WorkingTree.open_containing(filename)
1173
fid = tree.path2id(relpath)
1175
raise errors.NotVersionedError(filename)
1176
segments = osutils.splitpath(relpath)
1177
for pos in range(1, len(segments) + 1):
1178
path = osutils.joinpath(segments[:pos])
1179
self.outf.write("%s\n" % tree.path2id(path))
1182
class cmd_reconcile(Command):
1183
"""Reconcile bzr metadata in a branch.
1185
This can correct data mismatches that may have been caused by
1186
previous ghost operations or bzr upgrades. You should only
1187
need to run this command if 'bzr check' or a bzr developer
1188
advises you to run it.
1190
If a second branch is provided, cross-branch reconciliation is
1191
also attempted, which will check that data like the tree root
1192
id which was not present in very early bzr versions is represented
1193
correctly in both branches.
1195
At the same time it is run it may recompress data resulting in
1196
a potential saving in disk space or performance gain.
1198
The branch *MUST* be on a listable system such as local disk or sftp.
1201
_see_also = ['check']
1202
takes_args = ['branch?']
1204
def run(self, branch="."):
1205
from bzrlib.reconcile import reconcile
1206
dir = bzrdir.BzrDir.open(branch)
1210
class cmd_revision_history(Command):
1211
"""Display the list of revision ids on a branch."""
1214
takes_args = ['location?']
1219
def run(self, location="."):
1220
branch = Branch.open_containing(location)[0]
1221
for revid in branch.revision_history():
1222
self.outf.write(revid)
1223
self.outf.write('\n')
1226
class cmd_ancestry(Command):
1227
"""List all revisions merged into this branch."""
1229
_see_also = ['log', 'revision-history']
1230
takes_args = ['location?']
1235
def run(self, location="."):
1237
wt = WorkingTree.open_containing(location)[0]
1238
except errors.NoWorkingTree:
1239
b = Branch.open(location)
1240
last_revision = b.last_revision()
1243
last_revision = wt.last_revision()
1245
revision_ids = b.repository.get_ancestry(last_revision)
1247
for revision_id in revision_ids:
1248
self.outf.write(revision_id + '\n')
1251
class cmd_init(Command):
1252
"""Make a directory into a versioned branch.
1254
Use this to create an empty branch, or before importing an
1257
If there is a repository in a parent directory of the location, then
1258
the history of the branch will be stored in the repository. Otherwise
1259
init creates a standalone branch which carries its own history
1260
in the .bzr directory.
1262
If there is already a branch at the location but it has no working tree,
1263
the tree can be populated with 'bzr checkout'.
1265
Recipe for importing a tree of files::
1271
bzr commit -m "imported project"
1274
_see_also = ['init-repository', 'branch', 'checkout']
1275
takes_args = ['location?']
1277
Option('create-prefix',
1278
help='Create the path leading up to the branch '
1279
'if it does not already exist.'),
1280
RegistryOption('format',
1281
help='Specify a format for this branch. '
1282
'See "help formats".',
1283
registry=bzrdir.format_registry,
1284
converter=bzrdir.format_registry.make_bzrdir,
1285
value_switches=True,
1286
title="Branch Format",
1288
Option('append-revisions-only',
1289
help='Never change revnos or the existing log.'
1290
' Append revisions to it only.')
1292
def run(self, location=None, format=None, append_revisions_only=False,
1293
create_prefix=False):
1295
format = bzrdir.format_registry.make_bzrdir('default')
1296
if location is None:
1299
to_transport = transport.get_transport(location)
1301
# The path has to exist to initialize a
1302
# branch inside of it.
1303
# Just using os.mkdir, since I don't
1304
# believe that we want to create a bunch of
1305
# locations if the user supplies an extended path
1307
to_transport.ensure_base()
1308
except errors.NoSuchFile:
1309
if not create_prefix:
1310
raise errors.BzrCommandError("Parent directory of %s"
1312
"\nYou may supply --create-prefix to create all"
1313
" leading parent directories."
1315
_create_prefix(to_transport)
1318
existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1319
except errors.NotBranchError:
1320
# really a NotBzrDir error...
1321
create_branch = bzrdir.BzrDir.create_branch_convenience
1322
branch = create_branch(to_transport.base, format=format,
1323
possible_transports=[to_transport])
1325
from bzrlib.transport.local import LocalTransport
1326
if existing_bzrdir.has_branch():
1327
if (isinstance(to_transport, LocalTransport)
1328
and not existing_bzrdir.has_workingtree()):
1329
raise errors.BranchExistsWithoutWorkingTree(location)
1330
raise errors.AlreadyBranchError(location)
1332
branch = existing_bzrdir.create_branch()
1333
existing_bzrdir.create_workingtree()
1334
if append_revisions_only:
1336
branch.set_append_revisions_only(True)
1337
except errors.UpgradeRequired:
1338
raise errors.BzrCommandError('This branch format cannot be set'
1339
' to append-revisions-only. Try --experimental-branch6')
1341
from bzrlib.info import show_bzrdir_info
1342
show_bzrdir_info(bzrdir.BzrDir.open_containing_from_transport(
1343
to_transport)[0], verbose=0, outfile=self.outf)
1346
class cmd_init_repository(Command):
1347
"""Create a shared repository to hold branches.
1349
New branches created under the repository directory will store their
1350
revisions in the repository, not in the branch directory.
1352
If the --no-trees option is used then the branches in the repository
1353
will not have working trees by default.
1356
Create a shared repositories holding just branches::
1358
bzr init-repo --no-trees repo
1361
Make a lightweight checkout elsewhere::
1363
bzr checkout --lightweight repo/trunk trunk-checkout
1368
_see_also = ['init', 'branch', 'checkout', 'repositories']
1369
takes_args = ["location"]
1370
takes_options = [RegistryOption('format',
1371
help='Specify a format for this repository. See'
1372
' "bzr help formats" for details.',
1373
registry=bzrdir.format_registry,
1374
converter=bzrdir.format_registry.make_bzrdir,
1375
value_switches=True, title='Repository format'),
1377
help='Branches in the repository will default to'
1378
' not having a working tree.'),
1380
aliases = ["init-repo"]
1382
def run(self, location, format=None, no_trees=False):
1384
format = bzrdir.format_registry.make_bzrdir('default')
1386
if location is None:
1389
to_transport = transport.get_transport(location)
1390
to_transport.ensure_base()
1392
newdir = format.initialize_on_transport(to_transport)
1393
repo = newdir.create_repository(shared=True)
1394
repo.set_make_working_trees(not no_trees)
1396
from bzrlib.info import show_bzrdir_info
1397
show_bzrdir_info(bzrdir.BzrDir.open_containing_from_transport(
1398
to_transport)[0], verbose=0, outfile=self.outf)
1401
class cmd_diff(Command):
1402
"""Show differences in the working tree, between revisions or branches.
1404
If no arguments are given, all changes for the current tree are listed.
1405
If files are given, only the changes in those files are listed.
1406
Remote and multiple branches can be compared by using the --old and
1407
--new options. If not provided, the default for both is derived from
1408
the first argument, if any, or the current tree if no arguments are
1411
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1412
produces patches suitable for "patch -p1".
1416
2 - unrepresentable changes
1421
Shows the difference in the working tree versus the last commit::
1425
Difference between the working tree and revision 1::
1429
Difference between revision 2 and revision 1::
1433
Difference between revision 2 and revision 1 for branch xxx::
1437
Show just the differences for file NEWS::
1441
Show the differences in working tree xxx for file NEWS::
1445
Show the differences from branch xxx to this working tree:
1449
Show the differences between two branches for file NEWS::
1451
bzr diff --old xxx --new yyy NEWS
1453
Same as 'bzr diff' but prefix paths with old/ and new/::
1455
bzr diff --prefix old/:new/
1457
_see_also = ['status']
1458
takes_args = ['file*']
1460
Option('diff-options', type=str,
1461
help='Pass these options to the external diff program.'),
1462
Option('prefix', type=str,
1464
help='Set prefixes added to old and new filenames, as '
1465
'two values separated by a colon. (eg "old/:new/").'),
1467
help='Branch/tree to compare from.',
1471
help='Branch/tree to compare to.',
1477
help='Use this command to compare files.',
1481
aliases = ['di', 'dif']
1482
encoding_type = 'exact'
1485
def run(self, revision=None, file_list=None, diff_options=None,
1486
prefix=None, old=None, new=None, using=None):
1487
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1489
if (prefix is None) or (prefix == '0'):
1497
old_label, new_label = prefix.split(":")
1499
raise errors.BzrCommandError(
1500
'--prefix expects two values separated by a colon'
1501
' (eg "old/:new/")')
1503
if revision and len(revision) > 2:
1504
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1505
' one or two revision specifiers')
1507
old_tree, new_tree, specific_files, extra_trees = \
1508
_get_trees_to_diff(file_list, revision, old, new)
1509
return show_diff_trees(old_tree, new_tree, sys.stdout,
1510
specific_files=specific_files,
1511
external_diff_options=diff_options,
1512
old_label=old_label, new_label=new_label,
1513
extra_trees=extra_trees, using=using)
1516
class cmd_deleted(Command):
1517
"""List files deleted in the working tree.
1519
# TODO: Show files deleted since a previous revision, or
1520
# between two revisions.
1521
# TODO: Much more efficient way to do this: read in new
1522
# directories with readdir, rather than stating each one. Same
1523
# level of effort but possibly much less IO. (Or possibly not,
1524
# if the directories are very large...)
1525
_see_also = ['status', 'ls']
1526
takes_options = ['show-ids']
1529
def run(self, show_ids=False):
1530
tree = WorkingTree.open_containing(u'.')[0]
1533
old = tree.basis_tree()
1536
for path, ie in old.inventory.iter_entries():
1537
if not tree.has_id(ie.file_id):
1538
self.outf.write(path)
1540
self.outf.write(' ')
1541
self.outf.write(ie.file_id)
1542
self.outf.write('\n')
1549
class cmd_modified(Command):
1550
"""List files modified in working tree.
1554
_see_also = ['status', 'ls']
1557
help='Write an ascii NUL (\\0) separator '
1558
'between files rather than a newline.')
1562
def run(self, null=False):
1563
tree = WorkingTree.open_containing(u'.')[0]
1564
td = tree.changes_from(tree.basis_tree())
1565
for path, id, kind, text_modified, meta_modified in td.modified:
1567
self.outf.write(path + '\0')
1569
self.outf.write(osutils.quotefn(path) + '\n')
1572
class cmd_added(Command):
1573
"""List files added in working tree.
1577
_see_also = ['status', 'ls']
1580
help='Write an ascii NUL (\\0) separator '
1581
'between files rather than a newline.')
1585
def run(self, null=False):
1586
wt = WorkingTree.open_containing(u'.')[0]
1589
basis = wt.basis_tree()
1592
basis_inv = basis.inventory
1595
if file_id in basis_inv:
1597
if inv.is_root(file_id) and len(basis_inv) == 0:
1599
path = inv.id2path(file_id)
1600
if not os.access(osutils.abspath(path), os.F_OK):
1603
self.outf.write(path + '\0')
1605
self.outf.write(osutils.quotefn(path) + '\n')
1612
class cmd_root(Command):
1613
"""Show the tree root directory.
1615
The root is the nearest enclosing directory with a .bzr control
1618
takes_args = ['filename?']
1620
def run(self, filename=None):
1621
"""Print the branch root."""
1622
tree = WorkingTree.open_containing(filename)[0]
1623
self.outf.write(tree.basedir + '\n')
1626
def _parse_limit(limitstring):
1628
return int(limitstring)
1630
msg = "The limit argument must be an integer."
1631
raise errors.BzrCommandError(msg)
1634
class cmd_log(Command):
1635
"""Show log of a branch, file, or directory.
1637
By default show the log of the branch containing the working directory.
1639
To request a range of logs, you can use the command -r begin..end
1640
-r revision requests a specific revision, -r ..end or -r begin.. are
1644
Log the current branch::
1652
Log the last 10 revisions of a branch::
1654
bzr log -r -10.. http://server/branch
1657
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1659
takes_args = ['location?']
1662
help='Show from oldest to newest.'),
1665
help='Display timezone as local, original, or utc.'),
1666
custom_help('verbose',
1667
help='Show files changed in each revision.'),
1673
help='Show revisions whose message matches this '
1674
'regular expression.',
1678
help='Limit the output to the first N revisions.',
1682
encoding_type = 'replace'
1685
def run(self, location=None, timezone='original',
1693
from bzrlib.log import show_log
1694
direction = (forward and 'forward') or 'reverse'
1699
# find the file id to log:
1701
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1705
tree = b.basis_tree()
1706
file_id = tree.path2id(fp)
1708
raise errors.BzrCommandError(
1709
"Path does not have any revision history: %s" %
1713
# FIXME ? log the current subdir only RBC 20060203
1714
if revision is not None \
1715
and len(revision) > 0 and revision[0].get_branch():
1716
location = revision[0].get_branch()
1719
dir, relpath = bzrdir.BzrDir.open_containing(location)
1720
b = dir.open_branch()
1724
if revision is None:
1727
elif len(revision) == 1:
1728
rev1 = rev2 = revision[0].in_history(b)
1729
elif len(revision) == 2:
1730
if revision[1].get_branch() != revision[0].get_branch():
1731
# b is taken from revision[0].get_branch(), and
1732
# show_log will use its revision_history. Having
1733
# different branches will lead to weird behaviors.
1734
raise errors.BzrCommandError(
1735
"Log doesn't accept two revisions in different"
1737
rev1 = revision[0].in_history(b)
1738
rev2 = revision[1].in_history(b)
1740
raise errors.BzrCommandError(
1741
'bzr log --revision takes one or two values.')
1743
if log_format is None:
1744
log_format = log.log_formatter_registry.get_default(b)
1746
lf = log_format(show_ids=show_ids, to_file=self.outf,
1747
show_timezone=timezone)
1753
direction=direction,
1754
start_revision=rev1,
1762
def get_log_format(long=False, short=False, line=False, default='long'):
1763
log_format = default
1767
log_format = 'short'
1773
class cmd_touching_revisions(Command):
1774
"""Return revision-ids which affected a particular file.
1776
A more user-friendly interface is "bzr log FILE".
1780
takes_args = ["filename"]
1783
def run(self, filename):
1784
tree, relpath = WorkingTree.open_containing(filename)
1786
file_id = tree.path2id(relpath)
1787
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1788
self.outf.write("%6d %s\n" % (revno, what))
1791
class cmd_ls(Command):
1792
"""List files in a tree.
1795
_see_also = ['status', 'cat']
1796
takes_args = ['path?']
1797
# TODO: Take a revision or remote path and list that tree instead.
1801
Option('non-recursive',
1802
help='Don\'t recurse into subdirectories.'),
1804
help='Print paths relative to the root of the branch.'),
1805
Option('unknown', help='Print unknown files.'),
1806
Option('versioned', help='Print versioned files.',
1808
Option('ignored', help='Print ignored files.'),
1810
help='Write an ascii NUL (\\0) separator '
1811
'between files rather than a newline.'),
1813
help='List entries of a particular kind: file, directory, symlink.',
1818
def run(self, revision=None, verbose=False,
1819
non_recursive=False, from_root=False,
1820
unknown=False, versioned=False, ignored=False,
1821
null=False, kind=None, show_ids=False, path=None):
1823
if kind and kind not in ('file', 'directory', 'symlink'):
1824
raise errors.BzrCommandError('invalid kind specified')
1826
if verbose and null:
1827
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1828
all = not (unknown or versioned or ignored)
1830
selection = {'I':ignored, '?':unknown, 'V':versioned}
1837
raise errors.BzrCommandError('cannot specify both --from-root'
1841
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1847
if revision is not None:
1848
tree = branch.repository.revision_tree(
1849
revision[0].as_revision_id(branch))
1851
tree = branch.basis_tree()
1855
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1856
if fp.startswith(relpath):
1857
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1858
if non_recursive and '/' in fp:
1860
if not all and not selection[fc]:
1862
if kind is not None and fkind != kind:
1865
kindch = entry.kind_character()
1866
outstring = '%-8s %s%s' % (fc, fp, kindch)
1867
if show_ids and fid is not None:
1868
outstring = "%-50s %s" % (outstring, fid)
1869
self.outf.write(outstring + '\n')
1871
self.outf.write(fp + '\0')
1874
self.outf.write(fid)
1875
self.outf.write('\0')
1883
self.outf.write('%-50s %s\n' % (fp, my_id))
1885
self.outf.write(fp + '\n')
1890
class cmd_unknowns(Command):
1891
"""List unknown files.
1899
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1900
self.outf.write(osutils.quotefn(f) + '\n')
1903
class cmd_ignore(Command):
1904
"""Ignore specified files or patterns.
1906
See ``bzr help patterns`` for details on the syntax of patterns.
1908
To remove patterns from the ignore list, edit the .bzrignore file.
1909
After adding, editing or deleting that file either indirectly by
1910
using this command or directly by using an editor, be sure to commit
1913
Note: ignore patterns containing shell wildcards must be quoted from
1917
Ignore the top level Makefile::
1919
bzr ignore ./Makefile
1921
Ignore class files in all directories::
1923
bzr ignore "*.class"
1925
Ignore .o files under the lib directory::
1927
bzr ignore "lib/**/*.o"
1929
Ignore .o files under the lib directory::
1931
bzr ignore "RE:lib/.*\.o"
1933
Ignore everything but the "debian" toplevel directory::
1935
bzr ignore "RE:(?!debian/).*"
1938
_see_also = ['status', 'ignored', 'patterns']
1939
takes_args = ['name_pattern*']
1941
Option('old-default-rules',
1942
help='Write out the ignore rules bzr < 0.9 always used.')
1945
def run(self, name_pattern_list=None, old_default_rules=None):
1946
from bzrlib import ignores
1947
if old_default_rules is not None:
1948
# dump the rules and exit
1949
for pattern in ignores.OLD_DEFAULTS:
1952
if not name_pattern_list:
1953
raise errors.BzrCommandError("ignore requires at least one "
1954
"NAME_PATTERN or --old-default-rules")
1955
name_pattern_list = [globbing.normalize_pattern(p)
1956
for p in name_pattern_list]
1957
for name_pattern in name_pattern_list:
1958
if (name_pattern[0] == '/' or
1959
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1960
raise errors.BzrCommandError(
1961
"NAME_PATTERN should not be an absolute path")
1962
tree, relpath = WorkingTree.open_containing(u'.')
1963
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
1964
ignored = globbing.Globster(name_pattern_list)
1967
for entry in tree.list_files():
1971
if ignored.match(filename):
1972
matches.append(filename.encode('utf-8'))
1974
if len(matches) > 0:
1975
print "Warning: the following files are version controlled and" \
1976
" match your ignore pattern:\n%s" % ("\n".join(matches),)
1979
class cmd_ignored(Command):
1980
"""List ignored files and the patterns that matched them.
1982
List all the ignored files and the ignore pattern that caused the file to
1985
Alternatively, to list just the files::
1990
encoding_type = 'replace'
1991
_see_also = ['ignore', 'ls']
1995
tree = WorkingTree.open_containing(u'.')[0]
1998
for path, file_class, kind, file_id, entry in tree.list_files():
1999
if file_class != 'I':
2001
## XXX: Slightly inefficient since this was already calculated
2002
pat = tree.is_ignored(path)
2003
self.outf.write('%-50s %s\n' % (path, pat))
2008
class cmd_lookup_revision(Command):
2009
"""Lookup the revision-id from a revision-number
2012
bzr lookup-revision 33
2015
takes_args = ['revno']
2018
def run(self, revno):
2022
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
2024
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2027
class cmd_export(Command):
2028
"""Export current or past revision to a destination directory or archive.
2030
If no revision is specified this exports the last committed revision.
2032
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
2033
given, try to find the format with the extension. If no extension
2034
is found exports to a directory (equivalent to --format=dir).
2036
If root is supplied, it will be used as the root directory inside
2037
container formats (tar, zip, etc). If it is not supplied it will default
2038
to the exported filename. The root option has no effect for 'dir' format.
2040
If branch is omitted then the branch containing the current working
2041
directory will be used.
2043
Note: Export of tree with non-ASCII filenames to zip is not supported.
2045
================= =========================
2046
Supported formats Autodetected by extension
2047
================= =========================
2050
tbz2 .tar.bz2, .tbz2
2053
================= =========================
2055
takes_args = ['dest', 'branch_or_subdir?']
2058
help="Type of file to export to.",
2063
help="Name of the root directory inside the exported file."),
2065
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2067
from bzrlib.export import export
2069
if branch_or_subdir is None:
2070
tree = WorkingTree.open_containing(u'.')[0]
2074
b, subdir = Branch.open_containing(branch_or_subdir)
2076
if revision is None:
2077
# should be tree.last_revision FIXME
2078
rev_id = b.last_revision()
2080
if len(revision) != 1:
2081
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2082
rev_id = revision[0].as_revision_id(b)
2083
t = b.repository.revision_tree(rev_id)
2085
export(t, dest, format, root, subdir)
2086
except errors.NoSuchExportFormat, e:
2087
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2090
class cmd_cat(Command):
2091
"""Write the contents of a file as of a given revision to standard output.
2093
If no revision is nominated, the last revision is used.
2095
Note: Take care to redirect standard output when using this command on a
2101
Option('name-from-revision', help='The path name in the old tree.'),
2104
takes_args = ['filename']
2105
encoding_type = 'exact'
2108
def run(self, filename, revision=None, name_from_revision=False):
2109
if revision is not None and len(revision) != 1:
2110
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2111
" one revision specifier")
2112
tree, branch, relpath = \
2113
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2116
return self._run(tree, branch, relpath, filename, revision,
2121
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2123
tree = b.basis_tree()
2124
if revision is None:
2125
revision_id = b.last_revision()
2127
revision_id = revision[0].as_revision_id(b)
2129
cur_file_id = tree.path2id(relpath)
2130
rev_tree = b.repository.revision_tree(revision_id)
2131
old_file_id = rev_tree.path2id(relpath)
2133
if name_from_revision:
2134
if old_file_id is None:
2135
raise errors.BzrCommandError("%r is not present in revision %s"
2136
% (filename, revision_id))
2138
content = rev_tree.get_file_text(old_file_id)
2139
elif cur_file_id is not None:
2140
content = rev_tree.get_file_text(cur_file_id)
2141
elif old_file_id is not None:
2142
content = rev_tree.get_file_text(old_file_id)
2144
raise errors.BzrCommandError("%r is not present in revision %s" %
2145
(filename, revision_id))
2146
self.outf.write(content)
2149
class cmd_local_time_offset(Command):
2150
"""Show the offset in seconds from GMT to local time."""
2154
print osutils.local_time_offset()
2158
class cmd_commit(Command):
2159
"""Commit changes into a new revision.
2161
If no arguments are given, the entire tree is committed.
2163
If selected files are specified, only changes to those files are
2164
committed. If a directory is specified then the directory and everything
2165
within it is committed.
2167
When excludes are given, they take precedence over selected files.
2168
For example, too commit only changes within foo, but not changes within
2171
bzr commit foo -x foo/bar
2173
If author of the change is not the same person as the committer, you can
2174
specify the author's name using the --author option. The name should be
2175
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2177
A selected-file commit may fail in some cases where the committed
2178
tree would be invalid. Consider::
2183
bzr commit foo -m "committing foo"
2184
bzr mv foo/bar foo/baz
2187
bzr commit foo/bar -m "committing bar but not baz"
2189
In the example above, the last commit will fail by design. This gives
2190
the user the opportunity to decide whether they want to commit the
2191
rename at the same time, separately first, or not at all. (As a general
2192
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2194
Note: A selected-file commit after a merge is not yet supported.
2196
# TODO: Run hooks on tree to-be-committed, and after commit.
2198
# TODO: Strict commit that fails if there are deleted files.
2199
# (what does "deleted files" mean ??)
2201
# TODO: Give better message for -s, --summary, used by tla people
2203
# XXX: verbose currently does nothing
2205
_see_also = ['bugs', 'uncommit']
2206
takes_args = ['selected*']
2208
ListOption('exclude', type=str, short_name='x',
2209
help="Do not consider changes made to a given path."),
2210
Option('message', type=unicode,
2212
help="Description of the new revision."),
2215
help='Commit even if nothing has changed.'),
2216
Option('file', type=str,
2219
help='Take commit message from this file.'),
2221
help="Refuse to commit if there are unknown "
2222
"files in the working tree."),
2223
ListOption('fixes', type=str,
2224
help="Mark a bug as being fixed by this revision."),
2225
Option('author', type=unicode,
2226
help="Set the author's name, if it's different "
2227
"from the committer."),
2229
help="Perform a local commit in a bound "
2230
"branch. Local commits are not pushed to "
2231
"the master branch until a normal commit "
2235
help='When no message is supplied, show the diff along'
2236
' with the status summary in the message editor.'),
2238
aliases = ['ci', 'checkin']
2240
def _get_bug_fix_properties(self, fixes, branch):
2242
# Configure the properties for bug fixing attributes.
2243
for fixed_bug in fixes:
2244
tokens = fixed_bug.split(':')
2245
if len(tokens) != 2:
2246
raise errors.BzrCommandError(
2247
"Invalid bug %s. Must be in the form of 'tag:id'. "
2248
"Commit refused." % fixed_bug)
2249
tag, bug_id = tokens
2251
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2252
except errors.UnknownBugTrackerAbbreviation:
2253
raise errors.BzrCommandError(
2254
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2255
except errors.MalformedBugIdentifier:
2256
raise errors.BzrCommandError(
2257
"Invalid bug identifier for %s. Commit refused."
2259
properties.append('%s fixed' % bug_url)
2260
return '\n'.join(properties)
2262
def run(self, message=None, file=None, verbose=False, selected_list=None,
2263
unchanged=False, strict=False, local=False, fixes=None,
2264
author=None, show_diff=False, exclude=None):
2265
from bzrlib.errors import (
2270
from bzrlib.msgeditor import (
2271
edit_commit_message_encoded,
2272
make_commit_message_template_encoded
2275
# TODO: Need a blackbox test for invoking the external editor; may be
2276
# slightly problematic to run this cross-platform.
2278
# TODO: do more checks that the commit will succeed before
2279
# spending the user's valuable time typing a commit message.
2283
tree, selected_list = tree_files(selected_list)
2284
if selected_list == ['']:
2285
# workaround - commit of root of tree should be exactly the same
2286
# as just default commit in that tree, and succeed even though
2287
# selected-file merge commit is not done yet
2292
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2294
properties['bugs'] = bug_property
2296
if local and not tree.branch.get_bound_location():
2297
raise errors.LocalRequiresBoundBranch()
2299
def get_message(commit_obj):
2300
"""Callback to get commit message"""
2301
my_message = message
2302
if my_message is None and not file:
2303
t = make_commit_message_template_encoded(tree,
2304
selected_list, diff=show_diff,
2305
output_encoding=bzrlib.user_encoding)
2306
my_message = edit_commit_message_encoded(t)
2307
if my_message is None:
2308
raise errors.BzrCommandError("please specify a commit"
2309
" message with either --message or --file")
2310
elif my_message and file:
2311
raise errors.BzrCommandError(
2312
"please specify either --message or --file")
2314
my_message = codecs.open(file, 'rt',
2315
bzrlib.user_encoding).read()
2316
if my_message == "":
2317
raise errors.BzrCommandError("empty commit message specified")
2321
tree.commit(message_callback=get_message,
2322
specific_files=selected_list,
2323
allow_pointless=unchanged, strict=strict, local=local,
2324
reporter=None, verbose=verbose, revprops=properties,
2326
exclude=safe_relpath_files(tree, exclude))
2327
except PointlessCommit:
2328
# FIXME: This should really happen before the file is read in;
2329
# perhaps prepare the commit; get the message; then actually commit
2330
raise errors.BzrCommandError("no changes to commit."
2331
" use --unchanged to commit anyhow")
2332
except ConflictsInTree:
2333
raise errors.BzrCommandError('Conflicts detected in working '
2334
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2336
except StrictCommitFailed:
2337
raise errors.BzrCommandError("Commit refused because there are"
2338
" unknown files in the working tree.")
2339
except errors.BoundBranchOutOfDate, e:
2340
raise errors.BzrCommandError(str(e) + "\n"
2341
'To commit to master branch, run update and then commit.\n'
2342
'You can also pass --local to commit to continue working '
2346
class cmd_check(Command):
2347
"""Validate working tree structure, branch consistency and repository history.
2349
This command checks various invariants about branch and repository storage
2350
to detect data corruption or bzr bugs.
2352
The working tree and branch checks will only give output if a problem is
2353
detected. The output fields of the repository check are:
2355
revisions: This is just the number of revisions checked. It doesn't
2357
versionedfiles: This is just the number of versionedfiles checked. It
2358
doesn't indicate a problem.
2359
unreferenced ancestors: Texts that are ancestors of other texts, but
2360
are not properly referenced by the revision ancestry. This is a
2361
subtle problem that Bazaar can work around.
2362
unique file texts: This is the total number of unique file contents
2363
seen in the checked revisions. It does not indicate a problem.
2364
repeated file texts: This is the total number of repeated texts seen
2365
in the checked revisions. Texts can be repeated when their file
2366
entries are modified, but the file contents are not. It does not
2369
If no restrictions are specified, all Bazaar data that is found at the given
2370
location will be checked.
2374
Check the tree and branch at 'foo'::
2376
bzr check --tree --branch foo
2378
Check only the repository at 'bar'::
2380
bzr check --repo bar
2382
Check everything at 'baz'::
2387
_see_also = ['reconcile']
2388
takes_args = ['path?']
2389
takes_options = ['verbose',
2390
Option('branch', help="Check the branch related to the"
2391
" current directory."),
2392
Option('repo', help="Check the repository related to the"
2393
" current directory."),
2394
Option('tree', help="Check the working tree related to"
2395
" the current directory.")]
2397
def run(self, path=None, verbose=False, branch=False, repo=False,
2399
from bzrlib.check import check_dwim
2402
if not branch and not repo and not tree:
2403
branch = repo = tree = True
2404
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2407
class cmd_upgrade(Command):
2408
"""Upgrade branch storage to current format.
2410
The check command or bzr developers may sometimes advise you to run
2411
this command. When the default format has changed you may also be warned
2412
during other operations to upgrade.
2415
_see_also = ['check']
2416
takes_args = ['url?']
2418
RegistryOption('format',
2419
help='Upgrade to a specific format. See "bzr help'
2420
' formats" for details.',
2421
registry=bzrdir.format_registry,
2422
converter=bzrdir.format_registry.make_bzrdir,
2423
value_switches=True, title='Branch format'),
2426
def run(self, url='.', format=None):
2427
from bzrlib.upgrade import upgrade
2429
format = bzrdir.format_registry.make_bzrdir('default')
2430
upgrade(url, format)
2433
class cmd_whoami(Command):
2434
"""Show or set bzr user id.
2437
Show the email of the current user::
2441
Set the current user::
2443
bzr whoami "Frank Chu <fchu@example.com>"
2445
takes_options = [ Option('email',
2446
help='Display email address only.'),
2448
help='Set identity for the current branch instead of '
2451
takes_args = ['name?']
2452
encoding_type = 'replace'
2455
def run(self, email=False, branch=False, name=None):
2457
# use branch if we're inside one; otherwise global config
2459
c = Branch.open_containing('.')[0].get_config()
2460
except errors.NotBranchError:
2461
c = config.GlobalConfig()
2463
self.outf.write(c.user_email() + '\n')
2465
self.outf.write(c.username() + '\n')
2468
# display a warning if an email address isn't included in the given name.
2470
config.extract_email_address(name)
2471
except errors.NoEmailInUsername, e:
2472
warning('"%s" does not seem to contain an email address. '
2473
'This is allowed, but not recommended.', name)
2475
# use global config unless --branch given
2477
c = Branch.open_containing('.')[0].get_config()
2479
c = config.GlobalConfig()
2480
c.set_user_option('email', name)
2483
class cmd_nick(Command):
2484
"""Print or set the branch nickname.
2486
If unset, the tree root directory name is used as the nickname
2487
To print the current nickname, execute with no argument.
2490
_see_also = ['info']
2491
takes_args = ['nickname?']
2492
def run(self, nickname=None):
2493
branch = Branch.open_containing(u'.')[0]
2494
if nickname is None:
2495
self.printme(branch)
2497
branch.nick = nickname
2500
def printme(self, branch):
2504
class cmd_alias(Command):
2505
"""Set/unset and display aliases.
2508
Show the current aliases::
2512
Show the alias specified for 'll'::
2516
Set an alias for 'll'::
2518
bzr alias ll="log --line -r-10..-1"
2520
To remove an alias for 'll'::
2522
bzr alias --remove ll
2525
takes_args = ['name?']
2527
Option('remove', help='Remove the alias.'),
2530
def run(self, name=None, remove=False):
2532
self.remove_alias(name)
2534
self.print_aliases()
2536
equal_pos = name.find('=')
2538
self.print_alias(name)
2540
self.set_alias(name[:equal_pos], name[equal_pos+1:])
2542
def remove_alias(self, alias_name):
2543
if alias_name is None:
2544
raise errors.BzrCommandError(
2545
'bzr alias --remove expects an alias to remove.')
2546
# If alias is not found, print something like:
2547
# unalias: foo: not found
2548
c = config.GlobalConfig()
2549
c.unset_alias(alias_name)
2552
def print_aliases(self):
2553
"""Print out the defined aliases in a similar format to bash."""
2554
aliases = config.GlobalConfig().get_aliases()
2555
for key, value in sorted(aliases.iteritems()):
2556
self.outf.write('bzr alias %s="%s"\n' % (key, value))
2559
def print_alias(self, alias_name):
2560
from bzrlib.commands import get_alias
2561
alias = get_alias(alias_name)
2563
self.outf.write("bzr alias: %s: not found\n" % alias_name)
2566
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
2568
def set_alias(self, alias_name, alias_command):
2569
"""Save the alias in the global config."""
2570
c = config.GlobalConfig()
2571
c.set_alias(alias_name, alias_command)
2574
class cmd_selftest(Command):
2575
"""Run internal test suite.
2577
If arguments are given, they are regular expressions that say which tests
2578
should run. Tests matching any expression are run, and other tests are
2581
Alternatively if --first is given, matching tests are run first and then
2582
all other tests are run. This is useful if you have been working in a
2583
particular area, but want to make sure nothing else was broken.
2585
If --exclude is given, tests that match that regular expression are
2586
excluded, regardless of whether they match --first or not.
2588
To help catch accidential dependencies between tests, the --randomize
2589
option is useful. In most cases, the argument used is the word 'now'.
2590
Note that the seed used for the random number generator is displayed
2591
when this option is used. The seed can be explicitly passed as the
2592
argument to this option if required. This enables reproduction of the
2593
actual ordering used if and when an order sensitive problem is encountered.
2595
If --list-only is given, the tests that would be run are listed. This is
2596
useful when combined with --first, --exclude and/or --randomize to
2597
understand their impact. The test harness reports "Listed nn tests in ..."
2598
instead of "Ran nn tests in ..." when list mode is enabled.
2600
If the global option '--no-plugins' is given, plugins are not loaded
2601
before running the selftests. This has two effects: features provided or
2602
modified by plugins will not be tested, and tests provided by plugins will
2605
Tests that need working space on disk use a common temporary directory,
2606
typically inside $TMPDIR or /tmp.
2609
Run only tests relating to 'ignore'::
2613
Disable plugins and list tests as they're run::
2615
bzr --no-plugins selftest -v
2617
# NB: this is used from the class without creating an instance, which is
2618
# why it does not have a self parameter.
2619
def get_transport_type(typestring):
2620
"""Parse and return a transport specifier."""
2621
if typestring == "sftp":
2622
from bzrlib.transport.sftp import SFTPAbsoluteServer
2623
return SFTPAbsoluteServer
2624
if typestring == "memory":
2625
from bzrlib.transport.memory import MemoryServer
2627
if typestring == "fakenfs":
2628
from bzrlib.transport.fakenfs import FakeNFSServer
2629
return FakeNFSServer
2630
msg = "No known transport type %s. Supported types are: sftp\n" %\
2632
raise errors.BzrCommandError(msg)
2635
takes_args = ['testspecs*']
2636
takes_options = ['verbose',
2638
help='Stop when one test fails.',
2642
help='Use a different transport by default '
2643
'throughout the test suite.',
2644
type=get_transport_type),
2646
help='Run the benchmarks rather than selftests.'),
2647
Option('lsprof-timed',
2648
help='Generate lsprof output for benchmarked'
2649
' sections of code.'),
2650
Option('cache-dir', type=str,
2651
help='Cache intermediate benchmark output in this '
2654
help='Run all tests, but run specified tests first.',
2658
help='List the tests instead of running them.'),
2659
Option('randomize', type=str, argname="SEED",
2660
help='Randomize the order of tests using the given'
2661
' seed or "now" for the current time.'),
2662
Option('exclude', type=str, argname="PATTERN",
2664
help='Exclude tests that match this regular'
2666
Option('strict', help='Fail on missing dependencies or '
2668
Option('load-list', type=str, argname='TESTLISTFILE',
2669
help='Load a test id list from a text file.'),
2670
ListOption('debugflag', type=str, short_name='E',
2671
help='Turn on a selftest debug flag.'),
2672
ListOption('starting-with', type=str, argname='TESTID',
2673
param_name='starting_with', short_name='s',
2675
'Load only the tests starting with TESTID.'),
2677
encoding_type = 'replace'
2679
def run(self, testspecs_list=None, verbose=False, one=False,
2680
transport=None, benchmark=None,
2681
lsprof_timed=None, cache_dir=None,
2682
first=False, list_only=False,
2683
randomize=None, exclude=None, strict=False,
2684
load_list=None, debugflag=None, starting_with=None):
2686
from bzrlib.tests import selftest
2687
import bzrlib.benchmarks as benchmarks
2688
from bzrlib.benchmarks import tree_creator
2690
# Make deprecation warnings visible, unless -Werror is set
2691
symbol_versioning.activate_deprecation_warnings(override=False)
2693
if cache_dir is not None:
2694
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2696
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2697
print ' %s (%s python%s)' % (
2699
bzrlib.version_string,
2700
bzrlib._format_version_tuple(sys.version_info),
2703
if testspecs_list is not None:
2704
pattern = '|'.join(testspecs_list)
2708
test_suite_factory = benchmarks.test_suite
2709
# Unless user explicitly asks for quiet, be verbose in benchmarks
2710
verbose = not is_quiet()
2711
# TODO: should possibly lock the history file...
2712
benchfile = open(".perf_history", "at", buffering=1)
2714
test_suite_factory = None
2717
result = selftest(verbose=verbose,
2719
stop_on_failure=one,
2720
transport=transport,
2721
test_suite_factory=test_suite_factory,
2722
lsprof_timed=lsprof_timed,
2723
bench_history=benchfile,
2724
matching_tests_first=first,
2725
list_only=list_only,
2726
random_seed=randomize,
2727
exclude_pattern=exclude,
2729
load_list=load_list,
2730
debug_flags=debugflag,
2731
starting_with=starting_with,
2734
if benchfile is not None:
2737
note('tests passed')
2739
note('tests failed')
2740
return int(not result)
2743
class cmd_version(Command):
2744
"""Show version of bzr."""
2746
encoding_type = 'replace'
2748
Option("short", help="Print just the version number."),
2752
def run(self, short=False):
2753
from bzrlib.version import show_version
2755
self.outf.write(bzrlib.version_string + '\n')
2757
show_version(to_file=self.outf)
2760
class cmd_rocks(Command):
2761
"""Statement of optimism."""
2767
print "It sure does!"
2770
class cmd_find_merge_base(Command):
2771
"""Find and print a base revision for merging two branches."""
2772
# TODO: Options to specify revisions on either side, as if
2773
# merging only part of the history.
2774
takes_args = ['branch', 'other']
2778
def run(self, branch, other):
2779
from bzrlib.revision import ensure_null
2781
branch1 = Branch.open_containing(branch)[0]
2782
branch2 = Branch.open_containing(other)[0]
2787
last1 = ensure_null(branch1.last_revision())
2788
last2 = ensure_null(branch2.last_revision())
2790
graph = branch1.repository.get_graph(branch2.repository)
2791
base_rev_id = graph.find_unique_lca(last1, last2)
2793
print 'merge base is revision %s' % base_rev_id
2800
class cmd_merge(Command):
2801
"""Perform a three-way merge.
2803
The source of the merge can be specified either in the form of a branch,
2804
or in the form of a path to a file containing a merge directive generated
2805
with bzr send. If neither is specified, the default is the upstream branch
2806
or the branch most recently merged using --remember.
2808
When merging a branch, by default the tip will be merged. To pick a different
2809
revision, pass --revision. If you specify two values, the first will be used as
2810
BASE and the second one as OTHER. Merging individual revisions, or a subset of
2811
available revisions, like this is commonly referred to as "cherrypicking".
2813
Revision numbers are always relative to the branch being merged.
2815
By default, bzr will try to merge in all new work from the other
2816
branch, automatically determining an appropriate base. If this
2817
fails, you may need to give an explicit base.
2819
Merge will do its best to combine the changes in two branches, but there
2820
are some kinds of problems only a human can fix. When it encounters those,
2821
it will mark a conflict. A conflict means that you need to fix something,
2822
before you should commit.
2824
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2826
If there is no default branch set, the first merge will set it. After
2827
that, you can omit the branch to use the default. To change the
2828
default, use --remember. The value will only be saved if the remote
2829
location can be accessed.
2831
The results of the merge are placed into the destination working
2832
directory, where they can be reviewed (with bzr diff), tested, and then
2833
committed to record the result of the merge.
2835
merge refuses to run if there are any uncommitted changes, unless
2839
To merge the latest revision from bzr.dev::
2841
bzr merge ../bzr.dev
2843
To merge changes up to and including revision 82 from bzr.dev::
2845
bzr merge -r 82 ../bzr.dev
2847
To merge the changes introduced by 82, without previous changes::
2849
bzr merge -r 81..82 ../bzr.dev
2851
To apply a merge directive contained in in /tmp/merge:
2853
bzr merge /tmp/merge
2856
encoding_type = 'exact'
2857
_see_also = ['update', 'remerge', 'status-flags']
2858
takes_args = ['location?']
2863
help='Merge even if the destination tree has uncommitted changes.'),
2867
Option('show-base', help="Show base revision text in "
2869
Option('uncommitted', help='Apply uncommitted changes'
2870
' from a working copy, instead of branch changes.'),
2871
Option('pull', help='If the destination is already'
2872
' completely merged into the source, pull from the'
2873
' source rather than merging. When this happens,'
2874
' you do not need to commit the result.'),
2876
help='Branch to merge into, '
2877
'rather than the one containing the working directory.',
2881
Option('preview', help='Instead of merging, show a diff of the merge.')
2884
def run(self, location=None, revision=None, force=False,
2885
merge_type=None, show_base=False, reprocess=False, remember=False,
2886
uncommitted=False, pull=False,
2890
if merge_type is None:
2891
merge_type = _mod_merge.Merge3Merger
2893
if directory is None: directory = u'.'
2894
possible_transports = []
2896
allow_pending = True
2897
verified = 'inapplicable'
2898
tree = WorkingTree.open_containing(directory)[0]
2899
change_reporter = delta._ChangeReporter(
2900
unversioned_filter=tree.is_ignored)
2903
pb = ui.ui_factory.nested_progress_bar()
2904
cleanups.append(pb.finished)
2906
cleanups.append(tree.unlock)
2907
if location is not None:
2909
mergeable = bundle.read_mergeable_from_url(location,
2910
possible_transports=possible_transports)
2911
except errors.NotABundle:
2915
raise errors.BzrCommandError('Cannot use --uncommitted'
2916
' with bundles or merge directives.')
2918
if revision is not None:
2919
raise errors.BzrCommandError(
2920
'Cannot use -r with merge directives or bundles')
2921
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2924
if merger is None and uncommitted:
2925
if revision is not None and len(revision) > 0:
2926
raise errors.BzrCommandError('Cannot use --uncommitted and'
2927
' --revision at the same time.')
2928
location = self._select_branch_location(tree, location)[0]
2929
other_tree, other_path = WorkingTree.open_containing(location)
2930
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2932
allow_pending = False
2933
if other_path != '':
2934
merger.interesting_files = [other_path]
2937
merger, allow_pending = self._get_merger_from_branch(tree,
2938
location, revision, remember, possible_transports, pb)
2940
merger.merge_type = merge_type
2941
merger.reprocess = reprocess
2942
merger.show_base = show_base
2943
self.sanity_check_merger(merger)
2944
if (merger.base_rev_id == merger.other_rev_id and
2945
merger.other_rev_id is not None):
2946
note('Nothing to do.')
2949
if merger.interesting_files is not None:
2950
raise errors.BzrCommandError('Cannot pull individual files')
2951
if (merger.base_rev_id == tree.last_revision()):
2952
result = tree.pull(merger.other_branch, False,
2953
merger.other_rev_id)
2954
result.report(self.outf)
2956
merger.check_basis(not force)
2958
return self._do_preview(merger)
2960
return self._do_merge(merger, change_reporter, allow_pending,
2963
for cleanup in reversed(cleanups):
2966
def _do_preview(self, merger):
2967
from bzrlib.diff import show_diff_trees
2968
tree_merger = merger.make_merger()
2969
tt = tree_merger.make_preview_transform()
2971
result_tree = tt.get_preview_tree()
2972
show_diff_trees(merger.this_tree, result_tree, self.outf,
2973
old_label='', new_label='')
2977
def _do_merge(self, merger, change_reporter, allow_pending, verified):
2978
merger.change_reporter = change_reporter
2979
conflict_count = merger.do_merge()
2981
merger.set_pending()
2982
if verified == 'failed':
2983
warning('Preview patch does not match changes')
2984
if conflict_count != 0:
2989
def sanity_check_merger(self, merger):
2990
if (merger.show_base and
2991
not merger.merge_type is _mod_merge.Merge3Merger):
2992
raise errors.BzrCommandError("Show-base is not supported for this"
2993
" merge type. %s" % merger.merge_type)
2994
if merger.reprocess and not merger.merge_type.supports_reprocess:
2995
raise errors.BzrCommandError("Conflict reduction is not supported"
2996
" for merge type %s." %
2998
if merger.reprocess and merger.show_base:
2999
raise errors.BzrCommandError("Cannot do conflict reduction and"
3002
def _get_merger_from_branch(self, tree, location, revision, remember,
3003
possible_transports, pb):
3004
"""Produce a merger from a location, assuming it refers to a branch."""
3005
from bzrlib.tag import _merge_tags_if_possible
3006
# find the branch locations
3007
other_loc, user_location = self._select_branch_location(tree, location,
3009
if revision is not None and len(revision) == 2:
3010
base_loc, _unused = self._select_branch_location(tree,
3011
location, revision, 0)
3013
base_loc = other_loc
3015
other_branch, other_path = Branch.open_containing(other_loc,
3016
possible_transports)
3017
if base_loc == other_loc:
3018
base_branch = other_branch
3020
base_branch, base_path = Branch.open_containing(base_loc,
3021
possible_transports)
3022
# Find the revision ids
3023
if revision is None or len(revision) < 1 or revision[-1] is None:
3024
other_revision_id = _mod_revision.ensure_null(
3025
other_branch.last_revision())
3027
other_revision_id = revision[-1].as_revision_id(other_branch)
3028
if (revision is not None and len(revision) == 2
3029
and revision[0] is not None):
3030
base_revision_id = revision[0].as_revision_id(base_branch)
3032
base_revision_id = None
3033
# Remember where we merge from
3034
if ((remember or tree.branch.get_submit_branch() is None) and
3035
user_location is not None):
3036
tree.branch.set_submit_branch(other_branch.base)
3037
_merge_tags_if_possible(other_branch, tree.branch)
3038
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3039
other_revision_id, base_revision_id, other_branch, base_branch)
3040
if other_path != '':
3041
allow_pending = False
3042
merger.interesting_files = [other_path]
3044
allow_pending = True
3045
return merger, allow_pending
3047
def _select_branch_location(self, tree, user_location, revision=None,
3049
"""Select a branch location, according to possible inputs.
3051
If provided, branches from ``revision`` are preferred. (Both
3052
``revision`` and ``index`` must be supplied.)
3054
Otherwise, the ``location`` parameter is used. If it is None, then the
3055
``submit`` or ``parent`` location is used, and a note is printed.
3057
:param tree: The working tree to select a branch for merging into
3058
:param location: The location entered by the user
3059
:param revision: The revision parameter to the command
3060
:param index: The index to use for the revision parameter. Negative
3061
indices are permitted.
3062
:return: (selected_location, user_location). The default location
3063
will be the user-entered location.
3065
if (revision is not None and index is not None
3066
and revision[index] is not None):
3067
branch = revision[index].get_branch()
3068
if branch is not None:
3069
return branch, branch
3070
if user_location is None:
3071
location = self._get_remembered(tree, 'Merging from')
3073
location = user_location
3074
return location, user_location
3076
def _get_remembered(self, tree, verb_string):
3077
"""Use tree.branch's parent if none was supplied.
3079
Report if the remembered location was used.
3081
stored_location = tree.branch.get_submit_branch()
3082
stored_location_type = "submit"
3083
if stored_location is None:
3084
stored_location = tree.branch.get_parent()
3085
stored_location_type = "parent"
3086
mutter("%s", stored_location)
3087
if stored_location is None:
3088
raise errors.BzrCommandError("No location specified or remembered")
3089
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3090
note(u"%s remembered %s location %s", verb_string,
3091
stored_location_type, display_url)
3092
return stored_location
3095
class cmd_remerge(Command):
3098
Use this if you want to try a different merge technique while resolving
3099
conflicts. Some merge techniques are better than others, and remerge
3100
lets you try different ones on different files.
3102
The options for remerge have the same meaning and defaults as the ones for
3103
merge. The difference is that remerge can (only) be run when there is a
3104
pending merge, and it lets you specify particular files.
3107
Re-do the merge of all conflicted files, and show the base text in
3108
conflict regions, in addition to the usual THIS and OTHER texts::
3110
bzr remerge --show-base
3112
Re-do the merge of "foobar", using the weave merge algorithm, with
3113
additional processing to reduce the size of conflict regions::
3115
bzr remerge --merge-type weave --reprocess foobar
3117
takes_args = ['file*']
3122
help="Show base revision text in conflicts."),
3125
def run(self, file_list=None, merge_type=None, show_base=False,
3127
if merge_type is None:
3128
merge_type = _mod_merge.Merge3Merger
3129
tree, file_list = tree_files(file_list)
3132
parents = tree.get_parent_ids()
3133
if len(parents) != 2:
3134
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3135
" merges. Not cherrypicking or"
3137
repository = tree.branch.repository
3138
interesting_ids = None
3140
conflicts = tree.conflicts()
3141
if file_list is not None:
3142
interesting_ids = set()
3143
for filename in file_list:
3144
file_id = tree.path2id(filename)
3146
raise errors.NotVersionedError(filename)
3147
interesting_ids.add(file_id)
3148
if tree.kind(file_id) != "directory":
3151
for name, ie in tree.inventory.iter_entries(file_id):
3152
interesting_ids.add(ie.file_id)
3153
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3155
# Remerge only supports resolving contents conflicts
3156
allowed_conflicts = ('text conflict', 'contents conflict')
3157
restore_files = [c.path for c in conflicts
3158
if c.typestring in allowed_conflicts]
3159
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3160
tree.set_conflicts(ConflictList(new_conflicts))
3161
if file_list is not None:
3162
restore_files = file_list
3163
for filename in restore_files:
3165
restore(tree.abspath(filename))
3166
except errors.NotConflicted:
3168
# Disable pending merges, because the file texts we are remerging
3169
# have not had those merges performed. If we use the wrong parents
3170
# list, we imply that the working tree text has seen and rejected
3171
# all the changes from the other tree, when in fact those changes
3172
# have not yet been seen.
3173
pb = ui.ui_factory.nested_progress_bar()
3174
tree.set_parent_ids(parents[:1])
3176
merger = _mod_merge.Merger.from_revision_ids(pb,
3178
merger.interesting_ids = interesting_ids
3179
merger.merge_type = merge_type
3180
merger.show_base = show_base
3181
merger.reprocess = reprocess
3182
conflicts = merger.do_merge()
3184
tree.set_parent_ids(parents)
3194
class cmd_revert(Command):
3195
"""Revert files to a previous revision.
3197
Giving a list of files will revert only those files. Otherwise, all files
3198
will be reverted. If the revision is not specified with '--revision', the
3199
last committed revision is used.
3201
To remove only some changes, without reverting to a prior version, use
3202
merge instead. For example, "merge . --revision -2..-3" will remove the
3203
changes introduced by -2, without affecting the changes introduced by -1.
3204
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3206
By default, any files that have been manually changed will be backed up
3207
first. (Files changed only by merge are not backed up.) Backup files have
3208
'.~#~' appended to their name, where # is a number.
3210
When you provide files, you can use their current pathname or the pathname
3211
from the target revision. So you can use revert to "undelete" a file by
3212
name. If you name a directory, all the contents of that directory will be
3215
Any files that have been newly added since that revision will be deleted,
3216
with a backup kept if appropriate. Directories containing unknown files
3217
will not be deleted.
3219
The working tree contains a list of pending merged revisions, which will
3220
be included as parents in the next commit. Normally, revert clears that
3221
list as well as reverting the files. If any files are specified, revert
3222
leaves the pending merge list alone and reverts only the files. Use "bzr
3223
revert ." in the tree root to revert all files but keep the merge record,
3224
and "bzr revert --forget-merges" to clear the pending merge list without
3225
reverting any files.
3228
_see_also = ['cat', 'export']
3231
Option('no-backup', "Do not save backups of reverted files."),
3232
Option('forget-merges',
3233
'Remove pending merge marker, without changing any files.'),
3235
takes_args = ['file*']
3237
def run(self, revision=None, no_backup=False, file_list=None,
3238
forget_merges=None):
3239
tree, file_list = tree_files(file_list)
3241
tree.set_parent_ids(tree.get_parent_ids()[:1])
3243
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3246
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3247
if revision is None:
3248
rev_id = tree.last_revision()
3249
elif len(revision) != 1:
3250
raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
3252
rev_id = revision[0].as_revision_id(tree.branch)
3253
pb = ui.ui_factory.nested_progress_bar()
3255
tree.revert(file_list,
3256
tree.branch.repository.revision_tree(rev_id),
3257
not no_backup, pb, report_changes=True)
3262
class cmd_assert_fail(Command):
3263
"""Test reporting of assertion failures"""
3264
# intended just for use in testing
3269
raise AssertionError("always fails")
3272
class cmd_help(Command):
3273
"""Show help on a command or other topic.
3276
_see_also = ['topics']
3278
Option('long', 'Show help on all commands.'),
3280
takes_args = ['topic?']
3281
aliases = ['?', '--help', '-?', '-h']
3284
def run(self, topic=None, long=False):
3286
if topic is None and long:
3288
bzrlib.help.help(topic)
3291
class cmd_shell_complete(Command):
3292
"""Show appropriate completions for context.
3294
For a list of all available commands, say 'bzr shell-complete'.
3296
takes_args = ['context?']
3301
def run(self, context=None):
3302
import shellcomplete
3303
shellcomplete.shellcomplete(context)
3306
class cmd_missing(Command):
3307
"""Show unmerged/unpulled revisions between two branches.
3309
OTHER_BRANCH may be local or remote.
3312
_see_also = ['merge', 'pull']
3313
takes_args = ['other_branch?']
3315
Option('reverse', 'Reverse the order of revisions.'),
3317
'Display changes in the local branch only.'),
3318
Option('this' , 'Same as --mine-only.'),
3319
Option('theirs-only',
3320
'Display changes in the remote branch only.'),
3321
Option('other', 'Same as --theirs-only.'),
3326
encoding_type = 'replace'
3329
def run(self, other_branch=None, reverse=False, mine_only=False,
3330
theirs_only=False, log_format=None, long=False, short=False, line=False,
3331
show_ids=False, verbose=False, this=False, other=False):
3332
from bzrlib.missing import find_unmerged, iter_log_revisions
3338
# TODO: We should probably check that we don't have mine-only and
3339
# theirs-only set, but it gets complicated because we also have
3340
# this and other which could be used.
3347
local_branch = Branch.open_containing(u".")[0]
3348
parent = local_branch.get_parent()
3349
if other_branch is None:
3350
other_branch = parent
3351
if other_branch is None:
3352
raise errors.BzrCommandError("No peer location known"
3354
display_url = urlutils.unescape_for_display(parent,
3356
self.outf.write("Using saved parent location: "
3357
+ display_url + "\n")
3359
remote_branch = Branch.open(other_branch)
3360
if remote_branch.base == local_branch.base:
3361
remote_branch = local_branch
3362
local_branch.lock_read()
3364
remote_branch.lock_read()
3366
local_extra, remote_extra = find_unmerged(
3367
local_branch, remote_branch, restrict)
3369
if log_format is None:
3370
registry = log.log_formatter_registry
3371
log_format = registry.get_default(local_branch)
3372
lf = log_format(to_file=self.outf,
3374
show_timezone='original')
3375
if reverse is False:
3376
if local_extra is not None:
3377
local_extra.reverse()
3378
if remote_extra is not None:
3379
remote_extra.reverse()
3382
if local_extra and not theirs_only:
3383
self.outf.write("You have %d extra revision(s):\n" %
3385
for revision in iter_log_revisions(local_extra,
3386
local_branch.repository,
3388
lf.log_revision(revision)
3389
printed_local = True
3392
printed_local = False
3394
if remote_extra and not mine_only:
3395
if printed_local is True:
3396
self.outf.write("\n\n\n")
3397
self.outf.write("You are missing %d revision(s):\n" %
3399
for revision in iter_log_revisions(remote_extra,
3400
remote_branch.repository,
3402
lf.log_revision(revision)
3405
if mine_only and not local_extra:
3406
# We checked local, and found nothing extra
3407
self.outf.write('This branch is up to date.\n')
3408
elif theirs_only and not remote_extra:
3409
# We checked remote, and found nothing extra
3410
self.outf.write('Other branch is up to date.\n')
3411
elif not (mine_only or theirs_only or local_extra or
3413
# We checked both branches, and neither one had extra
3415
self.outf.write("Branches are up to date.\n")
3417
remote_branch.unlock()
3419
local_branch.unlock()
3420
if not status_code and parent is None and other_branch is not None:
3421
local_branch.lock_write()
3423
# handle race conditions - a parent might be set while we run.
3424
if local_branch.get_parent() is None:
3425
local_branch.set_parent(remote_branch.base)
3427
local_branch.unlock()
3431
class cmd_pack(Command):
3432
"""Compress the data within a repository."""
3434
_see_also = ['repositories']
3435
takes_args = ['branch_or_repo?']
3437
def run(self, branch_or_repo='.'):
3438
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3440
branch = dir.open_branch()
3441
repository = branch.repository
3442
except errors.NotBranchError:
3443
repository = dir.open_repository()
3447
class cmd_plugins(Command):
3448
"""List the installed plugins.
3450
This command displays the list of installed plugins including
3451
version of plugin and a short description of each.
3453
--verbose shows the path where each plugin is located.
3455
A plugin is an external component for Bazaar that extends the
3456
revision control system, by adding or replacing code in Bazaar.
3457
Plugins can do a variety of things, including overriding commands,
3458
adding new commands, providing additional network transports and
3459
customizing log output.
3461
See the Bazaar web site, http://bazaar-vcs.org, for further
3462
information on plugins including where to find them and how to
3463
install them. Instructions are also provided there on how to
3464
write new plugins using the Python programming language.
3466
takes_options = ['verbose']
3469
def run(self, verbose=False):
3470
import bzrlib.plugin
3471
from inspect import getdoc
3473
for name, plugin in bzrlib.plugin.plugins().items():
3474
version = plugin.__version__
3475
if version == 'unknown':
3477
name_ver = '%s %s' % (name, version)
3478
d = getdoc(plugin.module)
3480
doc = d.split('\n')[0]
3482
doc = '(no description)'
3483
result.append((name_ver, doc, plugin.path()))
3484
for name_ver, doc, path in sorted(result):
3492
class cmd_testament(Command):
3493
"""Show testament (signing-form) of a revision."""
3496
Option('long', help='Produce long-format testament.'),
3498
help='Produce a strict-format testament.')]
3499
takes_args = ['branch?']
3501
def run(self, branch=u'.', revision=None, long=False, strict=False):
3502
from bzrlib.testament import Testament, StrictTestament
3504
testament_class = StrictTestament
3506
testament_class = Testament
3508
b = Branch.open_containing(branch)[0]
3510
b = Branch.open(branch)
3513
if revision is None:
3514
rev_id = b.last_revision()
3516
rev_id = revision[0].as_revision_id(b)
3517
t = testament_class.from_revision(b.repository, rev_id)
3519
sys.stdout.writelines(t.as_text_lines())
3521
sys.stdout.write(t.as_short_text())
3526
class cmd_annotate(Command):
3527
"""Show the origin of each line in a file.
3529
This prints out the given file with an annotation on the left side
3530
indicating which revision, author and date introduced the change.
3532
If the origin is the same for a run of consecutive lines, it is
3533
shown only at the top, unless the --all option is given.
3535
# TODO: annotate directories; showing when each file was last changed
3536
# TODO: if the working copy is modified, show annotations on that
3537
# with new uncommitted lines marked
3538
aliases = ['ann', 'blame', 'praise']
3539
takes_args = ['filename']
3540
takes_options = [Option('all', help='Show annotations on all lines.'),
3541
Option('long', help='Show commit date in annotations.'),
3545
encoding_type = 'exact'
3548
def run(self, filename, all=False, long=False, revision=None,
3550
from bzrlib.annotate import annotate_file
3551
wt, branch, relpath = \
3552
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3558
if revision is None:
3559
revision_id = branch.last_revision()
3560
elif len(revision) != 1:
3561
raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3563
revision_id = revision[0].as_revision_id(branch)
3564
tree = branch.repository.revision_tree(revision_id)
3566
file_id = wt.path2id(relpath)
3568
file_id = tree.path2id(relpath)
3570
raise errors.NotVersionedError(filename)
3571
file_version = tree.inventory[file_id].revision
3572
annotate_file(branch, file_version, file_id, long, all, self.outf,
3581
class cmd_re_sign(Command):
3582
"""Create a digital signature for an existing revision."""
3583
# TODO be able to replace existing ones.
3585
hidden = True # is this right ?
3586
takes_args = ['revision_id*']
3587
takes_options = ['revision']
3589
def run(self, revision_id_list=None, revision=None):
3590
if revision_id_list is not None and revision is not None:
3591
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3592
if revision_id_list is None and revision is None:
3593
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3594
b = WorkingTree.open_containing(u'.')[0].branch
3597
return self._run(b, revision_id_list, revision)
3601
def _run(self, b, revision_id_list, revision):
3602
import bzrlib.gpg as gpg
3603
gpg_strategy = gpg.GPGStrategy(b.get_config())
3604
if revision_id_list is not None:
3605
b.repository.start_write_group()
3607
for revision_id in revision_id_list:
3608
b.repository.sign_revision(revision_id, gpg_strategy)
3610
b.repository.abort_write_group()
3613
b.repository.commit_write_group()
3614
elif revision is not None:
3615
if len(revision) == 1:
3616
revno, rev_id = revision[0].in_history(b)
3617
b.repository.start_write_group()
3619
b.repository.sign_revision(rev_id, gpg_strategy)
3621
b.repository.abort_write_group()
3624
b.repository.commit_write_group()
3625
elif len(revision) == 2:
3626
# are they both on rh- if so we can walk between them
3627
# might be nice to have a range helper for arbitrary
3628
# revision paths. hmm.
3629
from_revno, from_revid = revision[0].in_history(b)
3630
to_revno, to_revid = revision[1].in_history(b)
3631
if to_revid is None:
3632
to_revno = b.revno()
3633
if from_revno is None or to_revno is None:
3634
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3635
b.repository.start_write_group()
3637
for revno in range(from_revno, to_revno + 1):
3638
b.repository.sign_revision(b.get_rev_id(revno),
3641
b.repository.abort_write_group()
3644
b.repository.commit_write_group()
3646
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3649
class cmd_bind(Command):
3650
"""Convert the current branch into a checkout of the supplied branch.
3652
Once converted into a checkout, commits must succeed on the master branch
3653
before they will be applied to the local branch.
3656
_see_also = ['checkouts', 'unbind']
3657
takes_args = ['location?']
3660
def run(self, location=None):
3661
b, relpath = Branch.open_containing(u'.')
3662
if location is None:
3664
location = b.get_old_bound_location()
3665
except errors.UpgradeRequired:
3666
raise errors.BzrCommandError('No location supplied. '
3667
'This format does not remember old locations.')
3669
if location is None:
3670
raise errors.BzrCommandError('No location supplied and no '
3671
'previous location known')
3672
b_other = Branch.open(location)
3675
except errors.DivergedBranches:
3676
raise errors.BzrCommandError('These branches have diverged.'
3677
' Try merging, and then bind again.')
3680
class cmd_unbind(Command):
3681
"""Convert the current checkout into a regular branch.
3683
After unbinding, the local branch is considered independent and subsequent
3684
commits will be local only.
3687
_see_also = ['checkouts', 'bind']
3692
b, relpath = Branch.open_containing(u'.')
3694
raise errors.BzrCommandError('Local branch is not bound')
3697
class cmd_uncommit(Command):
3698
"""Remove the last committed revision.
3700
--verbose will print out what is being removed.
3701
--dry-run will go through all the motions, but not actually
3704
If --revision is specified, uncommit revisions to leave the branch at the
3705
specified revision. For example, "bzr uncommit -r 15" will leave the
3706
branch at revision 15.
3708
Uncommit leaves the working tree ready for a new commit. The only change
3709
it may make is to restore any pending merges that were present before
3713
# TODO: jam 20060108 Add an option to allow uncommit to remove
3714
# unreferenced information in 'branch-as-repository' branches.
3715
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3716
# information in shared branches as well.
3717
_see_also = ['commit']
3718
takes_options = ['verbose', 'revision',
3719
Option('dry-run', help='Don\'t actually make changes.'),
3720
Option('force', help='Say yes to all questions.'),
3722
help="Only remove the commits from the local branch"
3723
" when in a checkout."
3726
takes_args = ['location?']
3728
encoding_type = 'replace'
3730
def run(self, location=None,
3731
dry_run=False, verbose=False,
3732
revision=None, force=False, local=False):
3733
if location is None:
3735
control, relpath = bzrdir.BzrDir.open_containing(location)
3737
tree = control.open_workingtree()
3739
except (errors.NoWorkingTree, errors.NotLocalUrl):
3741
b = control.open_branch()
3743
if tree is not None:
3748
return self._run(b, tree, dry_run, verbose, revision, force,
3751
if tree is not None:
3756
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
3757
from bzrlib.log import log_formatter, show_log
3758
from bzrlib.uncommit import uncommit
3760
last_revno, last_rev_id = b.last_revision_info()
3763
if revision is None:
3765
rev_id = last_rev_id
3767
# 'bzr uncommit -r 10' actually means uncommit
3768
# so that the final tree is at revno 10.
3769
# but bzrlib.uncommit.uncommit() actually uncommits
3770
# the revisions that are supplied.
3771
# So we need to offset it by one
3772
revno = revision[0].in_history(b).revno + 1
3773
if revno <= last_revno:
3774
rev_id = b.get_rev_id(revno)
3776
if rev_id is None or _mod_revision.is_null(rev_id):
3777
self.outf.write('No revisions to uncommit.\n')
3780
lf = log_formatter('short',
3782
show_timezone='original')
3787
direction='forward',
3788
start_revision=revno,
3789
end_revision=last_revno)
3792
print 'Dry-run, pretending to remove the above revisions.'
3794
val = raw_input('Press <enter> to continue')
3796
print 'The above revision(s) will be removed.'
3798
val = raw_input('Are you sure [y/N]? ')
3799
if val.lower() not in ('y', 'yes'):
3803
mutter('Uncommitting from {%s} to {%s}',
3804
last_rev_id, rev_id)
3805
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3806
revno=revno, local=local)
3807
note('You can restore the old tip by running:\n'
3808
' bzr pull . -r revid:%s', last_rev_id)
3811
class cmd_break_lock(Command):
3812
"""Break a dead lock on a repository, branch or working directory.
3814
CAUTION: Locks should only be broken when you are sure that the process
3815
holding the lock has been stopped.
3817
You can get information on what locks are open via the 'bzr info' command.
3822
takes_args = ['location?']
3824
def run(self, location=None, show=False):
3825
if location is None:
3827
control, relpath = bzrdir.BzrDir.open_containing(location)
3829
control.break_lock()
3830
except NotImplementedError:
3834
class cmd_wait_until_signalled(Command):
3835
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3837
This just prints a line to signal when it is ready, then blocks on stdin.
3843
sys.stdout.write("running\n")
3845
sys.stdin.readline()
3848
class cmd_serve(Command):
3849
"""Run the bzr server."""
3851
aliases = ['server']
3855
help='Serve on stdin/out for use from inetd or sshd.'),
3857
help='Listen for connections on nominated port of the form '
3858
'[hostname:]portnumber. Passing 0 as the port number will '
3859
'result in a dynamically allocated port. The default port is '
3863
help='Serve contents of this directory.',
3865
Option('allow-writes',
3866
help='By default the server is a readonly server. Supplying '
3867
'--allow-writes enables write access to the contents of '
3868
'the served directory and below.'
3872
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3873
from bzrlib import lockdir
3874
from bzrlib.smart import medium, server
3875
from bzrlib.transport import get_transport
3876
from bzrlib.transport.chroot import ChrootServer
3877
if directory is None:
3878
directory = os.getcwd()
3879
url = urlutils.local_path_to_url(directory)
3880
if not allow_writes:
3881
url = 'readonly+' + url
3882
chroot_server = ChrootServer(get_transport(url))
3883
chroot_server.setUp()
3884
t = get_transport(chroot_server.get_url())
3886
smart_server = medium.SmartServerPipeStreamMedium(
3887
sys.stdin, sys.stdout, t)
3889
host = medium.BZR_DEFAULT_INTERFACE
3891
port = medium.BZR_DEFAULT_PORT
3894
host, port = port.split(':')
3896
smart_server = server.SmartTCPServer(t, host=host, port=port)
3897
print 'listening on port: ', smart_server.port
3899
# for the duration of this server, no UI output is permitted.
3900
# note that this may cause problems with blackbox tests. This should
3901
# be changed with care though, as we dont want to use bandwidth sending
3902
# progress over stderr to smart server clients!
3903
old_factory = ui.ui_factory
3904
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3906
ui.ui_factory = ui.SilentUIFactory()
3907
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3908
smart_server.serve()
3910
ui.ui_factory = old_factory
3911
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
3914
class cmd_join(Command):
3915
"""Combine a subtree into its containing tree.
3917
This command is for experimental use only. It requires the target tree
3918
to be in dirstate-with-subtree format, which cannot be converted into
3921
The TREE argument should be an independent tree, inside another tree, but
3922
not part of it. (Such trees can be produced by "bzr split", but also by
3923
running "bzr branch" with the target inside a tree.)
3925
The result is a combined tree, with the subtree no longer an independant
3926
part. This is marked as a merge of the subtree into the containing tree,
3927
and all history is preserved.
3929
If --reference is specified, the subtree retains its independence. It can
3930
be branched by itself, and can be part of multiple projects at the same
3931
time. But operations performed in the containing tree, such as commit
3932
and merge, will recurse into the subtree.
3935
_see_also = ['split']
3936
takes_args = ['tree']
3938
Option('reference', help='Join by reference.'),
3942
def run(self, tree, reference=False):
3943
sub_tree = WorkingTree.open(tree)
3944
parent_dir = osutils.dirname(sub_tree.basedir)
3945
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3946
repo = containing_tree.branch.repository
3947
if not repo.supports_rich_root():
3948
raise errors.BzrCommandError(
3949
"Can't join trees because %s doesn't support rich root data.\n"
3950
"You can use bzr upgrade on the repository."
3954
containing_tree.add_reference(sub_tree)
3955
except errors.BadReferenceTarget, e:
3956
# XXX: Would be better to just raise a nicely printable
3957
# exception from the real origin. Also below. mbp 20070306
3958
raise errors.BzrCommandError("Cannot join %s. %s" %
3962
containing_tree.subsume(sub_tree)
3963
except errors.BadSubsumeSource, e:
3964
raise errors.BzrCommandError("Cannot join %s. %s" %
3968
class cmd_split(Command):
3969
"""Split a subdirectory of a tree into a separate tree.
3971
This command will produce a target tree in a format that supports
3972
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
3973
converted into earlier formats like 'dirstate-tags'.
3975
The TREE argument should be a subdirectory of a working tree. That
3976
subdirectory will be converted into an independent tree, with its own
3977
branch. Commits in the top-level tree will not apply to the new subtree.
3980
# join is not un-hidden yet
3981
#_see_also = ['join']
3982
takes_args = ['tree']
3984
def run(self, tree):
3985
containing_tree, subdir = WorkingTree.open_containing(tree)
3986
sub_id = containing_tree.path2id(subdir)
3988
raise errors.NotVersionedError(subdir)
3990
containing_tree.extract(sub_id)
3991
except errors.RootNotRich:
3992
raise errors.UpgradeRequired(containing_tree.branch.base)
3995
class cmd_merge_directive(Command):
3996
"""Generate a merge directive for auto-merge tools.
3998
A directive requests a merge to be performed, and also provides all the
3999
information necessary to do so. This means it must either include a
4000
revision bundle, or the location of a branch containing the desired
4003
A submit branch (the location to merge into) must be supplied the first
4004
time the command is issued. After it has been supplied once, it will
4005
be remembered as the default.
4007
A public branch is optional if a revision bundle is supplied, but required
4008
if --diff or --plain is specified. It will be remembered as the default
4009
after the first use.
4012
takes_args = ['submit_branch?', 'public_branch?']
4016
_see_also = ['send']
4019
RegistryOption.from_kwargs('patch-type',
4020
'The type of patch to include in the directive.',
4022
value_switches=True,
4024
bundle='Bazaar revision bundle (default).',
4025
diff='Normal unified diff.',
4026
plain='No patch, just directive.'),
4027
Option('sign', help='GPG-sign the directive.'), 'revision',
4028
Option('mail-to', type=str,
4029
help='Instead of printing the directive, email to this address.'),
4030
Option('message', type=str, short_name='m',
4031
help='Message to use when committing this merge.')
4034
encoding_type = 'exact'
4036
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4037
sign=False, revision=None, mail_to=None, message=None):
4038
from bzrlib.revision import ensure_null, NULL_REVISION
4039
include_patch, include_bundle = {
4040
'plain': (False, False),
4041
'diff': (True, False),
4042
'bundle': (True, True),
4044
branch = Branch.open('.')
4045
stored_submit_branch = branch.get_submit_branch()
4046
if submit_branch is None:
4047
submit_branch = stored_submit_branch
4049
if stored_submit_branch is None:
4050
branch.set_submit_branch(submit_branch)
4051
if submit_branch is None:
4052
submit_branch = branch.get_parent()
4053
if submit_branch is None:
4054
raise errors.BzrCommandError('No submit branch specified or known')
4056
stored_public_branch = branch.get_public_branch()
4057
if public_branch is None:
4058
public_branch = stored_public_branch
4059
elif stored_public_branch is None:
4060
branch.set_public_branch(public_branch)
4061
if not include_bundle and public_branch is None:
4062
raise errors.BzrCommandError('No public branch specified or'
4064
base_revision_id = None
4065
if revision is not None:
4066
if len(revision) > 2:
4067
raise errors.BzrCommandError('bzr merge-directive takes '
4068
'at most two one revision identifiers')
4069
revision_id = revision[-1].as_revision_id(branch)
4070
if len(revision) == 2:
4071
base_revision_id = revision[0].as_revision_id(branch)
4073
revision_id = branch.last_revision()
4074
revision_id = ensure_null(revision_id)
4075
if revision_id == NULL_REVISION:
4076
raise errors.BzrCommandError('No revisions to bundle.')
4077
directive = merge_directive.MergeDirective2.from_objects(
4078
branch.repository, revision_id, time.time(),
4079
osutils.local_time_offset(), submit_branch,
4080
public_branch=public_branch, include_patch=include_patch,
4081
include_bundle=include_bundle, message=message,
4082
base_revision_id=base_revision_id)
4085
self.outf.write(directive.to_signed(branch))
4087
self.outf.writelines(directive.to_lines())
4089
message = directive.to_email(mail_to, branch, sign)
4090
s = SMTPConnection(branch.get_config())
4091
s.send_email(message)
4094
class cmd_send(Command):
4095
"""Mail or create a merge-directive for submiting changes.
4097
A merge directive provides many things needed for requesting merges:
4099
* A machine-readable description of the merge to perform
4101
* An optional patch that is a preview of the changes requested
4103
* An optional bundle of revision data, so that the changes can be applied
4104
directly from the merge directive, without retrieving data from a
4107
If --no-bundle is specified, then public_branch is needed (and must be
4108
up-to-date), so that the receiver can perform the merge using the
4109
public_branch. The public_branch is always included if known, so that
4110
people can check it later.
4112
The submit branch defaults to the parent, but can be overridden. Both
4113
submit branch and public branch will be remembered if supplied.
4115
If a public_branch is known for the submit_branch, that public submit
4116
branch is used in the merge instructions. This means that a local mirror
4117
can be used as your actual submit branch, once you have set public_branch
4120
Mail is sent using your preferred mail program. This should be transparent
4121
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4122
If the preferred client can't be found (or used), your editor will be used.
4124
To use a specific mail program, set the mail_client configuration option.
4125
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4126
specific clients are "evolution", "kmail", "mutt", and "thunderbird";
4127
generic options are "default", "editor", "emacsclient", "mapi", and
4128
"xdg-email". Plugins may also add supported clients.
4130
If mail is being sent, a to address is required. This can be supplied
4131
either on the commandline, by setting the submit_to configuration
4132
option in the branch itself or the child_submit_to configuration option
4133
in the submit branch.
4135
Two formats are currently supported: "4" uses revision bundle format 4 and
4136
merge directive format 2. It is significantly faster and smaller than
4137
older formats. It is compatible with Bazaar 0.19 and later. It is the
4138
default. "0.9" uses revision bundle format 0.9 and merge directive
4139
format 1. It is compatible with Bazaar 0.12 - 0.18.
4141
Merge directives are applied using the merge command or the pull command.
4144
encoding_type = 'exact'
4146
_see_also = ['merge', 'pull']
4148
takes_args = ['submit_branch?', 'public_branch?']
4152
help='Do not include a bundle in the merge directive.'),
4153
Option('no-patch', help='Do not include a preview patch in the merge'
4156
help='Remember submit and public branch.'),
4158
help='Branch to generate the submission from, '
4159
'rather than the one containing the working directory.',
4162
Option('output', short_name='o',
4163
help='Write merge directive to this file; '
4164
'use - for stdout.',
4166
Option('mail-to', help='Mail the request to this address.',
4170
RegistryOption.from_kwargs('format',
4171
'Use the specified output format.',
4172
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4173
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4176
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4177
no_patch=False, revision=None, remember=False, output=None,
4178
format='4', mail_to=None, message=None, **kwargs):
4179
return self._run(submit_branch, revision, public_branch, remember,
4180
format, no_bundle, no_patch, output,
4181
kwargs.get('from', '.'), mail_to, message)
4183
def _run(self, submit_branch, revision, public_branch, remember, format,
4184
no_bundle, no_patch, output, from_, mail_to, message):
4185
from bzrlib.revision import NULL_REVISION
4186
branch = Branch.open_containing(from_)[0]
4188
outfile = StringIO()
4192
outfile = open(output, 'wb')
4193
# we may need to write data into branch's repository to calculate
4198
config = branch.get_config()
4200
mail_to = config.get_user_option('submit_to')
4201
mail_client = config.get_mail_client()
4202
if remember and submit_branch is None:
4203
raise errors.BzrCommandError(
4204
'--remember requires a branch to be specified.')
4205
stored_submit_branch = branch.get_submit_branch()
4206
remembered_submit_branch = None
4207
if submit_branch is None:
4208
submit_branch = stored_submit_branch
4209
remembered_submit_branch = "submit"
4211
if stored_submit_branch is None or remember:
4212
branch.set_submit_branch(submit_branch)
4213
if submit_branch is None:
4214
submit_branch = branch.get_parent()
4215
remembered_submit_branch = "parent"
4216
if submit_branch is None:
4217
raise errors.BzrCommandError('No submit branch known or'
4219
if remembered_submit_branch is not None:
4220
note('Using saved %s location "%s" to determine what '
4221
'changes to submit.', remembered_submit_branch,
4225
submit_config = Branch.open(submit_branch).get_config()
4226
mail_to = submit_config.get_user_option("child_submit_to")
4228
stored_public_branch = branch.get_public_branch()
4229
if public_branch is None:
4230
public_branch = stored_public_branch
4231
elif stored_public_branch is None or remember:
4232
branch.set_public_branch(public_branch)
4233
if no_bundle and public_branch is None:
4234
raise errors.BzrCommandError('No public branch specified or'
4236
base_revision_id = None
4238
if revision is not None:
4239
if len(revision) > 2:
4240
raise errors.BzrCommandError('bzr send takes '
4241
'at most two one revision identifiers')
4242
revision_id = revision[-1].as_revision_id(branch)
4243
if len(revision) == 2:
4244
base_revision_id = revision[0].as_revision_id(branch)
4245
if revision_id is None:
4246
revision_id = branch.last_revision()
4247
if revision_id == NULL_REVISION:
4248
raise errors.BzrCommandError('No revisions to submit.')
4250
directive = merge_directive.MergeDirective2.from_objects(
4251
branch.repository, revision_id, time.time(),
4252
osutils.local_time_offset(), submit_branch,
4253
public_branch=public_branch, include_patch=not no_patch,
4254
include_bundle=not no_bundle, message=message,
4255
base_revision_id=base_revision_id)
4256
elif format == '0.9':
4259
patch_type = 'bundle'
4261
raise errors.BzrCommandError('Format 0.9 does not'
4262
' permit bundle with no patch')
4268
directive = merge_directive.MergeDirective.from_objects(
4269
branch.repository, revision_id, time.time(),
4270
osutils.local_time_offset(), submit_branch,
4271
public_branch=public_branch, patch_type=patch_type,
4274
outfile.writelines(directive.to_lines())
4276
subject = '[MERGE] '
4277
if message is not None:
4280
revision = branch.repository.get_revision(revision_id)
4281
subject += revision.get_summary()
4282
basename = directive.get_disk_name(branch)
4283
mail_client.compose_merge_request(mail_to, subject,
4284
outfile.getvalue(), basename)
4291
class cmd_bundle_revisions(cmd_send):
4293
"""Create a merge-directive for submiting changes.
4295
A merge directive provides many things needed for requesting merges:
4297
* A machine-readable description of the merge to perform
4299
* An optional patch that is a preview of the changes requested
4301
* An optional bundle of revision data, so that the changes can be applied
4302
directly from the merge directive, without retrieving data from a
4305
If --no-bundle is specified, then public_branch is needed (and must be
4306
up-to-date), so that the receiver can perform the merge using the
4307
public_branch. The public_branch is always included if known, so that
4308
people can check it later.
4310
The submit branch defaults to the parent, but can be overridden. Both
4311
submit branch and public branch will be remembered if supplied.
4313
If a public_branch is known for the submit_branch, that public submit
4314
branch is used in the merge instructions. This means that a local mirror
4315
can be used as your actual submit branch, once you have set public_branch
4318
Two formats are currently supported: "4" uses revision bundle format 4 and
4319
merge directive format 2. It is significantly faster and smaller than
4320
older formats. It is compatible with Bazaar 0.19 and later. It is the
4321
default. "0.9" uses revision bundle format 0.9 and merge directive
4322
format 1. It is compatible with Bazaar 0.12 - 0.18.
4327
help='Do not include a bundle in the merge directive.'),
4328
Option('no-patch', help='Do not include a preview patch in the merge'
4331
help='Remember submit and public branch.'),
4333
help='Branch to generate the submission from, '
4334
'rather than the one containing the working directory.',
4337
Option('output', short_name='o', help='Write directive to this file.',
4340
RegistryOption.from_kwargs('format',
4341
'Use the specified output format.',
4342
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4343
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4345
aliases = ['bundle']
4347
_see_also = ['send', 'merge']
4351
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4352
no_patch=False, revision=None, remember=False, output=None,
4353
format='4', **kwargs):
4356
return self._run(submit_branch, revision, public_branch, remember,
4357
format, no_bundle, no_patch, output,
4358
kwargs.get('from', '.'), None, None)
4361
class cmd_tag(Command):
4362
"""Create, remove or modify a tag naming a revision.
4364
Tags give human-meaningful names to revisions. Commands that take a -r
4365
(--revision) option can be given -rtag:X, where X is any previously
4368
Tags are stored in the branch. Tags are copied from one branch to another
4369
along when you branch, push, pull or merge.
4371
It is an error to give a tag name that already exists unless you pass
4372
--force, in which case the tag is moved to point to the new revision.
4374
To rename a tag (change the name but keep it on the same revsion), run ``bzr
4375
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4378
_see_also = ['commit', 'tags']
4379
takes_args = ['tag_name']
4382
help='Delete this tag rather than placing it.',
4385
help='Branch in which to place the tag.',
4390
help='Replace existing tags.',
4395
def run(self, tag_name,
4401
branch, relpath = Branch.open_containing(directory)
4405
branch.tags.delete_tag(tag_name)
4406
self.outf.write('Deleted tag %s.\n' % tag_name)
4409
if len(revision) != 1:
4410
raise errors.BzrCommandError(
4411
"Tags can only be placed on a single revision, "
4413
revision_id = revision[0].as_revision_id(branch)
4415
revision_id = branch.last_revision()
4416
if (not force) and branch.tags.has_tag(tag_name):
4417
raise errors.TagAlreadyExists(tag_name)
4418
branch.tags.set_tag(tag_name, revision_id)
4419
self.outf.write('Created tag %s.\n' % tag_name)
4424
class cmd_tags(Command):
4427
This command shows a table of tag names and the revisions they reference.
4433
help='Branch whose tags should be displayed.',
4437
RegistryOption.from_kwargs('sort',
4438
'Sort tags by different criteria.', title='Sorting',
4439
alpha='Sort tags lexicographically (default).',
4440
time='Sort tags chronologically.',
4451
branch, relpath = Branch.open_containing(directory)
4452
tags = branch.tags.get_tag_dict().items()
4457
elif sort == 'time':
4459
for tag, revid in tags:
4461
revobj = branch.repository.get_revision(revid)
4462
except errors.NoSuchRevision:
4463
timestamp = sys.maxint # place them at the end
4465
timestamp = revobj.timestamp
4466
timestamps[revid] = timestamp
4467
tags.sort(key=lambda x: timestamps[x[1]])
4469
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
4470
revno_map = branch.get_revision_id_to_revno_map()
4471
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4472
for tag, revid in tags ]
4473
for tag, revspec in tags:
4474
self.outf.write('%-20s %s\n' % (tag, revspec))
4477
class cmd_reconfigure(Command):
4478
"""Reconfigure the type of a bzr directory.
4480
A target configuration must be specified.
4482
For checkouts, the bind-to location will be auto-detected if not specified.
4483
The order of preference is
4484
1. For a lightweight checkout, the current bound location.
4485
2. For branches that used to be checkouts, the previously-bound location.
4486
3. The push location.
4487
4. The parent location.
4488
If none of these is available, --bind-to must be specified.
4491
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4492
takes_args = ['location?']
4493
takes_options = [RegistryOption.from_kwargs('target_type',
4494
title='Target type',
4495
help='The type to reconfigure the directory to.',
4496
value_switches=True, enum_switch=False,
4497
branch='Reconfigure to be an unbound branch '
4498
'with no working tree.',
4499
tree='Reconfigure to be an unbound branch '
4500
'with a working tree.',
4501
checkout='Reconfigure to be a bound branch '
4502
'with a working tree.',
4503
lightweight_checkout='Reconfigure to be a lightweight'
4504
' checkout (with no local history).',
4505
standalone='Reconfigure to be a standalone branch '
4506
'(i.e. stop using shared repository).',
4507
use_shared='Reconfigure to use a shared repository.'),
4508
Option('bind-to', help='Branch to bind checkout to.',
4511
help='Perform reconfiguration even if local changes'
4515
def run(self, location=None, target_type=None, bind_to=None, force=False):
4516
directory = bzrdir.BzrDir.open(location)
4517
if target_type is None:
4518
raise errors.BzrCommandError('No target configuration specified')
4519
elif target_type == 'branch':
4520
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4521
elif target_type == 'tree':
4522
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4523
elif target_type == 'checkout':
4524
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4526
elif target_type == 'lightweight-checkout':
4527
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4529
elif target_type == 'use-shared':
4530
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
4531
elif target_type == 'standalone':
4532
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
4533
reconfiguration.apply(force)
4536
class cmd_switch(Command):
4537
"""Set the branch of a checkout and update.
4539
For lightweight checkouts, this changes the branch being referenced.
4540
For heavyweight checkouts, this checks that there are no local commits
4541
versus the current bound branch, then it makes the local branch a mirror
4542
of the new location and binds to it.
4544
In both cases, the working tree is updated and uncommitted changes
4545
are merged. The user can commit or revert these as they desire.
4547
Pending merges need to be committed or reverted before using switch.
4549
The path to the branch to switch to can be specified relative to the parent
4550
directory of the current branch. For example, if you are currently in a
4551
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
4555
takes_args = ['to_location']
4556
takes_options = [Option('force',
4557
help='Switch even if local commits will be lost.')
4560
def run(self, to_location, force=False):
4561
from bzrlib import switch
4563
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4565
to_branch = Branch.open(to_location)
4566
except errors.NotBranchError:
4567
to_branch = Branch.open(
4568
control_dir.open_branch().base + '../' + to_location)
4569
switch.switch(control_dir, to_branch, force)
4570
note('Switched to branch: %s',
4571
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4574
class cmd_hooks(Command):
4575
"""Show a branch's currently registered hooks.
4579
takes_args = ['path?']
4581
def run(self, path=None):
4584
branch_hooks = Branch.open(path).hooks
4585
for hook_type in branch_hooks:
4586
hooks = branch_hooks[hook_type]
4587
self.outf.write("%s:\n" % (hook_type,))
4590
self.outf.write(" %s\n" %
4591
(branch_hooks.get_hook_name(hook),))
4593
self.outf.write(" <no hooks installed>\n")
4596
def _create_prefix(cur_transport):
4597
needed = [cur_transport]
4598
# Recurse upwards until we can create a directory successfully
4600
new_transport = cur_transport.clone('..')
4601
if new_transport.base == cur_transport.base:
4602
raise errors.BzrCommandError(
4603
"Failed to create path prefix for %s."
4604
% cur_transport.base)
4606
new_transport.mkdir('.')
4607
except errors.NoSuchFile:
4608
needed.append(new_transport)
4609
cur_transport = new_transport
4612
# Now we only need to create child directories
4614
cur_transport = needed.pop()
4615
cur_transport.ensure_base()
4618
# these get imported and then picked up by the scan for cmd_*
4619
# TODO: Some more consistent way to split command definitions across files;
4620
# we do need to load at least some information about them to know of
4621
# aliases. ideally we would avoid loading the implementation until the
4622
# details were needed.
4623
from bzrlib.cmd_version_info import cmd_version_info
4624
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
4625
from bzrlib.bundle.commands import (
4628
from bzrlib.sign_my_commits import cmd_sign_my_commits
4629
from bzrlib.weave_commands import cmd_versionedfile_list, \
4630
cmd_weave_plan_merge, cmd_weave_merge_text