1
# Copyright (C) 2004, 2005, 2006, 2007 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(), """
54
from bzrlib.branch import Branch
55
from bzrlib.conflicts import ConflictList
56
from bzrlib.revisionspec import RevisionSpec
57
from bzrlib.smtp_connection import SMTPConnection
58
from bzrlib.workingtree import WorkingTree
61
from bzrlib.commands import Command, display_command
62
from bzrlib.option import ListOption, Option, RegistryOption
63
from bzrlib.progress import DummyProgress, ProgressPhase
64
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
67
def tree_files(file_list, default_branch=u'.'):
69
return internal_tree_files(file_list, default_branch)
70
except errors.FileInWrongBranch, e:
71
raise errors.BzrCommandError("%s is not in the same branch as %s" %
72
(e.path, file_list[0]))
75
# XXX: Bad function name; should possibly also be a class method of
76
# WorkingTree rather than a function.
77
def internal_tree_files(file_list, default_branch=u'.'):
78
"""Convert command-line paths to a WorkingTree and relative paths.
80
This is typically used for command-line processors that take one or
81
more filenames, and infer the workingtree that contains them.
83
The filenames given are not required to exist.
85
:param file_list: Filenames to convert.
87
:param default_branch: Fallback tree path to use if file_list is empty or
90
:return: workingtree, [relative_paths]
92
if file_list is None or len(file_list) == 0:
93
return WorkingTree.open_containing(default_branch)[0], file_list
94
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
96
for filename in file_list:
98
new_list.append(tree.relpath(osutils.dereference_path(filename)))
99
except errors.PathNotChild:
100
raise errors.FileInWrongBranch(tree.branch, filename)
101
return tree, new_list
104
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
105
def get_format_type(typestring):
106
"""Parse and return a format specifier."""
107
# Have to use BzrDirMetaFormat1 directly, so that
108
# RepositoryFormat.set_default_format works
109
if typestring == "default":
110
return bzrdir.BzrDirMetaFormat1()
112
return bzrdir.format_registry.make_bzrdir(typestring)
114
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
115
raise errors.BzrCommandError(msg)
118
# TODO: Make sure no commands unconditionally use the working directory as a
119
# branch. If a filename argument is used, the first of them should be used to
120
# specify the branch. (Perhaps this can be factored out into some kind of
121
# Argument class, representing a file in a branch, where the first occurrence
124
class cmd_status(Command):
125
"""Display status summary.
127
This reports on versioned and unknown files, reporting them
128
grouped by state. Possible states are:
131
Versioned in the working copy but not in the previous revision.
134
Versioned in the previous revision but removed or deleted
138
Path of this file changed from the previous revision;
139
the text may also have changed. This includes files whose
140
parent directory was renamed.
143
Text has changed since the previous revision.
146
File kind has been changed (e.g. from file to directory).
149
Not versioned and not matching an ignore pattern.
151
To see ignored files use 'bzr ignored'. For details on the
152
changes to file texts, use 'bzr diff'.
154
--short gives a status flags for each item, similar to the SVN's status
157
If no arguments are specified, the status of the entire working
158
directory is shown. Otherwise, only the status of the specified
159
files or directories is reported. If a directory is given, status
160
is reported for everything inside that directory.
162
If a revision argument is given, the status is calculated against
163
that revision, or between two revisions if two are provided.
166
# TODO: --no-recurse, --recurse options
168
takes_args = ['file*']
169
takes_options = ['show-ids', 'revision',
170
Option('short', help='Give short SVN-style status lines'),
171
Option('versioned', help='Only show versioned files')]
172
aliases = ['st', 'stat']
174
encoding_type = 'replace'
175
_see_also = ['diff', 'revert', 'status-flags']
178
def run(self, show_ids=False, file_list=None, revision=None, short=False,
180
from bzrlib.status import show_tree_status
182
tree, file_list = tree_files(file_list)
184
show_tree_status(tree, show_ids=show_ids,
185
specific_files=file_list, revision=revision,
186
to_file=self.outf, short=short, versioned=versioned)
189
class cmd_cat_revision(Command):
190
"""Write out metadata for a revision.
192
The revision to print can either be specified by a specific
193
revision identifier, or you can use --revision.
197
takes_args = ['revision_id?']
198
takes_options = ['revision']
199
# cat-revision is more for frontends so should be exact
203
def run(self, revision_id=None, revision=None):
205
revision_id = osutils.safe_revision_id(revision_id, warn=False)
206
if revision_id is not None and revision is not None:
207
raise errors.BzrCommandError('You can only supply one of'
208
' revision_id or --revision')
209
if revision_id is None and revision is None:
210
raise errors.BzrCommandError('You must supply either'
211
' --revision or a revision_id')
212
b = WorkingTree.open_containing(u'.')[0].branch
214
# TODO: jam 20060112 should cat-revision always output utf-8?
215
if revision_id is not None:
216
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
217
elif revision is not None:
220
raise errors.BzrCommandError('You cannot specify a NULL'
222
revno, rev_id = rev.in_history(b)
223
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
226
class cmd_remove_tree(Command):
227
"""Remove the working tree from a given branch/checkout.
229
Since a lightweight checkout is little more than a working tree
230
this will refuse to run against one.
232
To re-create the working tree, use "bzr checkout".
234
_see_also = ['checkout', 'working-trees']
236
takes_args = ['location?']
238
def run(self, location='.'):
239
d = bzrdir.BzrDir.open(location)
242
working = d.open_workingtree()
243
except errors.NoWorkingTree:
244
raise errors.BzrCommandError("No working tree to remove")
245
except errors.NotLocalUrl:
246
raise errors.BzrCommandError("You cannot remove the working tree of a "
249
working_path = working.bzrdir.root_transport.base
250
branch_path = working.branch.bzrdir.root_transport.base
251
if working_path != branch_path:
252
raise errors.BzrCommandError("You cannot remove the working tree from "
253
"a lightweight checkout")
255
d.destroy_workingtree()
258
class cmd_revno(Command):
259
"""Show current revision number.
261
This is equal to the number of revisions on this branch.
265
takes_args = ['location?']
268
def run(self, location=u'.'):
269
self.outf.write(str(Branch.open_containing(location)[0].revno()))
270
self.outf.write('\n')
273
class cmd_revision_info(Command):
274
"""Show revision number and revision id for a given revision identifier.
277
takes_args = ['revision_info*']
278
takes_options = ['revision']
281
def run(self, revision=None, revision_info_list=[]):
284
if revision is not None:
285
revs.extend(revision)
286
if revision_info_list is not None:
287
for rev in revision_info_list:
288
revs.append(RevisionSpec.from_string(rev))
290
b = Branch.open_containing(u'.')[0]
293
revs.append(RevisionSpec.from_string('-1'))
296
revinfo = rev.in_history(b)
297
if revinfo.revno is None:
298
dotted_map = b.get_revision_id_to_revno_map()
299
revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
300
print '%s %s' % (revno, revinfo.rev_id)
302
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
305
class cmd_add(Command):
306
"""Add specified files or directories.
308
In non-recursive mode, all the named items are added, regardless
309
of whether they were previously ignored. A warning is given if
310
any of the named files are already versioned.
312
In recursive mode (the default), files are treated the same way
313
but the behaviour for directories is different. Directories that
314
are already versioned do not give a warning. All directories,
315
whether already versioned or not, are searched for files or
316
subdirectories that are neither versioned or ignored, and these
317
are added. This search proceeds recursively into versioned
318
directories. If no names are given '.' is assumed.
320
Therefore simply saying 'bzr add' will version all files that
321
are currently unknown.
323
Adding a file whose parent directory is not versioned will
324
implicitly add the parent, and so on up to the root. This means
325
you should never need to explicitly add a directory, they'll just
326
get added when you add a file in the directory.
328
--dry-run will show which files would be added, but not actually
331
--file-ids-from will try to use the file ids from the supplied path.
332
It looks up ids trying to find a matching parent directory with the
333
same filename, and then by pure path. This option is rarely needed
334
but can be useful when adding the same logical file into two
335
branches that will be merged later (without showing the two different
336
adds as a conflict). It is also useful when merging another project
337
into a subdirectory of this one.
339
takes_args = ['file*']
340
takes_options = ['no-recurse', 'dry-run', 'verbose',
341
Option('file-ids-from', type=unicode,
342
help='Lookup file ids from here')]
343
encoding_type = 'replace'
344
_see_also = ['remove']
346
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
351
if file_ids_from is not None:
353
base_tree, base_path = WorkingTree.open_containing(
355
except errors.NoWorkingTree:
356
base_branch, base_path = Branch.open_containing(
358
base_tree = base_branch.basis_tree()
360
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
361
to_file=self.outf, should_print=(not is_quiet()))
363
action = bzrlib.add.AddAction(to_file=self.outf,
364
should_print=(not is_quiet()))
367
base_tree.lock_read()
369
file_list = self._maybe_expand_globs(file_list)
371
tree = WorkingTree.open_containing(file_list[0])[0]
373
tree = WorkingTree.open_containing(u'.')[0]
374
added, ignored = tree.smart_add(file_list, not
375
no_recurse, action=action, save=not dry_run)
377
if base_tree is not None:
381
for glob in sorted(ignored.keys()):
382
for path in ignored[glob]:
383
self.outf.write("ignored %s matching \"%s\"\n"
387
for glob, paths in ignored.items():
388
match_len += len(paths)
389
self.outf.write("ignored %d file(s).\n" % match_len)
390
self.outf.write("If you wish to add some of these files,"
391
" please add them by name.\n")
394
class cmd_mkdir(Command):
395
"""Create a new versioned directory.
397
This is equivalent to creating the directory and then adding it.
400
takes_args = ['dir+']
401
encoding_type = 'replace'
403
def run(self, dir_list):
406
wt, dd = WorkingTree.open_containing(d)
408
self.outf.write('added %s\n' % d)
411
class cmd_relpath(Command):
412
"""Show path of a file relative to root"""
414
takes_args = ['filename']
418
def run(self, filename):
419
# TODO: jam 20050106 Can relpath return a munged path if
420
# sys.stdout encoding cannot represent it?
421
tree, relpath = WorkingTree.open_containing(filename)
422
self.outf.write(relpath)
423
self.outf.write('\n')
426
class cmd_inventory(Command):
427
"""Show inventory of the current working copy or a revision.
429
It is possible to limit the output to a particular entry
430
type using the --kind option. For example: --kind file.
432
It is also possible to restrict the list of files to a specific
433
set. For example: bzr inventory --show-ids this/file
438
takes_options = ['revision', 'show-ids', 'kind']
439
takes_args = ['file*']
442
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
443
if kind and kind not in ['file', 'directory', 'symlink']:
444
raise errors.BzrCommandError('invalid kind specified')
446
work_tree, file_list = tree_files(file_list)
447
work_tree.lock_read()
449
if revision is not None:
450
if len(revision) > 1:
451
raise errors.BzrCommandError(
452
'bzr inventory --revision takes exactly one revision'
454
revision_id = revision[0].in_history(work_tree.branch).rev_id
455
tree = work_tree.branch.repository.revision_tree(revision_id)
457
extra_trees = [work_tree]
463
if file_list is not None:
464
file_ids = tree.paths2ids(file_list, trees=extra_trees,
465
require_versioned=True)
466
# find_ids_across_trees may include some paths that don't
468
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
469
for file_id in file_ids if file_id in tree)
471
entries = tree.inventory.entries()
474
if tree is not work_tree:
477
for path, entry in entries:
478
if kind and kind != entry.kind:
481
self.outf.write('%-50s %s\n' % (path, entry.file_id))
483
self.outf.write(path)
484
self.outf.write('\n')
487
class cmd_mv(Command):
488
"""Move or rename a file.
491
bzr mv OLDNAME NEWNAME
492
bzr mv SOURCE... DESTINATION
494
If the last argument is a versioned directory, all the other names
495
are moved into it. Otherwise, there must be exactly two arguments
496
and the file is changed to a new name.
498
If OLDNAME does not exist on the filesystem but is versioned and
499
NEWNAME does exist on the filesystem but is not versioned, mv
500
assumes that the file has been manually moved and only updates
501
its internal inventory to reflect that change.
502
The same is valid when moving many SOURCE files to a DESTINATION.
504
Files cannot be moved between branches.
507
takes_args = ['names*']
508
takes_options = [Option("after", help="move only the bzr identifier"
509
" of the file (file has already been moved). Use this flag if"
510
" bzr is not able to detect this itself.")]
511
aliases = ['move', 'rename']
512
encoding_type = 'replace'
514
def run(self, names_list, after=False):
515
if names_list is None:
518
if len(names_list) < 2:
519
raise errors.BzrCommandError("missing file argument")
520
tree, rel_names = tree_files(names_list)
522
if os.path.isdir(names_list[-1]):
523
# move into existing directory
524
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
525
self.outf.write("%s => %s\n" % pair)
527
if len(names_list) != 2:
528
raise errors.BzrCommandError('to mv multiple files the'
529
' destination must be a versioned'
531
tree.rename_one(rel_names[0], rel_names[1], after=after)
532
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
535
class cmd_pull(Command):
536
"""Turn this branch into a mirror of another branch.
538
This command only works on branches that have not diverged. Branches are
539
considered diverged if the destination branch's most recent commit is one
540
that has not been merged (directly or indirectly) into the parent.
542
If branches have diverged, you can use 'bzr merge' to integrate the changes
543
from one into the other. Once one branch has merged, the other should
544
be able to pull it again.
546
If you want to forget your local changes and just update your branch to
547
match the remote one, use pull --overwrite.
549
If there is no default location set, the first pull will set it. After
550
that, you can omit the location to use the default. To change the
551
default, use --remember. The value will only be saved if the remote
552
location can be accessed.
555
_see_also = ['push', 'update', 'status-flags']
556
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
558
help='branch to pull into, '
559
'rather than the one containing the working directory',
564
takes_args = ['location?']
565
encoding_type = 'replace'
567
def run(self, location=None, remember=False, overwrite=False,
568
revision=None, verbose=False,
570
from bzrlib.tag import _merge_tags_if_possible
571
# FIXME: too much stuff is in the command class
574
if directory is None:
577
tree_to = WorkingTree.open_containing(directory)[0]
578
branch_to = tree_to.branch
579
except errors.NoWorkingTree:
581
branch_to = Branch.open_containing(directory)[0]
584
if location is not None:
586
mergeable = bundle.read_mergeable_from_url(
588
except errors.NotABundle:
589
pass # Continue on considering this url a Branch
591
stored_loc = branch_to.get_parent()
593
if stored_loc is None:
594
raise errors.BzrCommandError("No pull location known or"
597
display_url = urlutils.unescape_for_display(stored_loc,
599
self.outf.write("Using saved location: %s\n" % display_url)
600
location = stored_loc
602
if mergeable is not None:
603
if revision is not None:
604
raise errors.BzrCommandError(
605
'Cannot use -r with merge directives or bundles')
606
mergeable.install_revisions(branch_to.repository)
607
base_revision_id, revision_id, verified = \
608
mergeable.get_merge_request(branch_to.repository)
609
branch_from = branch_to
611
branch_from = Branch.open(location)
613
if branch_to.get_parent() is None or remember:
614
branch_to.set_parent(branch_from.base)
616
if revision is not None:
617
if len(revision) == 1:
618
revision_id = revision[0].in_history(branch_from).rev_id
620
raise errors.BzrCommandError(
621
'bzr pull --revision takes one value.')
623
old_rh = branch_to.revision_history()
624
if tree_to is not None:
625
result = tree_to.pull(branch_from, overwrite, revision_id,
626
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
628
result = branch_to.pull(branch_from, overwrite, revision_id)
630
result.report(self.outf)
632
from bzrlib.log import show_changed_revisions
633
new_rh = branch_to.revision_history()
634
show_changed_revisions(branch_to, old_rh, new_rh,
638
class cmd_push(Command):
639
"""Update a mirror of this branch.
641
The target branch will not have its working tree populated because this
642
is both expensive, and is not supported on remote file systems.
644
Some smart servers or protocols *may* put the working tree in place in
647
This command only works on branches that have not diverged. Branches are
648
considered diverged if the destination branch's most recent commit is one
649
that has not been merged (directly or indirectly) by the source branch.
651
If branches have diverged, you can use 'bzr push --overwrite' to replace
652
the other branch completely, discarding its unmerged changes.
654
If you want to ensure you have the different changes in the other branch,
655
do a merge (see bzr help merge) from the other branch, and commit that.
656
After that you will be able to do a push without '--overwrite'.
658
If there is no default push location set, the first push will set it.
659
After that, you can omit the location to use the default. To change the
660
default, use --remember. The value will only be saved if the remote
661
location can be accessed.
664
_see_also = ['pull', 'update', 'working-trees']
665
takes_options = ['remember', 'overwrite', 'verbose',
666
Option('create-prefix',
667
help='Create the path leading up to the branch '
668
'if it does not already exist'),
670
help='branch to push from, '
671
'rather than the one containing the working directory',
675
Option('use-existing-dir',
676
help='By default push will fail if the target'
677
' directory exists, but does not already'
678
' have a control directory. This flag will'
679
' allow push to proceed.'),
681
takes_args = ['location?']
682
encoding_type = 'replace'
684
def run(self, location=None, remember=False, overwrite=False,
685
create_prefix=False, verbose=False,
686
use_existing_dir=False,
688
# FIXME: Way too big! Put this into a function called from the
690
if directory is None:
692
br_from = Branch.open_containing(directory)[0]
693
stored_loc = br_from.get_push_location()
695
if stored_loc is None:
696
raise errors.BzrCommandError("No push location known or specified.")
698
display_url = urlutils.unescape_for_display(stored_loc,
700
self.outf.write("Using saved location: %s\n" % display_url)
701
location = stored_loc
703
to_transport = transport.get_transport(location)
705
br_to = repository_to = dir_to = None
707
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
708
except errors.NotBranchError:
709
pass # Didn't find anything
711
# If we can open a branch, use its direct repository, otherwise see
712
# if there is a repository without a branch.
714
br_to = dir_to.open_branch()
715
except errors.NotBranchError:
716
# Didn't find a branch, can we find a repository?
718
repository_to = dir_to.find_repository()
719
except errors.NoRepositoryPresent:
722
# Found a branch, so we must have found a repository
723
repository_to = br_to.repository
727
# The destination doesn't exist; create it.
728
# XXX: Refactor the create_prefix/no_create_prefix code into a
729
# common helper function
731
to_transport.mkdir('.')
732
except errors.FileExists:
733
if not use_existing_dir:
734
raise errors.BzrCommandError("Target directory %s"
735
" already exists, but does not have a valid .bzr"
736
" directory. Supply --use-existing-dir to push"
737
" there anyway." % location)
738
except errors.NoSuchFile:
739
if not create_prefix:
740
raise errors.BzrCommandError("Parent directory of %s"
742
"\nYou may supply --create-prefix to create all"
743
" leading parent directories."
746
_create_prefix(to_transport)
748
# Now the target directory exists, but doesn't have a .bzr
749
# directory. So we need to create it, along with any work to create
750
# all of the dependent branches, etc.
751
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
752
revision_id=br_from.last_revision())
753
br_to = dir_to.open_branch()
754
# TODO: Some more useful message about what was copied
755
note('Created new branch.')
756
# We successfully created the target, remember it
757
if br_from.get_push_location() is None or remember:
758
br_from.set_push_location(br_to.base)
759
elif repository_to is None:
760
# we have a bzrdir but no branch or repository
761
# XXX: Figure out what to do other than complain.
762
raise errors.BzrCommandError("At %s you have a valid .bzr control"
763
" directory, but not a branch or repository. This is an"
764
" unsupported configuration. Please move the target directory"
765
" out of the way and try again."
768
# We have a repository but no branch, copy the revisions, and then
770
last_revision_id = br_from.last_revision()
771
repository_to.fetch(br_from.repository,
772
revision_id=last_revision_id)
773
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
774
note('Created new branch.')
775
if br_from.get_push_location() is None or remember:
776
br_from.set_push_location(br_to.base)
777
else: # We have a valid to branch
778
# We were able to connect to the remote location, so remember it
779
# we don't need to successfully push because of possible divergence.
780
if br_from.get_push_location() is None or remember:
781
br_from.set_push_location(br_to.base)
782
old_rh = br_to.revision_history()
785
tree_to = dir_to.open_workingtree()
786
except errors.NotLocalUrl:
787
warning("This transport does not update the working "
788
"tree of: %s. See 'bzr help working-trees' for "
789
"more information." % br_to.base)
790
push_result = br_from.push(br_to, overwrite)
791
except errors.NoWorkingTree:
792
push_result = br_from.push(br_to, overwrite)
796
push_result = br_from.push(tree_to.branch, overwrite)
800
except errors.DivergedBranches:
801
raise errors.BzrCommandError('These branches have diverged.'
802
' Try using "merge" and then "push".')
803
if push_result is not None:
804
push_result.report(self.outf)
806
new_rh = br_to.revision_history()
809
from bzrlib.log import show_changed_revisions
810
show_changed_revisions(br_to, old_rh, new_rh,
813
# we probably did a clone rather than a push, so a message was
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']
835
aliases = ['get', 'clone']
837
def run(self, from_location, to_location=None, revision=None):
838
from bzrlib.tag import _merge_tags_if_possible
841
elif len(revision) > 1:
842
raise errors.BzrCommandError(
843
'bzr branch --revision takes exactly 1 revision value')
845
br_from = Branch.open(from_location)
848
if len(revision) == 1 and revision[0] is not None:
849
revision_id = revision[0].in_history(br_from)[1]
851
# FIXME - wt.last_revision, fallback to branch, fall back to
852
# None or perhaps NULL_REVISION to mean copy nothing
854
revision_id = br_from.last_revision()
855
if to_location is None:
856
to_location = urlutils.derive_to_location(from_location)
859
name = os.path.basename(to_location) + '\n'
861
to_transport = transport.get_transport(to_location)
863
to_transport.mkdir('.')
864
except errors.FileExists:
865
raise errors.BzrCommandError('Target directory "%s" already'
866
' exists.' % to_location)
867
except errors.NoSuchFile:
868
raise errors.BzrCommandError('Parent of "%s" does not exist.'
871
# preserve whatever source format we have.
872
dir = br_from.bzrdir.sprout(to_transport.base, revision_id)
873
branch = dir.open_branch()
874
except errors.NoSuchRevision:
875
to_transport.delete_tree('.')
876
msg = "The branch %s has no revision %s." % (from_location, revision[0])
877
raise errors.BzrCommandError(msg)
879
branch.control_files.put_utf8('branch-name', name)
880
_merge_tags_if_possible(br_from, branch)
881
note('Branched %d revision(s).' % branch.revno())
886
class cmd_checkout(Command):
887
"""Create a new checkout of an existing branch.
889
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
890
the branch found in '.'. This is useful if you have removed the working tree
891
or if it was never created - i.e. if you pushed the branch to its current
894
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
895
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
896
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
897
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
898
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
901
To retrieve the branch as of a particular revision, supply the --revision
902
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
903
out of date [so you cannot commit] but it may be useful (i.e. to examine old
907
_see_also = ['checkouts', 'branch']
908
takes_args = ['branch_location?', 'to_location?']
909
takes_options = ['revision',
910
Option('lightweight',
911
help="perform a lightweight checkout. Lightweight "
912
"checkouts depend on access to the branch for "
913
"every operation. Normal checkouts can perform "
914
"common operations like diff and status without "
915
"such access, and also support local commits."
920
def run(self, branch_location=None, to_location=None, revision=None,
924
elif len(revision) > 1:
925
raise errors.BzrCommandError(
926
'bzr checkout --revision takes exactly 1 revision value')
927
if branch_location is None:
928
branch_location = osutils.getcwd()
929
to_location = branch_location
930
source = Branch.open(branch_location)
931
if len(revision) == 1 and revision[0] is not None:
932
revision_id = revision[0].in_history(source)[1]
935
if to_location is None:
936
to_location = urlutils.derive_to_location(branch_location)
937
# if the source and to_location are the same,
938
# and there is no working tree,
939
# then reconstitute a branch
940
if (osutils.abspath(to_location) ==
941
osutils.abspath(branch_location)):
943
source.bzrdir.open_workingtree()
944
except errors.NoWorkingTree:
945
source.bzrdir.create_workingtree()
948
os.mkdir(to_location)
950
if e.errno == errno.EEXIST:
951
raise errors.BzrCommandError('Target directory "%s" already'
952
' exists.' % to_location)
953
if e.errno == errno.ENOENT:
954
raise errors.BzrCommandError('Parent of "%s" does not exist.'
958
source.create_checkout(to_location, revision_id, lightweight)
961
class cmd_renames(Command):
962
"""Show list of renamed files.
964
# TODO: Option to show renames between two historical versions.
966
# TODO: Only show renames under dir, rather than in the whole branch.
967
_see_also = ['status']
968
takes_args = ['dir?']
971
def run(self, dir=u'.'):
972
tree = WorkingTree.open_containing(dir)[0]
975
new_inv = tree.inventory
976
old_tree = tree.basis_tree()
979
old_inv = old_tree.inventory
980
renames = list(_mod_tree.find_renames(old_inv, new_inv))
982
for old_name, new_name in renames:
983
self.outf.write("%s => %s\n" % (old_name, new_name))
990
class cmd_update(Command):
991
"""Update a tree to have the latest code committed to its branch.
993
This will perform a merge into the working tree, and may generate
994
conflicts. If you have any local changes, you will still
995
need to commit them after the update for the update to be complete.
997
If you want to discard your local changes, you can just do a
998
'bzr revert' instead of 'bzr commit' after the update.
1001
_see_also = ['pull', 'working-trees']
1002
takes_args = ['dir?']
1005
def run(self, dir='.'):
1006
tree = WorkingTree.open_containing(dir)[0]
1007
master = tree.branch.get_master_branch()
1008
if master is not None:
1011
tree.lock_tree_write()
1013
existing_pending_merges = tree.get_parent_ids()[1:]
1014
last_rev = tree.last_revision()
1015
if last_rev == tree.branch.last_revision():
1016
# may be up to date, check master too.
1017
master = tree.branch.get_master_branch()
1018
if master is None or last_rev == master.last_revision():
1019
revno = tree.branch.revision_id_to_revno(last_rev)
1020
note("Tree is up to date at revision %d." % (revno,))
1022
conflicts = tree.update(delta._ChangeReporter(
1023
unversioned_filter=tree.is_ignored))
1024
revno = tree.branch.revision_id_to_revno(tree.last_revision())
1025
note('Updated to revision %d.' % (revno,))
1026
if tree.get_parent_ids()[1:] != existing_pending_merges:
1027
note('Your local commits will now show as pending merges with '
1028
"'bzr status', and can be committed with 'bzr commit'.")
1037
class cmd_info(Command):
1038
"""Show information about a working tree, branch or repository.
1040
This command will show all known locations and formats associated to the
1041
tree, branch or repository. Statistical information is included with
1044
Branches and working trees will also report any missing revisions.
1046
_see_also = ['revno', 'working-trees', 'repositories']
1047
takes_args = ['location?']
1048
takes_options = ['verbose']
1051
def run(self, location=None, verbose=0):
1052
from bzrlib.info import show_bzrdir_info
1053
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1057
class cmd_remove(Command):
1058
"""Remove files or directories.
1060
This makes bzr stop tracking changes to the specified files and
1061
delete them if they can easily be recovered using revert.
1063
You can specify one or more files, and/or --new. If you specify --new,
1064
only 'added' files will be removed. If you specify both, then new files
1065
in the specified directories will be removed. If the directories are
1066
also new, they will also be removed.
1068
takes_args = ['file*']
1069
takes_options = ['verbose',
1070
Option('new', help='remove newly-added files'),
1071
RegistryOption.from_kwargs('file-deletion-strategy',
1072
'The file deletion mode to be used',
1073
title='Deletion Strategy', value_switches=True, enum_switch=False,
1074
safe='Only delete files if they can be'
1075
' safely recovered (default).',
1076
keep="Don't delete any files.",
1077
force='Delete all the specified files, even if they can not be '
1078
'recovered and even if they are non-empty directories.')]
1080
encoding_type = 'replace'
1082
def run(self, file_list, verbose=False, new=False,
1083
file_deletion_strategy='safe'):
1084
tree, file_list = tree_files(file_list)
1086
if file_list is not None:
1087
file_list = [f for f in file_list if f != '']
1089
raise errors.BzrCommandError('Specify one or more files to'
1090
' remove, or use --new.')
1093
added = tree.changes_from(tree.basis_tree(),
1094
specific_files=file_list).added
1095
file_list = sorted([f[0] for f in added], reverse=True)
1096
if len(file_list) == 0:
1097
raise errors.BzrCommandError('No matching files.')
1098
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1099
keep_files=file_deletion_strategy=='keep',
1100
force=file_deletion_strategy=='force')
1103
class cmd_file_id(Command):
1104
"""Print file_id of a particular file or directory.
1106
The file_id is assigned when the file is first added and remains the
1107
same through all revisions where the file exists, even when it is
1112
_see_also = ['inventory', 'ls']
1113
takes_args = ['filename']
1116
def run(self, filename):
1117
tree, relpath = WorkingTree.open_containing(filename)
1118
i = tree.path2id(relpath)
1120
raise errors.NotVersionedError(filename)
1122
self.outf.write(i + '\n')
1125
class cmd_file_path(Command):
1126
"""Print path of file_ids to a file or directory.
1128
This prints one line for each directory down to the target,
1129
starting at the branch root.
1133
takes_args = ['filename']
1136
def run(self, filename):
1137
tree, relpath = WorkingTree.open_containing(filename)
1138
fid = tree.path2id(relpath)
1140
raise errors.NotVersionedError(filename)
1141
segments = osutils.splitpath(relpath)
1142
for pos in range(1, len(segments) + 1):
1143
path = osutils.joinpath(segments[:pos])
1144
self.outf.write("%s\n" % tree.path2id(path))
1147
class cmd_reconcile(Command):
1148
"""Reconcile bzr metadata in a branch.
1150
This can correct data mismatches that may have been caused by
1151
previous ghost operations or bzr upgrades. You should only
1152
need to run this command if 'bzr check' or a bzr developer
1153
advises you to run it.
1155
If a second branch is provided, cross-branch reconciliation is
1156
also attempted, which will check that data like the tree root
1157
id which was not present in very early bzr versions is represented
1158
correctly in both branches.
1160
At the same time it is run it may recompress data resulting in
1161
a potential saving in disk space or performance gain.
1163
The branch *MUST* be on a listable system such as local disk or sftp.
1166
_see_also = ['check']
1167
takes_args = ['branch?']
1169
def run(self, branch="."):
1170
from bzrlib.reconcile import reconcile
1171
dir = bzrdir.BzrDir.open(branch)
1175
class cmd_revision_history(Command):
1176
"""Display the list of revision ids on a branch."""
1179
takes_args = ['location?']
1184
def run(self, location="."):
1185
branch = Branch.open_containing(location)[0]
1186
for revid in branch.revision_history():
1187
self.outf.write(revid)
1188
self.outf.write('\n')
1191
class cmd_ancestry(Command):
1192
"""List all revisions merged into this branch."""
1194
_see_also = ['log', 'revision-history']
1195
takes_args = ['location?']
1200
def run(self, location="."):
1202
wt = WorkingTree.open_containing(location)[0]
1203
except errors.NoWorkingTree:
1204
b = Branch.open(location)
1205
last_revision = b.last_revision()
1208
last_revision = wt.last_revision()
1210
revision_ids = b.repository.get_ancestry(last_revision)
1211
assert revision_ids[0] is None
1213
for revision_id in revision_ids:
1214
self.outf.write(revision_id + '\n')
1217
class cmd_init(Command):
1218
"""Make a directory into a versioned branch.
1220
Use this to create an empty branch, or before importing an
1223
If there is a repository in a parent directory of the location, then
1224
the history of the branch will be stored in the repository. Otherwise
1225
init creates a standalone branch which carries its own history
1226
in the .bzr directory.
1228
If there is already a branch at the location but it has no working tree,
1229
the tree can be populated with 'bzr checkout'.
1231
Recipe for importing a tree of files:
1236
bzr commit -m 'imported project'
1239
_see_also = ['init-repo', 'branch', 'checkout']
1240
takes_args = ['location?']
1242
Option('create-prefix',
1243
help='Create the path leading up to the branch '
1244
'if it does not already exist'),
1245
RegistryOption('format',
1246
help='Specify a format for this branch. '
1247
'See "help formats".',
1248
registry=bzrdir.format_registry,
1249
converter=bzrdir.format_registry.make_bzrdir,
1250
value_switches=True,
1251
title="Branch Format",
1253
Option('append-revisions-only',
1254
help='Never change revnos or the existing log.'
1255
' Append revisions to it only.')
1257
def run(self, location=None, format=None, append_revisions_only=False,
1258
create_prefix=False):
1260
format = bzrdir.format_registry.make_bzrdir('default')
1261
if location is None:
1264
to_transport = transport.get_transport(location)
1266
# The path has to exist to initialize a
1267
# branch inside of it.
1268
# Just using os.mkdir, since I don't
1269
# believe that we want to create a bunch of
1270
# locations if the user supplies an extended path
1272
to_transport.ensure_base()
1273
except errors.NoSuchFile:
1274
if not create_prefix:
1275
raise errors.BzrCommandError("Parent directory of %s"
1277
"\nYou may supply --create-prefix to create all"
1278
" leading parent directories."
1280
_create_prefix(to_transport)
1283
existing_bzrdir = bzrdir.BzrDir.open(location)
1284
except errors.NotBranchError:
1285
# really a NotBzrDir error...
1286
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1289
from bzrlib.transport.local import LocalTransport
1290
if existing_bzrdir.has_branch():
1291
if (isinstance(to_transport, LocalTransport)
1292
and not existing_bzrdir.has_workingtree()):
1293
raise errors.BranchExistsWithoutWorkingTree(location)
1294
raise errors.AlreadyBranchError(location)
1296
branch = existing_bzrdir.create_branch()
1297
existing_bzrdir.create_workingtree()
1298
if append_revisions_only:
1300
branch.set_append_revisions_only(True)
1301
except errors.UpgradeRequired:
1302
raise errors.BzrCommandError('This branch format cannot be set'
1303
' to append-revisions-only. Try --experimental-branch6')
1306
class cmd_init_repository(Command):
1307
"""Create a shared repository to hold branches.
1309
New branches created under the repository directory will store their
1310
revisions in the repository, not in the branch directory.
1312
If the --no-trees option is used then the branches in the repository
1313
will not have working trees by default.
1316
bzr init-repo --no-trees repo
1318
bzr checkout --lightweight repo/trunk trunk-checkout
1322
See 'bzr help repositories' for more information.
1325
_see_also = ['init', 'branch', 'checkout']
1326
takes_args = ["location"]
1327
takes_options = [RegistryOption('format',
1328
help='Specify a format for this repository. See'
1329
' "bzr help formats" for details',
1330
registry=bzrdir.format_registry,
1331
converter=bzrdir.format_registry.make_bzrdir,
1332
value_switches=True, title='Repository format'),
1334
help='Branches in the repository will default to'
1335
' not having a working tree'),
1337
aliases = ["init-repo"]
1339
def run(self, location, format=None, no_trees=False):
1341
format = bzrdir.format_registry.make_bzrdir('default')
1343
if location is None:
1346
to_transport = transport.get_transport(location)
1347
to_transport.ensure_base()
1349
newdir = format.initialize_on_transport(to_transport)
1350
repo = newdir.create_repository(shared=True)
1351
repo.set_make_working_trees(not no_trees)
1354
class cmd_diff(Command):
1355
"""Show differences in the working tree or between revisions.
1357
If files are listed, only the changes in those files are listed.
1358
Otherwise, all changes for the tree are listed.
1360
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1361
produces patches suitable for "patch -p1".
1365
Shows the difference in the working tree versus the last commit
1367
Difference between the working tree and revision 1
1369
Difference between revision 2 and revision 1
1370
bzr diff --prefix old/:new/
1371
Same as 'bzr diff' but prefix paths with old/ and new/
1372
bzr diff bzr.mine bzr.dev
1373
Show the differences between the two working trees
1375
Show just the differences for 'foo.c'
1377
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1378
# or a graphical diff.
1380
# TODO: Python difflib is not exactly the same as unidiff; should
1381
# either fix it up or prefer to use an external diff.
1383
# TODO: Selected-file diff is inefficient and doesn't show you
1386
# TODO: This probably handles non-Unix newlines poorly.
1388
_see_also = ['status']
1389
takes_args = ['file*']
1390
takes_options = ['revision', 'diff-options',
1391
Option('prefix', type=str,
1393
help='Set prefixes to added to old and new filenames, as '
1394
'two values separated by a colon. (eg "old/:new/")'),
1396
aliases = ['di', 'dif']
1397
encoding_type = 'exact'
1400
def run(self, revision=None, file_list=None, diff_options=None,
1402
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1404
if (prefix is None) or (prefix == '0'):
1412
old_label, new_label = prefix.split(":")
1414
raise errors.BzrCommandError(
1415
'--prefix expects two values separated by a colon'
1416
' (eg "old/:new/")')
1418
if revision and len(revision) > 2:
1419
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1420
' one or two revision specifiers')
1423
tree1, file_list = internal_tree_files(file_list)
1427
except errors.FileInWrongBranch:
1428
if len(file_list) != 2:
1429
raise errors.BzrCommandError("Files are in different branches")
1431
tree1, file1 = WorkingTree.open_containing(file_list[0])
1432
tree2, file2 = WorkingTree.open_containing(file_list[1])
1433
if file1 != "" or file2 != "":
1434
# FIXME diff those two files. rbc 20051123
1435
raise errors.BzrCommandError("Files are in different branches")
1437
except errors.NotBranchError:
1438
if (revision is not None and len(revision) == 2
1439
and not revision[0].needs_branch()
1440
and not revision[1].needs_branch()):
1441
# If both revision specs include a branch, we can
1442
# diff them without needing a local working tree
1443
tree1, tree2 = None, None
1447
if tree2 is not None:
1448
if revision is not None:
1449
# FIXME: but there should be a clean way to diff between
1450
# non-default versions of two trees, it's not hard to do
1452
raise errors.BzrCommandError(
1453
"Sorry, diffing arbitrary revisions across branches "
1454
"is not implemented yet")
1455
return show_diff_trees(tree1, tree2, sys.stdout,
1456
specific_files=file_list,
1457
external_diff_options=diff_options,
1458
old_label=old_label, new_label=new_label)
1460
return diff_cmd_helper(tree1, file_list, diff_options,
1461
revision_specs=revision,
1462
old_label=old_label, new_label=new_label)
1465
class cmd_deleted(Command):
1466
"""List files deleted in the working tree.
1468
# TODO: Show files deleted since a previous revision, or
1469
# between two revisions.
1470
# TODO: Much more efficient way to do this: read in new
1471
# directories with readdir, rather than stating each one. Same
1472
# level of effort but possibly much less IO. (Or possibly not,
1473
# if the directories are very large...)
1474
_see_also = ['status', 'ls']
1475
takes_options = ['show-ids']
1478
def run(self, show_ids=False):
1479
tree = WorkingTree.open_containing(u'.')[0]
1482
old = tree.basis_tree()
1485
for path, ie in old.inventory.iter_entries():
1486
if not tree.has_id(ie.file_id):
1487
self.outf.write(path)
1489
self.outf.write(' ')
1490
self.outf.write(ie.file_id)
1491
self.outf.write('\n')
1498
class cmd_modified(Command):
1499
"""List files modified in working tree.
1503
_see_also = ['status', 'ls']
1507
tree = WorkingTree.open_containing(u'.')[0]
1508
td = tree.changes_from(tree.basis_tree())
1509
for path, id, kind, text_modified, meta_modified in td.modified:
1510
self.outf.write(path + '\n')
1513
class cmd_added(Command):
1514
"""List files added in working tree.
1518
_see_also = ['status', 'ls']
1522
wt = WorkingTree.open_containing(u'.')[0]
1525
basis = wt.basis_tree()
1528
basis_inv = basis.inventory
1531
if file_id in basis_inv:
1533
if inv.is_root(file_id) and len(basis_inv) == 0:
1535
path = inv.id2path(file_id)
1536
if not os.access(osutils.abspath(path), os.F_OK):
1538
self.outf.write(path + '\n')
1545
class cmd_root(Command):
1546
"""Show the tree root directory.
1548
The root is the nearest enclosing directory with a .bzr control
1551
takes_args = ['filename?']
1553
def run(self, filename=None):
1554
"""Print the branch root."""
1555
tree = WorkingTree.open_containing(filename)[0]
1556
self.outf.write(tree.basedir + '\n')
1559
def _parse_limit(limitstring):
1561
return int(limitstring)
1563
msg = "The limit argument must be an integer."
1564
raise errors.BzrCommandError(msg)
1567
class cmd_log(Command):
1568
"""Show log of a branch, file, or directory.
1570
By default show the log of the branch containing the working directory.
1572
To request a range of logs, you can use the command -r begin..end
1573
-r revision requests a specific revision, -r ..end or -r begin.. are
1579
bzr log -r -10.. http://server/branch
1582
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1584
takes_args = ['location?']
1585
takes_options = [Option('forward',
1586
help='show from oldest to newest'),
1590
help='show files changed in each revision'),
1591
'show-ids', 'revision',
1595
help='show revisions whose message matches this regexp',
1598
help='limit the output to the first N revisions',
1601
encoding_type = 'replace'
1604
def run(self, location=None, timezone='original',
1612
from bzrlib.log import show_log
1613
assert message is None or isinstance(message, basestring), \
1614
"invalid message argument %r" % message
1615
direction = (forward and 'forward') or 'reverse'
1620
# find the file id to log:
1622
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1626
tree = b.basis_tree()
1627
file_id = tree.path2id(fp)
1629
raise errors.BzrCommandError(
1630
"Path does not have any revision history: %s" %
1634
# FIXME ? log the current subdir only RBC 20060203
1635
if revision is not None \
1636
and len(revision) > 0 and revision[0].get_branch():
1637
location = revision[0].get_branch()
1640
dir, relpath = bzrdir.BzrDir.open_containing(location)
1641
b = dir.open_branch()
1645
if revision is None:
1648
elif len(revision) == 1:
1649
rev1 = rev2 = revision[0].in_history(b)
1650
elif len(revision) == 2:
1651
if revision[1].get_branch() != revision[0].get_branch():
1652
# b is taken from revision[0].get_branch(), and
1653
# show_log will use its revision_history. Having
1654
# different branches will lead to weird behaviors.
1655
raise errors.BzrCommandError(
1656
"Log doesn't accept two revisions in different"
1658
rev1 = revision[0].in_history(b)
1659
rev2 = revision[1].in_history(b)
1661
raise errors.BzrCommandError(
1662
'bzr log --revision takes one or two values.')
1664
if log_format is None:
1665
log_format = log.log_formatter_registry.get_default(b)
1667
lf = log_format(show_ids=show_ids, to_file=self.outf,
1668
show_timezone=timezone)
1674
direction=direction,
1675
start_revision=rev1,
1683
def get_log_format(long=False, short=False, line=False, default='long'):
1684
log_format = default
1688
log_format = 'short'
1694
class cmd_touching_revisions(Command):
1695
"""Return revision-ids which affected a particular file.
1697
A more user-friendly interface is "bzr log FILE".
1701
takes_args = ["filename"]
1704
def run(self, filename):
1705
tree, relpath = WorkingTree.open_containing(filename)
1707
file_id = tree.path2id(relpath)
1708
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1709
self.outf.write("%6d %s\n" % (revno, what))
1712
class cmd_ls(Command):
1713
"""List files in a tree.
1716
_see_also = ['status', 'cat']
1717
takes_args = ['path?']
1718
# TODO: Take a revision or remote path and list that tree instead.
1719
takes_options = ['verbose', 'revision',
1720
Option('non-recursive',
1721
help='don\'t recurse into sub-directories'),
1723
help='Print all paths from the root of the branch.'),
1724
Option('unknown', help='Print unknown files'),
1725
Option('versioned', help='Print versioned files'),
1726
Option('ignored', help='Print ignored files'),
1728
Option('null', help='Null separate the files'),
1732
def run(self, revision=None, verbose=False,
1733
non_recursive=False, from_root=False,
1734
unknown=False, versioned=False, ignored=False,
1735
null=False, kind=None, show_ids=False, path=None):
1737
if kind and kind not in ('file', 'directory', 'symlink'):
1738
raise errors.BzrCommandError('invalid kind specified')
1740
if verbose and null:
1741
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1742
all = not (unknown or versioned or ignored)
1744
selection = {'I':ignored, '?':unknown, 'V':versioned}
1751
raise errors.BzrCommandError('cannot specify both --from-root'
1755
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1761
if revision is not None:
1762
tree = branch.repository.revision_tree(
1763
revision[0].in_history(branch).rev_id)
1765
tree = branch.basis_tree()
1769
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1770
if fp.startswith(relpath):
1771
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1772
if non_recursive and '/' in fp:
1774
if not all and not selection[fc]:
1776
if kind is not None and fkind != kind:
1779
kindch = entry.kind_character()
1780
outstring = '%-8s %s%s' % (fc, fp, kindch)
1781
if show_ids and fid is not None:
1782
outstring = "%-50s %s" % (outstring, fid)
1783
self.outf.write(outstring + '\n')
1785
self.outf.write(fp + '\0')
1788
self.outf.write(fid)
1789
self.outf.write('\0')
1797
self.outf.write('%-50s %s\n' % (fp, my_id))
1799
self.outf.write(fp + '\n')
1804
class cmd_unknowns(Command):
1805
"""List unknown files.
1813
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1814
self.outf.write(osutils.quotefn(f) + '\n')
1817
class cmd_ignore(Command):
1818
"""Ignore specified files or patterns.
1820
To remove patterns from the ignore list, edit the .bzrignore file.
1822
Trailing slashes on patterns are ignored.
1823
If the pattern contains a slash or is a regular expression, it is compared
1824
to the whole path from the branch root. Otherwise, it is compared to only
1825
the last component of the path. To match a file only in the root
1826
directory, prepend './'.
1828
Ignore patterns specifying absolute paths are not allowed.
1830
Ignore patterns may include globbing wildcards such as:
1831
? - Matches any single character except '/'
1832
* - Matches 0 or more characters except '/'
1833
/**/ - Matches 0 or more directories in a path
1834
[a-z] - Matches a single character from within a group of characters
1836
Ignore patterns may also be Python regular expressions.
1837
Regular expression ignore patterns are identified by a 'RE:' prefix
1838
followed by the regular expression. Regular expression ignore patterns
1839
may not include named or numbered groups.
1841
Note: ignore patterns containing shell wildcards must be quoted from
1845
bzr ignore ./Makefile
1846
bzr ignore '*.class'
1847
bzr ignore 'lib/**/*.o'
1848
bzr ignore 'RE:lib/.*\.o'
1851
_see_also = ['status', 'ignored']
1852
takes_args = ['name_pattern*']
1854
Option('old-default-rules',
1855
help='Out the ignore rules bzr < 0.9 always used.')
1858
def run(self, name_pattern_list=None, old_default_rules=None):
1859
from bzrlib.atomicfile import AtomicFile
1860
if old_default_rules is not None:
1861
# dump the rules and exit
1862
for pattern in ignores.OLD_DEFAULTS:
1865
if not name_pattern_list:
1866
raise errors.BzrCommandError("ignore requires at least one "
1867
"NAME_PATTERN or --old-default-rules")
1868
name_pattern_list = [globbing.normalize_pattern(p)
1869
for p in name_pattern_list]
1870
for name_pattern in name_pattern_list:
1871
if (name_pattern[0] == '/' or
1872
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1873
raise errors.BzrCommandError(
1874
"NAME_PATTERN should not be an absolute path")
1875
tree, relpath = WorkingTree.open_containing(u'.')
1876
ifn = tree.abspath('.bzrignore')
1877
if os.path.exists(ifn):
1880
igns = f.read().decode('utf-8')
1886
# TODO: If the file already uses crlf-style termination, maybe
1887
# we should use that for the newly added lines?
1889
if igns and igns[-1] != '\n':
1891
for name_pattern in name_pattern_list:
1892
igns += name_pattern + '\n'
1894
f = AtomicFile(ifn, 'wb')
1896
f.write(igns.encode('utf-8'))
1901
if not tree.path2id('.bzrignore'):
1902
tree.add(['.bzrignore'])
1905
class cmd_ignored(Command):
1906
"""List ignored files and the patterns that matched them.
1909
_see_also = ['ignore']
1912
tree = WorkingTree.open_containing(u'.')[0]
1915
for path, file_class, kind, file_id, entry in tree.list_files():
1916
if file_class != 'I':
1918
## XXX: Slightly inefficient since this was already calculated
1919
pat = tree.is_ignored(path)
1920
print '%-50s %s' % (path, pat)
1925
class cmd_lookup_revision(Command):
1926
"""Lookup the revision-id from a revision-number
1929
bzr lookup-revision 33
1932
takes_args = ['revno']
1935
def run(self, revno):
1939
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1941
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1944
class cmd_export(Command):
1945
"""Export current or past revision to a destination directory or archive.
1947
If no revision is specified this exports the last committed revision.
1949
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1950
given, try to find the format with the extension. If no extension
1951
is found exports to a directory (equivalent to --format=dir).
1953
If root is supplied, it will be used as the root directory inside
1954
container formats (tar, zip, etc). If it is not supplied it will default
1955
to the exported filename. The root option has no effect for 'dir' format.
1957
If branch is omitted then the branch containing the current working
1958
directory will be used.
1960
Note: Export of tree with non-ASCII filenames to zip is not supported.
1962
Supported formats Autodetected by extension
1963
----------------- -------------------------
1966
tbz2 .tar.bz2, .tbz2
1970
takes_args = ['dest', 'branch?']
1971
takes_options = ['revision', 'format', 'root']
1972
def run(self, dest, branch=None, revision=None, format=None, root=None):
1973
from bzrlib.export import export
1976
tree = WorkingTree.open_containing(u'.')[0]
1979
b = Branch.open(branch)
1981
if revision is None:
1982
# should be tree.last_revision FIXME
1983
rev_id = b.last_revision()
1985
if len(revision) != 1:
1986
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1987
rev_id = revision[0].in_history(b).rev_id
1988
t = b.repository.revision_tree(rev_id)
1990
export(t, dest, format, root)
1991
except errors.NoSuchExportFormat, e:
1992
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1995
class cmd_cat(Command):
1996
"""Write the contents of a file as of a given revision to standard output.
1998
If no revision is nominated, the last revision is used.
2000
Note: Take care to redirect standard output when using this command on a
2005
takes_options = ['revision', 'name-from-revision']
2006
takes_args = ['filename']
2007
encoding_type = 'exact'
2010
def run(self, filename, revision=None, name_from_revision=False):
2011
if revision is not None and len(revision) != 1:
2012
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2017
tree, b, relpath = \
2018
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2019
except errors.NotBranchError:
2022
if revision is not None and revision[0].get_branch() is not None:
2023
b = Branch.open(revision[0].get_branch())
2025
tree = b.basis_tree()
2026
if revision is None:
2027
revision_id = b.last_revision()
2029
revision_id = revision[0].in_history(b).rev_id
2031
cur_file_id = tree.path2id(relpath)
2032
rev_tree = b.repository.revision_tree(revision_id)
2033
old_file_id = rev_tree.path2id(relpath)
2035
if name_from_revision:
2036
if old_file_id is None:
2037
raise errors.BzrCommandError("%r is not present in revision %s"
2038
% (filename, revision_id))
2040
rev_tree.print_file(old_file_id)
2041
elif cur_file_id is not None:
2042
rev_tree.print_file(cur_file_id)
2043
elif old_file_id is not None:
2044
rev_tree.print_file(old_file_id)
2046
raise errors.BzrCommandError("%r is not present in revision %s" %
2047
(filename, revision_id))
2050
class cmd_local_time_offset(Command):
2051
"""Show the offset in seconds from GMT to local time."""
2055
print osutils.local_time_offset()
2059
class cmd_commit(Command):
2060
"""Commit changes into a new revision.
2062
If no arguments are given, the entire tree is committed.
2064
If selected files are specified, only changes to those files are
2065
committed. If a directory is specified then the directory and everything
2066
within it is committed.
2068
A selected-file commit may fail in some cases where the committed
2069
tree would be invalid. Consider::
2074
bzr commit foo -m "committing foo"
2075
bzr mv foo/bar foo/baz
2078
bzr commit foo/bar -m "committing bar but not baz"
2080
In the example above, the last commit will fail by design. This gives
2081
the user the opportunity to decide whether they want to commit the
2082
rename at the same time, separately first, or not at all. (As a general
2083
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2085
Note: A selected-file commit after a merge is not yet supported.
2087
# TODO: Run hooks on tree to-be-committed, and after commit.
2089
# TODO: Strict commit that fails if there are deleted files.
2090
# (what does "deleted files" mean ??)
2092
# TODO: Give better message for -s, --summary, used by tla people
2094
# XXX: verbose currently does nothing
2096
_see_also = ['bugs', 'uncommit']
2097
takes_args = ['selected*']
2098
takes_options = ['message', 'verbose',
2100
help='commit even if nothing has changed'),
2101
Option('file', type=str,
2104
help='file containing commit message'),
2106
help="refuse to commit if there are unknown "
2107
"files in the working tree."),
2108
ListOption('fixes', type=str,
2109
help="mark a bug as being fixed by this "
2112
help="perform a local only commit in a bound "
2113
"branch. Such commits are not pushed to "
2114
"the master branch until a normal commit "
2118
aliases = ['ci', 'checkin']
2120
def _get_bug_fix_properties(self, fixes, branch):
2122
# Configure the properties for bug fixing attributes.
2123
for fixed_bug in fixes:
2124
tokens = fixed_bug.split(':')
2125
if len(tokens) != 2:
2126
raise errors.BzrCommandError(
2127
"Invalid bug %s. Must be in the form of 'tag:id'. "
2128
"Commit refused." % fixed_bug)
2129
tag, bug_id = tokens
2131
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2132
except errors.UnknownBugTrackerAbbreviation:
2133
raise errors.BzrCommandError(
2134
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2135
except errors.MalformedBugIdentifier:
2136
raise errors.BzrCommandError(
2137
"Invalid bug identifier for %s. Commit refused."
2139
properties.append('%s fixed' % bug_url)
2140
return '\n'.join(properties)
2142
def run(self, message=None, file=None, verbose=True, selected_list=None,
2143
unchanged=False, strict=False, local=False, fixes=None):
2144
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2145
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2147
from bzrlib.msgeditor import edit_commit_message, \
2148
make_commit_message_template
2150
# TODO: Need a blackbox test for invoking the external editor; may be
2151
# slightly problematic to run this cross-platform.
2153
# TODO: do more checks that the commit will succeed before
2154
# spending the user's valuable time typing a commit message.
2158
tree, selected_list = tree_files(selected_list)
2159
if selected_list == ['']:
2160
# workaround - commit of root of tree should be exactly the same
2161
# as just default commit in that tree, and succeed even though
2162
# selected-file merge commit is not done yet
2165
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2167
properties['bugs'] = bug_property
2169
if local and not tree.branch.get_bound_location():
2170
raise errors.LocalRequiresBoundBranch()
2172
def get_message(commit_obj):
2173
"""Callback to get commit message"""
2174
my_message = message
2175
if my_message is None and not file:
2176
template = make_commit_message_template(tree, selected_list)
2177
my_message = edit_commit_message(template)
2178
if my_message is None:
2179
raise errors.BzrCommandError("please specify a commit"
2180
" message with either --message or --file")
2181
elif my_message and file:
2182
raise errors.BzrCommandError(
2183
"please specify either --message or --file")
2185
my_message = codecs.open(file, 'rt',
2186
bzrlib.user_encoding).read()
2187
if my_message == "":
2188
raise errors.BzrCommandError("empty commit message specified")
2192
reporter = ReportCommitToLog()
2194
reporter = NullCommitReporter()
2197
tree.commit(message_callback=get_message,
2198
specific_files=selected_list,
2199
allow_pointless=unchanged, strict=strict, local=local,
2200
reporter=reporter, revprops=properties)
2201
except PointlessCommit:
2202
# FIXME: This should really happen before the file is read in;
2203
# perhaps prepare the commit; get the message; then actually commit
2204
raise errors.BzrCommandError("no changes to commit."
2205
" use --unchanged to commit anyhow")
2206
except ConflictsInTree:
2207
raise errors.BzrCommandError('Conflicts detected in working '
2208
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2210
except StrictCommitFailed:
2211
raise errors.BzrCommandError("Commit refused because there are"
2212
" unknown files in the working tree.")
2213
except errors.BoundBranchOutOfDate, e:
2214
raise errors.BzrCommandError(str(e) + "\n"
2215
'To commit to master branch, run update and then commit.\n'
2216
'You can also pass --local to commit to continue working '
2220
class cmd_check(Command):
2221
"""Validate consistency of branch history.
2223
This command checks various invariants about the branch storage to
2224
detect data corruption or bzr bugs.
2227
_see_also = ['reconcile']
2228
takes_args = ['branch?']
2229
takes_options = ['verbose']
2231
def run(self, branch=None, verbose=False):
2232
from bzrlib.check import check
2234
tree = WorkingTree.open_containing()[0]
2235
branch = tree.branch
2237
branch = Branch.open(branch)
2238
check(branch, verbose)
2241
class cmd_upgrade(Command):
2242
"""Upgrade branch storage to current format.
2244
The check command or bzr developers may sometimes advise you to run
2245
this command. When the default format has changed you may also be warned
2246
during other operations to upgrade.
2249
_see_also = ['check']
2250
takes_args = ['url?']
2252
RegistryOption('format',
2253
help='Upgrade to a specific format. See "bzr help'
2254
' formats" for details',
2255
registry=bzrdir.format_registry,
2256
converter=bzrdir.format_registry.make_bzrdir,
2257
value_switches=True, title='Branch format'),
2260
def run(self, url='.', format=None):
2261
from bzrlib.upgrade import upgrade
2263
format = bzrdir.format_registry.make_bzrdir('default')
2264
upgrade(url, format)
2267
class cmd_whoami(Command):
2268
"""Show or set bzr user id.
2272
bzr whoami 'Frank Chu <fchu@example.com>'
2274
takes_options = [ Option('email',
2275
help='display email address only'),
2277
help='set identity for the current branch instead of '
2280
takes_args = ['name?']
2281
encoding_type = 'replace'
2284
def run(self, email=False, branch=False, name=None):
2286
# use branch if we're inside one; otherwise global config
2288
c = Branch.open_containing('.')[0].get_config()
2289
except errors.NotBranchError:
2290
c = config.GlobalConfig()
2292
self.outf.write(c.user_email() + '\n')
2294
self.outf.write(c.username() + '\n')
2297
# display a warning if an email address isn't included in the given name.
2299
config.extract_email_address(name)
2300
except errors.NoEmailInUsername, e:
2301
warning('"%s" does not seem to contain an email address. '
2302
'This is allowed, but not recommended.', name)
2304
# use global config unless --branch given
2306
c = Branch.open_containing('.')[0].get_config()
2308
c = config.GlobalConfig()
2309
c.set_user_option('email', name)
2312
class cmd_nick(Command):
2313
"""Print or set the branch nickname.
2315
If unset, the tree root directory name is used as the nickname
2316
To print the current nickname, execute with no argument.
2319
_see_also = ['info']
2320
takes_args = ['nickname?']
2321
def run(self, nickname=None):
2322
branch = Branch.open_containing(u'.')[0]
2323
if nickname is None:
2324
self.printme(branch)
2326
branch.nick = nickname
2329
def printme(self, branch):
2333
class cmd_selftest(Command):
2334
"""Run internal test suite.
2336
If arguments are given, they are regular expressions that say which tests
2337
should run. Tests matching any expression are run, and other tests are
2340
Alternatively if --first is given, matching tests are run first and then
2341
all other tests are run. This is useful if you have been working in a
2342
particular area, but want to make sure nothing else was broken.
2344
If --exclude is given, tests that match that regular expression are
2345
excluded, regardless of whether they match --first or not.
2347
To help catch accidential dependencies between tests, the --randomize
2348
option is useful. In most cases, the argument used is the word 'now'.
2349
Note that the seed used for the random number generator is displayed
2350
when this option is used. The seed can be explicitly passed as the
2351
argument to this option if required. This enables reproduction of the
2352
actual ordering used if and when an order sensitive problem is encountered.
2354
If --list-only is given, the tests that would be run are listed. This is
2355
useful when combined with --first, --exclude and/or --randomize to
2356
understand their impact. The test harness reports "Listed nn tests in ..."
2357
instead of "Ran nn tests in ..." when list mode is enabled.
2359
If the global option '--no-plugins' is given, plugins are not loaded
2360
before running the selftests. This has two effects: features provided or
2361
modified by plugins will not be tested, and tests provided by plugins will
2366
run only tests relating to 'ignore'
2367
bzr --no-plugins selftest -v
2368
disable plugins and list tests as they're run
2370
For each test, that needs actual disk access, bzr create their own
2371
subdirectory in the temporary testing directory (testXXXX.tmp).
2372
By default the name of such subdirectory is based on the name of the test.
2373
If option '--numbered-dirs' is given, bzr will use sequent numbers
2374
of running tests to create such subdirectories. This is default behavior
2375
on Windows because of path length limitation.
2377
# NB: this is used from the class without creating an instance, which is
2378
# why it does not have a self parameter.
2379
def get_transport_type(typestring):
2380
"""Parse and return a transport specifier."""
2381
if typestring == "sftp":
2382
from bzrlib.transport.sftp import SFTPAbsoluteServer
2383
return SFTPAbsoluteServer
2384
if typestring == "memory":
2385
from bzrlib.transport.memory import MemoryServer
2387
if typestring == "fakenfs":
2388
from bzrlib.transport.fakenfs import FakeNFSServer
2389
return FakeNFSServer
2390
msg = "No known transport type %s. Supported types are: sftp\n" %\
2392
raise errors.BzrCommandError(msg)
2395
takes_args = ['testspecs*']
2396
takes_options = ['verbose',
2398
help='stop when one test fails',
2401
Option('keep-output',
2402
help='keep output directories when tests fail'),
2404
help='Use a different transport by default '
2405
'throughout the test suite.',
2406
type=get_transport_type),
2407
Option('benchmark', help='run the bzr benchmarks.'),
2408
Option('lsprof-timed',
2409
help='generate lsprof output for benchmarked'
2410
' sections of code.'),
2411
Option('cache-dir', type=str,
2412
help='a directory to cache intermediate'
2413
' benchmark steps'),
2414
Option('clean-output',
2415
help='clean temporary tests directories'
2416
' without running tests'),
2418
help='run all tests, but run specified tests first',
2421
Option('numbered-dirs',
2422
help='use numbered dirs for TestCaseInTempDir'),
2424
help='list the tests instead of running them'),
2425
Option('randomize', type=str, argname="SEED",
2426
help='randomize the order of tests using the given'
2427
' seed or "now" for the current time'),
2428
Option('exclude', type=str, argname="PATTERN",
2430
help='exclude tests that match this regular'
2433
encoding_type = 'replace'
2435
def run(self, testspecs_list=None, verbose=None, one=False,
2436
keep_output=False, transport=None, benchmark=None,
2437
lsprof_timed=None, cache_dir=None, clean_output=False,
2438
first=False, numbered_dirs=None, list_only=False,
2439
randomize=None, exclude=None):
2441
from bzrlib.tests import selftest
2442
import bzrlib.benchmarks as benchmarks
2443
from bzrlib.benchmarks import tree_creator
2446
from bzrlib.tests import clean_selftest_output
2447
clean_selftest_output()
2450
warning("notice: selftest --keep-output "
2451
"is no longer supported; "
2452
"test output is always removed")
2454
if numbered_dirs is None and sys.platform == 'win32':
2455
numbered_dirs = True
2457
if cache_dir is not None:
2458
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2459
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2460
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2462
if testspecs_list is not None:
2463
pattern = '|'.join(testspecs_list)
2467
test_suite_factory = benchmarks.test_suite
2470
# TODO: should possibly lock the history file...
2471
benchfile = open(".perf_history", "at", buffering=1)
2473
test_suite_factory = None
2478
result = selftest(verbose=verbose,
2480
stop_on_failure=one,
2481
transport=transport,
2482
test_suite_factory=test_suite_factory,
2483
lsprof_timed=lsprof_timed,
2484
bench_history=benchfile,
2485
matching_tests_first=first,
2486
numbered_dirs=numbered_dirs,
2487
list_only=list_only,
2488
random_seed=randomize,
2489
exclude_pattern=exclude
2492
if benchfile is not None:
2495
info('tests passed')
2497
info('tests failed')
2498
return int(not result)
2501
class cmd_version(Command):
2502
"""Show version of bzr."""
2506
from bzrlib.version import show_version
2510
class cmd_rocks(Command):
2511
"""Statement of optimism."""
2517
print "It sure does!"
2520
class cmd_find_merge_base(Command):
2521
"""Find and print a base revision for merging two branches."""
2522
# TODO: Options to specify revisions on either side, as if
2523
# merging only part of the history.
2524
takes_args = ['branch', 'other']
2528
def run(self, branch, other):
2529
from bzrlib.revision import ensure_null, MultipleRevisionSources
2531
branch1 = Branch.open_containing(branch)[0]
2532
branch2 = Branch.open_containing(other)[0]
2534
last1 = ensure_null(branch1.last_revision())
2535
last2 = ensure_null(branch2.last_revision())
2537
graph = branch1.repository.get_graph(branch2.repository)
2538
base_rev_id = graph.find_unique_lca(last1, last2)
2540
print 'merge base is revision %s' % base_rev_id
2543
class cmd_merge(Command):
2544
"""Perform a three-way merge.
2546
The branch is the branch you will merge from. By default, it will merge
2547
the latest revision. If you specify a revision, that revision will be
2548
merged. If you specify two revisions, the first will be used as a BASE,
2549
and the second one as OTHER. Revision numbers are always relative to the
2552
By default, bzr will try to merge in all new work from the other
2553
branch, automatically determining an appropriate base. If this
2554
fails, you may need to give an explicit base.
2556
Merge will do its best to combine the changes in two branches, but there
2557
are some kinds of problems only a human can fix. When it encounters those,
2558
it will mark a conflict. A conflict means that you need to fix something,
2559
before you should commit.
2561
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2563
If there is no default branch set, the first merge will set it. After
2564
that, you can omit the branch to use the default. To change the
2565
default, use --remember. The value will only be saved if the remote
2566
location can be accessed.
2568
The results of the merge are placed into the destination working
2569
directory, where they can be reviewed (with bzr diff), tested, and then
2570
committed to record the result of the merge.
2574
To merge the latest revision from bzr.dev:
2575
bzr merge ../bzr.dev
2577
To merge changes up to and including revision 82 from bzr.dev:
2578
bzr merge -r 82 ../bzr.dev
2580
To merge the changes introduced by 82, without previous changes:
2581
bzr merge -r 81..82 ../bzr.dev
2583
merge refuses to run if there are any uncommitted changes, unless
2587
_see_also = ['update', 'remerge', 'status-flags']
2588
takes_args = ['branch?']
2589
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2590
Option('show-base', help="Show base revision text in "
2592
Option('uncommitted', help='Apply uncommitted changes'
2593
' from a working copy, instead of branch changes'),
2594
Option('pull', help='If the destination is already'
2595
' completely merged into the source, pull from the'
2596
' source rather than merging. When this happens,'
2597
' you do not need to commit the result.'),
2599
help='Branch to merge into, '
2600
'rather than the one containing the working directory',
2606
def run(self, branch=None, revision=None, force=False, merge_type=None,
2607
show_base=False, reprocess=False, remember=False,
2608
uncommitted=False, pull=False,
2611
from bzrlib.tag import _merge_tags_if_possible
2612
other_revision_id = None
2613
base_revision_id = None
2614
if merge_type is None:
2615
merge_type = _mod_merge.Merge3Merger
2617
if directory is None: directory = u'.'
2618
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2619
# inventory. Because merge is a mutating operation, it really
2620
# should be a lock_write() for the whole cmd_merge operation.
2621
# However, cmd_merge open's its own tree in _merge_helper, which
2622
# means if we lock here, the later lock_write() will always block.
2623
# Either the merge helper code should be updated to take a tree,
2624
# (What about tree.merge_from_branch?)
2625
tree = WorkingTree.open_containing(directory)[0]
2626
change_reporter = delta._ChangeReporter(
2627
unversioned_filter=tree.is_ignored)
2629
if branch is not None:
2631
mergeable = bundle.read_mergeable_from_url(
2633
except errors.NotABundle:
2634
pass # Continue on considering this url a Branch
2636
if revision is not None:
2637
raise errors.BzrCommandError(
2638
'Cannot use -r with merge directives or bundles')
2639
mergeable.install_revisions(tree.branch.repository)
2640
base_revision_id, other_revision_id, verified =\
2641
mergeable.get_merge_request(tree.branch.repository)
2642
if base_revision_id in tree.branch.repository.get_ancestry(
2643
tree.branch.last_revision(), topo_sorted=False):
2644
base_revision_id = None
2650
if other_revision_id is None:
2651
verified = 'inapplicable'
2652
if revision is None \
2653
or len(revision) < 1 or revision[0].needs_branch():
2654
branch = self._get_remembered_parent(tree, branch,
2657
if revision is None or len(revision) < 1:
2660
other = [branch, None]
2663
other = [branch, -1]
2664
other_branch, path = Branch.open_containing(branch)
2667
raise errors.BzrCommandError('Cannot use --uncommitted and'
2668
' --revision at the same time.')
2669
branch = revision[0].get_branch() or branch
2670
if len(revision) == 1:
2672
other_branch, path = Branch.open_containing(branch)
2673
revno = revision[0].in_history(other_branch).revno
2674
other = [branch, revno]
2676
assert len(revision) == 2
2677
if None in revision:
2678
raise errors.BzrCommandError(
2679
"Merge doesn't permit empty revision specifier.")
2680
base_branch, path = Branch.open_containing(branch)
2681
branch1 = revision[1].get_branch() or branch
2682
other_branch, path1 = Branch.open_containing(branch1)
2683
if revision[0].get_branch() is not None:
2684
# then path was obtained from it, and is None.
2687
base = [branch, revision[0].in_history(base_branch).revno]
2689
revision[1].in_history(other_branch).revno]
2691
if ((tree.branch.get_parent() is None or remember) and
2692
other_branch is not None):
2693
tree.branch.set_parent(other_branch.base)
2695
# pull tags now... it's a bit inconsistent to do it ahead of copying
2696
# the history but that's done inside the merge code
2697
if other_branch is not None:
2698
_merge_tags_if_possible(other_branch, tree.branch)
2701
interesting_files = [path]
2703
interesting_files = None
2704
pb = ui.ui_factory.nested_progress_bar()
2707
conflict_count = _merge_helper(
2708
other, base, other_rev_id=other_revision_id,
2709
base_rev_id=base_revision_id,
2710
check_clean=(not force),
2711
merge_type=merge_type,
2712
reprocess=reprocess,
2713
show_base=show_base,
2716
pb=pb, file_list=interesting_files,
2717
change_reporter=change_reporter)
2720
if verified == 'failed':
2721
warning('Preview patch does not match changes')
2722
if conflict_count != 0:
2726
except errors.AmbiguousBase, e:
2727
m = ("sorry, bzr can't determine the right merge base yet\n"
2728
"candidates are:\n "
2729
+ "\n ".join(e.bases)
2731
"please specify an explicit base with -r,\n"
2732
"and (if you want) report this to the bzr developers\n")
2735
# TODO: move up to common parent; this isn't merge-specific anymore.
2736
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2737
"""Use tree.branch's parent if none was supplied.
2739
Report if the remembered location was used.
2741
if supplied_location is not None:
2742
return supplied_location
2743
stored_location = tree.branch.get_parent()
2744
mutter("%s", stored_location)
2745
if stored_location is None:
2746
raise errors.BzrCommandError("No location specified or remembered")
2747
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2748
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2749
return stored_location
2752
class cmd_remerge(Command):
2755
Use this if you want to try a different merge technique while resolving
2756
conflicts. Some merge techniques are better than others, and remerge
2757
lets you try different ones on different files.
2759
The options for remerge have the same meaning and defaults as the ones for
2760
merge. The difference is that remerge can (only) be run when there is a
2761
pending merge, and it lets you specify particular files.
2765
$ bzr remerge --show-base
2766
Re-do the merge of all conflicted files, and show the base text in
2767
conflict regions, in addition to the usual THIS and OTHER texts.
2769
$ bzr remerge --merge-type weave --reprocess foobar
2770
Re-do the merge of "foobar", using the weave merge algorithm, with
2771
additional processing to reduce the size of conflict regions.
2773
takes_args = ['file*']
2774
takes_options = ['merge-type', 'reprocess',
2775
Option('show-base', help="Show base revision text in "
2778
def run(self, file_list=None, merge_type=None, show_base=False,
2780
if merge_type is None:
2781
merge_type = _mod_merge.Merge3Merger
2782
tree, file_list = tree_files(file_list)
2785
parents = tree.get_parent_ids()
2786
if len(parents) != 2:
2787
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2788
" merges. Not cherrypicking or"
2790
repository = tree.branch.repository
2791
graph = repository.get_graph()
2792
base_revision = graph.find_unique_lca(parents[0], parents[1])
2793
base_tree = repository.revision_tree(base_revision)
2794
other_tree = repository.revision_tree(parents[1])
2795
interesting_ids = None
2797
conflicts = tree.conflicts()
2798
if file_list is not None:
2799
interesting_ids = set()
2800
for filename in file_list:
2801
file_id = tree.path2id(filename)
2803
raise errors.NotVersionedError(filename)
2804
interesting_ids.add(file_id)
2805
if tree.kind(file_id) != "directory":
2808
for name, ie in tree.inventory.iter_entries(file_id):
2809
interesting_ids.add(ie.file_id)
2810
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2812
# Remerge only supports resolving contents conflicts
2813
allowed_conflicts = ('text conflict', 'contents conflict')
2814
restore_files = [c.path for c in conflicts
2815
if c.typestring in allowed_conflicts]
2816
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2817
tree.set_conflicts(ConflictList(new_conflicts))
2818
if file_list is not None:
2819
restore_files = file_list
2820
for filename in restore_files:
2822
restore(tree.abspath(filename))
2823
except errors.NotConflicted:
2825
conflicts = _mod_merge.merge_inner(
2826
tree.branch, other_tree, base_tree,
2828
interesting_ids=interesting_ids,
2829
other_rev_id=parents[1],
2830
merge_type=merge_type,
2831
show_base=show_base,
2832
reprocess=reprocess)
2841
class cmd_revert(Command):
2842
"""Revert files to a previous revision.
2844
Giving a list of files will revert only those files. Otherwise, all files
2845
will be reverted. If the revision is not specified with '--revision', the
2846
last committed revision is used.
2848
To remove only some changes, without reverting to a prior version, use
2849
merge instead. For example, "merge . --r-2..-3" will remove the changes
2850
introduced by -2, without affecting the changes introduced by -1. Or
2851
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2853
By default, any files that have been manually changed will be backed up
2854
first. (Files changed only by merge are not backed up.) Backup files have
2855
'.~#~' appended to their name, where # is a number.
2857
When you provide files, you can use their current pathname or the pathname
2858
from the target revision. So you can use revert to "undelete" a file by
2859
name. If you name a directory, all the contents of that directory will be
2863
_see_also = ['cat', 'export']
2864
takes_options = ['revision', 'no-backup']
2865
takes_args = ['file*']
2867
def run(self, revision=None, no_backup=False, file_list=None):
2868
if file_list is not None:
2869
if len(file_list) == 0:
2870
raise errors.BzrCommandError("No files specified")
2874
tree, file_list = tree_files(file_list)
2875
if revision is None:
2876
# FIXME should be tree.last_revision
2877
rev_id = tree.last_revision()
2878
elif len(revision) != 1:
2879
raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2881
rev_id = revision[0].in_history(tree.branch).rev_id
2882
pb = ui.ui_factory.nested_progress_bar()
2884
tree.revert(file_list,
2885
tree.branch.repository.revision_tree(rev_id),
2886
not no_backup, pb, report_changes=True)
2891
class cmd_assert_fail(Command):
2892
"""Test reporting of assertion failures"""
2893
# intended just for use in testing
2898
raise AssertionError("always fails")
2901
class cmd_help(Command):
2902
"""Show help on a command or other topic.
2905
_see_also = ['topics']
2906
takes_options = [Option('long', 'show help on all commands')]
2907
takes_args = ['topic?']
2908
aliases = ['?', '--help', '-?', '-h']
2911
def run(self, topic=None, long=False):
2913
if topic is None and long:
2915
bzrlib.help.help(topic)
2918
class cmd_shell_complete(Command):
2919
"""Show appropriate completions for context.
2921
For a list of all available commands, say 'bzr shell-complete'.
2923
takes_args = ['context?']
2928
def run(self, context=None):
2929
import shellcomplete
2930
shellcomplete.shellcomplete(context)
2933
class cmd_fetch(Command):
2934
"""Copy in history from another branch but don't merge it.
2936
This is an internal method used for pull and merge.
2939
takes_args = ['from_branch', 'to_branch']
2940
def run(self, from_branch, to_branch):
2941
from bzrlib.fetch import Fetcher
2942
from_b = Branch.open(from_branch)
2943
to_b = Branch.open(to_branch)
2944
Fetcher(to_b, from_b)
2947
class cmd_missing(Command):
2948
"""Show unmerged/unpulled revisions between two branches.
2950
OTHER_BRANCH may be local or remote.
2953
_see_also = ['merge', 'pull']
2954
takes_args = ['other_branch?']
2955
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2957
'Display changes in the local branch only'),
2958
Option('this' , 'same as --mine-only'),
2959
Option('theirs-only',
2960
'Display changes in the remote branch only'),
2961
Option('other', 'same as --theirs-only'),
2966
encoding_type = 'replace'
2969
def run(self, other_branch=None, reverse=False, mine_only=False,
2970
theirs_only=False, log_format=None, long=False, short=False, line=False,
2971
show_ids=False, verbose=False, this=False, other=False):
2972
from bzrlib.missing import find_unmerged, iter_log_revisions
2973
from bzrlib.log import log_formatter
2980
local_branch = Branch.open_containing(u".")[0]
2981
parent = local_branch.get_parent()
2982
if other_branch is None:
2983
other_branch = parent
2984
if other_branch is None:
2985
raise errors.BzrCommandError("No peer location known or specified.")
2986
display_url = urlutils.unescape_for_display(parent,
2988
print "Using last location: " + display_url
2990
remote_branch = Branch.open(other_branch)
2991
if remote_branch.base == local_branch.base:
2992
remote_branch = local_branch
2993
local_branch.lock_read()
2995
remote_branch.lock_read()
2997
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2998
if (log_format is None):
2999
log_format = log.log_formatter_registry.get_default(
3001
lf = log_format(to_file=self.outf,
3003
show_timezone='original')
3004
if reverse is False:
3005
local_extra.reverse()
3006
remote_extra.reverse()
3007
if local_extra and not theirs_only:
3008
print "You have %d extra revision(s):" % len(local_extra)
3009
for revision in iter_log_revisions(local_extra,
3010
local_branch.repository,
3012
lf.log_revision(revision)
3013
printed_local = True
3015
printed_local = False
3016
if remote_extra and not mine_only:
3017
if printed_local is True:
3019
print "You are missing %d revision(s):" % len(remote_extra)
3020
for revision in iter_log_revisions(remote_extra,
3021
remote_branch.repository,
3023
lf.log_revision(revision)
3024
if not remote_extra and not local_extra:
3026
print "Branches are up to date."
3030
remote_branch.unlock()
3032
local_branch.unlock()
3033
if not status_code and parent is None and other_branch is not None:
3034
local_branch.lock_write()
3036
# handle race conditions - a parent might be set while we run.
3037
if local_branch.get_parent() is None:
3038
local_branch.set_parent(remote_branch.base)
3040
local_branch.unlock()
3044
class cmd_plugins(Command):
3049
import bzrlib.plugin
3050
from inspect import getdoc
3051
for name, plugin in bzrlib.plugin.all_plugins().items():
3052
if getattr(plugin, '__path__', None) is not None:
3053
print plugin.__path__[0]
3054
elif getattr(plugin, '__file__', None) is not None:
3055
print plugin.__file__
3061
print '\t', d.split('\n')[0]
3064
class cmd_testament(Command):
3065
"""Show testament (signing-form) of a revision."""
3066
takes_options = ['revision',
3067
Option('long', help='Produce long-format testament'),
3068
Option('strict', help='Produce a strict-format'
3070
takes_args = ['branch?']
3072
def run(self, branch=u'.', revision=None, long=False, strict=False):
3073
from bzrlib.testament import Testament, StrictTestament
3075
testament_class = StrictTestament
3077
testament_class = Testament
3078
b = WorkingTree.open_containing(branch)[0].branch
3081
if revision is None:
3082
rev_id = b.last_revision()
3084
rev_id = revision[0].in_history(b).rev_id
3085
t = testament_class.from_revision(b.repository, rev_id)
3087
sys.stdout.writelines(t.as_text_lines())
3089
sys.stdout.write(t.as_short_text())
3094
class cmd_annotate(Command):
3095
"""Show the origin of each line in a file.
3097
This prints out the given file with an annotation on the left side
3098
indicating which revision, author and date introduced the change.
3100
If the origin is the same for a run of consecutive lines, it is
3101
shown only at the top, unless the --all option is given.
3103
# TODO: annotate directories; showing when each file was last changed
3104
# TODO: if the working copy is modified, show annotations on that
3105
# with new uncommitted lines marked
3106
aliases = ['ann', 'blame', 'praise']
3107
takes_args = ['filename']
3108
takes_options = [Option('all', help='show annotations on all lines'),
3109
Option('long', help='show date in annotations'),
3115
def run(self, filename, all=False, long=False, revision=None,
3117
from bzrlib.annotate import annotate_file
3118
tree, relpath = WorkingTree.open_containing(filename)
3119
branch = tree.branch
3122
if revision is None:
3123
revision_id = branch.last_revision()
3124
elif len(revision) != 1:
3125
raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3127
revision_id = revision[0].in_history(branch).rev_id
3128
file_id = tree.path2id(relpath)
3130
raise errors.NotVersionedError(filename)
3131
tree = branch.repository.revision_tree(revision_id)
3132
file_version = tree.inventory[file_id].revision
3133
annotate_file(branch, file_version, file_id, long, all, sys.stdout,
3139
class cmd_re_sign(Command):
3140
"""Create a digital signature for an existing revision."""
3141
# TODO be able to replace existing ones.
3143
hidden = True # is this right ?
3144
takes_args = ['revision_id*']
3145
takes_options = ['revision']
3147
def run(self, revision_id_list=None, revision=None):
3148
import bzrlib.gpg as gpg
3149
if revision_id_list is not None and revision is not None:
3150
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3151
if revision_id_list is None and revision is None:
3152
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3153
b = WorkingTree.open_containing(u'.')[0].branch
3154
gpg_strategy = gpg.GPGStrategy(b.get_config())
3155
if revision_id_list is not None:
3156
for revision_id in revision_id_list:
3157
b.repository.sign_revision(revision_id, gpg_strategy)
3158
elif revision is not None:
3159
if len(revision) == 1:
3160
revno, rev_id = revision[0].in_history(b)
3161
b.repository.sign_revision(rev_id, gpg_strategy)
3162
elif len(revision) == 2:
3163
# are they both on rh- if so we can walk between them
3164
# might be nice to have a range helper for arbitrary
3165
# revision paths. hmm.
3166
from_revno, from_revid = revision[0].in_history(b)
3167
to_revno, to_revid = revision[1].in_history(b)
3168
if to_revid is None:
3169
to_revno = b.revno()
3170
if from_revno is None or to_revno is None:
3171
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3172
for revno in range(from_revno, to_revno + 1):
3173
b.repository.sign_revision(b.get_rev_id(revno),
3176
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3179
class cmd_bind(Command):
3180
"""Convert the current branch into a checkout of the supplied branch.
3182
Once converted into a checkout, commits must succeed on the master branch
3183
before they will be applied to the local branch.
3186
_see_also = ['checkouts', 'unbind']
3187
takes_args = ['location?']
3190
def run(self, location=None):
3191
b, relpath = Branch.open_containing(u'.')
3192
if location is None:
3194
location = b.get_old_bound_location()
3195
except errors.UpgradeRequired:
3196
raise errors.BzrCommandError('No location supplied. '
3197
'This format does not remember old locations.')
3199
if location is None:
3200
raise errors.BzrCommandError('No location supplied and no '
3201
'previous location known')
3202
b_other = Branch.open(location)
3205
except errors.DivergedBranches:
3206
raise errors.BzrCommandError('These branches have diverged.'
3207
' Try merging, and then bind again.')
3210
class cmd_unbind(Command):
3211
"""Convert the current checkout into a regular branch.
3213
After unbinding, the local branch is considered independent and subsequent
3214
commits will be local only.
3217
_see_also = ['checkouts', 'bind']
3222
b, relpath = Branch.open_containing(u'.')
3224
raise errors.BzrCommandError('Local branch is not bound')
3227
class cmd_uncommit(Command):
3228
"""Remove the last committed revision.
3230
--verbose will print out what is being removed.
3231
--dry-run will go through all the motions, but not actually
3234
In the future, uncommit will create a revision bundle, which can then
3238
# TODO: jam 20060108 Add an option to allow uncommit to remove
3239
# unreferenced information in 'branch-as-repository' branches.
3240
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3241
# information in shared branches as well.
3242
_see_also = ['commit']
3243
takes_options = ['verbose', 'revision',
3244
Option('dry-run', help='Don\'t actually make changes'),
3245
Option('force', help='Say yes to all questions.')]
3246
takes_args = ['location?']
3249
def run(self, location=None,
3250
dry_run=False, verbose=False,
3251
revision=None, force=False):
3252
from bzrlib.log import log_formatter, show_log
3254
from bzrlib.uncommit import uncommit
3256
if location is None:
3258
control, relpath = bzrdir.BzrDir.open_containing(location)
3260
tree = control.open_workingtree()
3262
except (errors.NoWorkingTree, errors.NotLocalUrl):
3264
b = control.open_branch()
3267
if revision is None:
3270
# 'bzr uncommit -r 10' actually means uncommit
3271
# so that the final tree is at revno 10.
3272
# but bzrlib.uncommit.uncommit() actually uncommits
3273
# the revisions that are supplied.
3274
# So we need to offset it by one
3275
revno = revision[0].in_history(b).revno+1
3277
if revno <= b.revno():
3278
rev_id = b.get_rev_id(revno)
3280
self.outf.write('No revisions to uncommit.\n')
3283
lf = log_formatter('short',
3285
show_timezone='original')
3290
direction='forward',
3291
start_revision=revno,
3292
end_revision=b.revno())
3295
print 'Dry-run, pretending to remove the above revisions.'
3297
val = raw_input('Press <enter> to continue')
3299
print 'The above revision(s) will be removed.'
3301
val = raw_input('Are you sure [y/N]? ')
3302
if val.lower() not in ('y', 'yes'):
3306
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3310
class cmd_break_lock(Command):
3311
"""Break a dead lock on a repository, branch or working directory.
3313
CAUTION: Locks should only be broken when you are sure that the process
3314
holding the lock has been stopped.
3316
You can get information on what locks are open via the 'bzr info' command.
3321
takes_args = ['location?']
3323
def run(self, location=None, show=False):
3324
if location is None:
3326
control, relpath = bzrdir.BzrDir.open_containing(location)
3328
control.break_lock()
3329
except NotImplementedError:
3333
class cmd_wait_until_signalled(Command):
3334
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3336
This just prints a line to signal when it is ready, then blocks on stdin.
3342
sys.stdout.write("running\n")
3344
sys.stdin.readline()
3347
class cmd_serve(Command):
3348
"""Run the bzr server."""
3350
aliases = ['server']
3354
help='serve on stdin/out for use from inetd or sshd'),
3356
help='listen for connections on nominated port of the form '
3357
'[hostname:]portnumber. Passing 0 as the port number will '
3358
'result in a dynamically allocated port. Default port is '
3362
help='serve contents of directory',
3364
Option('allow-writes',
3365
help='By default the server is a readonly server. Supplying '
3366
'--allow-writes enables write access to the contents of '
3367
'the served directory and below. '
3371
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3372
from bzrlib.smart import medium, server
3373
from bzrlib.transport import get_transport
3374
from bzrlib.transport.chroot import ChrootServer
3375
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3376
if directory is None:
3377
directory = os.getcwd()
3378
url = urlutils.local_path_to_url(directory)
3379
if not allow_writes:
3380
url = 'readonly+' + url
3381
chroot_server = ChrootServer(get_transport(url))
3382
chroot_server.setUp()
3383
t = get_transport(chroot_server.get_url())
3385
smart_server = medium.SmartServerPipeStreamMedium(
3386
sys.stdin, sys.stdout, t)
3388
host = BZR_DEFAULT_INTERFACE
3390
port = BZR_DEFAULT_PORT
3393
host, port = port.split(':')
3395
smart_server = server.SmartTCPServer(t, host=host, port=port)
3396
print 'listening on port: ', smart_server.port
3398
# for the duration of this server, no UI output is permitted.
3399
# note that this may cause problems with blackbox tests. This should
3400
# be changed with care though, as we dont want to use bandwidth sending
3401
# progress over stderr to smart server clients!
3402
old_factory = ui.ui_factory
3404
ui.ui_factory = ui.SilentUIFactory()
3405
smart_server.serve()
3407
ui.ui_factory = old_factory
3410
class cmd_join(Command):
3411
"""Combine a subtree into its containing tree.
3413
This command is for experimental use only. It requires the target tree
3414
to be in dirstate-with-subtree format, which cannot be converted into
3417
The TREE argument should be an independent tree, inside another tree, but
3418
not part of it. (Such trees can be produced by "bzr split", but also by
3419
running "bzr branch" with the target inside a tree.)
3421
The result is a combined tree, with the subtree no longer an independant
3422
part. This is marked as a merge of the subtree into the containing tree,
3423
and all history is preserved.
3425
If --reference is specified, the subtree retains its independence. It can
3426
be branched by itself, and can be part of multiple projects at the same
3427
time. But operations performed in the containing tree, such as commit
3428
and merge, will recurse into the subtree.
3431
_see_also = ['split']
3432
takes_args = ['tree']
3433
takes_options = [Option('reference', 'join by reference')]
3436
def run(self, tree, reference=False):
3437
sub_tree = WorkingTree.open(tree)
3438
parent_dir = osutils.dirname(sub_tree.basedir)
3439
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3440
repo = containing_tree.branch.repository
3441
if not repo.supports_rich_root():
3442
raise errors.BzrCommandError(
3443
"Can't join trees because %s doesn't support rich root data.\n"
3444
"You can use bzr upgrade on the repository."
3448
containing_tree.add_reference(sub_tree)
3449
except errors.BadReferenceTarget, e:
3450
# XXX: Would be better to just raise a nicely printable
3451
# exception from the real origin. Also below. mbp 20070306
3452
raise errors.BzrCommandError("Cannot join %s. %s" %
3456
containing_tree.subsume(sub_tree)
3457
except errors.BadSubsumeSource, e:
3458
raise errors.BzrCommandError("Cannot join %s. %s" %
3462
class cmd_split(Command):
3463
"""Split a tree into two trees.
3465
This command is for experimental use only. It requires the target tree
3466
to be in dirstate-with-subtree format, which cannot be converted into
3469
The TREE argument should be a subdirectory of a working tree. That
3470
subdirectory will be converted into an independent tree, with its own
3471
branch. Commits in the top-level tree will not apply to the new subtree.
3472
If you want that behavior, do "bzr join --reference TREE".
3475
_see_also = ['join']
3476
takes_args = ['tree']
3480
def run(self, tree):
3481
containing_tree, subdir = WorkingTree.open_containing(tree)
3482
sub_id = containing_tree.path2id(subdir)
3484
raise errors.NotVersionedError(subdir)
3486
containing_tree.extract(sub_id)
3487
except errors.RootNotRich:
3488
raise errors.UpgradeRequired(containing_tree.branch.base)
3492
class cmd_merge_directive(Command):
3493
"""Generate a merge directive for auto-merge tools.
3495
A directive requests a merge to be performed, and also provides all the
3496
information necessary to do so. This means it must either include a
3497
revision bundle, or the location of a branch containing the desired
3500
A submit branch (the location to merge into) must be supplied the first
3501
time the command is issued. After it has been supplied once, it will
3502
be remembered as the default.
3504
A public branch is optional if a revision bundle is supplied, but required
3505
if --diff or --plain is specified. It will be remembered as the default
3506
after the first use.
3509
takes_args = ['submit_branch?', 'public_branch?']
3513
_see_also = ['submit']
3516
RegistryOption.from_kwargs('patch-type',
3517
'The type of patch to include in the directive',
3518
title='Patch type', value_switches=True, enum_switch=False,
3519
bundle='Bazaar revision bundle (default)',
3520
diff='Normal unified diff',
3521
plain='No patch, just directive'),
3522
Option('sign', help='GPG-sign the directive'), 'revision',
3523
Option('mail-to', type=str,
3524
help='Instead of printing the directive, email to this address'),
3525
Option('message', type=str, short_name='m',
3526
help='Message to use when committing this merge')
3529
encoding_type = 'exact'
3531
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3532
sign=False, revision=None, mail_to=None, message=None):
3533
from bzrlib.revision import ensure_null, NULL_REVISION
3534
include_patch, include_bundle = {
3535
'plain': (False, False),
3536
'diff': (True, False),
3537
'bundle': (True, True),
3539
branch = Branch.open('.')
3540
stored_submit_branch = branch.get_submit_branch()
3541
if submit_branch is None:
3542
submit_branch = stored_submit_branch
3544
if stored_submit_branch is None:
3545
branch.set_submit_branch(submit_branch)
3546
if submit_branch is None:
3547
submit_branch = branch.get_parent()
3548
if submit_branch is None:
3549
raise errors.BzrCommandError('No submit branch specified or known')
3551
stored_public_branch = branch.get_public_branch()
3552
if public_branch is None:
3553
public_branch = stored_public_branch
3554
elif stored_public_branch is None:
3555
branch.set_public_branch(public_branch)
3556
if not include_bundle and public_branch is None:
3557
raise errors.BzrCommandError('No public branch specified or'
3559
base_revision_id = None
3560
if revision is not None:
3561
if len(revision) > 2:
3562
raise errors.BzrCommandError('bzr merge-directive takes '
3563
'at most two one revision identifiers')
3564
revision_id = revision[-1].in_history(branch).rev_id
3565
if len(revision) == 2:
3566
base_revision_id = revision[0].in_history(branch).rev_id
3567
base_revision_id = ensure_null(base_revision_id)
3569
revision_id = branch.last_revision()
3570
revision_id = ensure_null(revision_id)
3571
if revision_id == NULL_REVISION:
3572
raise errors.BzrCommandError('No revisions to bundle.')
3573
directive = merge_directive.MergeDirective2.from_objects(
3574
branch.repository, revision_id, time.time(),
3575
osutils.local_time_offset(), submit_branch,
3576
public_branch=public_branch, include_patch=include_patch,
3577
include_bundle=include_bundle, message=message,
3578
base_revision_id=base_revision_id)
3581
self.outf.write(directive.to_signed(branch))
3583
self.outf.writelines(directive.to_lines())
3585
message = directive.to_email(mail_to, branch, sign)
3586
s = SMTPConnection(branch.get_config())
3587
s.send_email(message)
3590
class cmd_submit(Command):
3591
"""Create a merge-directive for submiting changes.
3593
A merge directive provides many things needed for requesting merges:
3594
- A machine-readable description of the merge to perform
3595
- An optional patch that is a preview of the changes requested
3596
- An optional bundle of revision data, so that the changes can be applied
3597
directly from the merge directive, without retrieving data from a
3600
If --no-bundle is specified, then public_branch is needed (and must be
3601
up-to-date), so that the receiver can perform the merge using the
3602
public_branch. The public_branch is always included if known, so that
3603
people can check it later.
3605
The submit branch defaults to the parent, but can be overridden. Both
3606
submit branch and public branch will be remembered if supplied.
3608
If a public_branch is known for the submit_branch, that public submit
3609
branch is used in the merge instructions. This means that a local mirror
3610
can be used as your actual submit branch, once you have set public_branch
3614
encoding_type = 'exact'
3616
aliases = ['bundle', 'bundle-revisions']
3618
_see_also = ['merge']
3620
takes_args = ['submit_branch?', 'public_branch?']
3623
help='Do not include a bundle in the merge directive'),
3624
Option('no-patch', help='Do not include a preview patch in the merge'
3627
help='Remember submit and public branch'),
3629
help='branch to generate the submission from, '
3630
'rather than the one containing the working directory',
3633
Option('output', short_name='o', help='Write directive to this file',
3638
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3639
no_patch=False, revision=None, remember=False, output=None,
3641
from bzrlib.revision import ensure_null, NULL_REVISION
3645
outfile = open(output, 'wb')
3647
from_ = kwargs.get('from', '.')
3648
branch = Branch.open_containing(from_)[0]
3649
if remember and submit_branch is None:
3650
raise errors.BzrCommandError(
3651
'--remember requires a branch to be specified.')
3652
stored_submit_branch = branch.get_submit_branch()
3653
remembered_submit_branch = False
3654
if submit_branch is None:
3655
submit_branch = stored_submit_branch
3656
remembered_submit_branch = True
3658
if stored_submit_branch is None or remember:
3659
branch.set_submit_branch(submit_branch)
3660
if submit_branch is None:
3661
submit_branch = branch.get_parent()
3662
remembered_submit_branch = True
3663
if submit_branch is None:
3664
raise errors.BzrCommandError('No submit branch known or'
3666
if remembered_submit_branch:
3667
note('Using saved location: %s', submit_branch)
3669
stored_public_branch = branch.get_public_branch()
3670
if public_branch is None:
3671
public_branch = stored_public_branch
3672
elif stored_public_branch is None or remember:
3673
branch.set_public_branch(public_branch)
3674
if no_bundle and public_branch is None:
3675
raise errors.BzrCommandError('No public branch specified or'
3677
base_revision_id = None
3678
if revision is not None:
3679
if len(revision) > 2:
3680
raise errors.BzrCommandError('bzr submit takes '
3681
'at most two one revision identifiers')
3682
revision_id = revision[-1].in_history(branch).rev_id
3683
if len(revision) == 2:
3684
base_revision_id = revision[0].in_history(branch).rev_id
3685
base_revision_id = ensure_null(base_revision_id)
3687
revision_id = branch.last_revision()
3688
revision_id = ensure_null(revision_id)
3689
if revision_id == NULL_REVISION:
3690
raise errors.BzrCommandError('No revisions to submit.')
3691
directive = merge_directive.MergeDirective2.from_objects(
3692
branch.repository, revision_id, time.time(),
3693
osutils.local_time_offset(), submit_branch,
3694
public_branch=public_branch, include_patch=not no_patch,
3695
include_bundle=not no_bundle, message=None,
3696
base_revision_id=base_revision_id)
3697
outfile.writelines(directive.to_lines())
3699
if output is not None:
3702
class cmd_tag(Command):
3703
"""Create a tag naming a revision.
3705
Tags give human-meaningful names to revisions. Commands that take a -r
3706
(--revision) option can be given -rtag:X, where X is any previously
3709
Tags are stored in the branch. Tags are copied from one branch to another
3710
along when you branch, push, pull or merge.
3712
It is an error to give a tag name that already exists unless you pass
3713
--force, in which case the tag is moved to point to the new revision.
3716
_see_also = ['commit', 'tags']
3717
takes_args = ['tag_name']
3720
help='Delete this tag rather than placing it.',
3723
help='Branch in which to place the tag.',
3728
help='Replace existing tags',
3733
def run(self, tag_name,
3739
branch, relpath = Branch.open_containing(directory)
3743
branch.tags.delete_tag(tag_name)
3744
self.outf.write('Deleted tag %s.\n' % tag_name)
3747
if len(revision) != 1:
3748
raise errors.BzrCommandError(
3749
"Tags can only be placed on a single revision, "
3751
revision_id = revision[0].in_history(branch).rev_id
3753
revision_id = branch.last_revision()
3754
if (not force) and branch.tags.has_tag(tag_name):
3755
raise errors.TagAlreadyExists(tag_name)
3756
branch.tags.set_tag(tag_name, revision_id)
3757
self.outf.write('Created tag %s.\n' % tag_name)
3762
class cmd_tags(Command):
3765
This tag shows a table of tag names and the revisions they reference.
3771
help='Branch whose tags should be displayed',
3781
branch, relpath = Branch.open_containing(directory)
3782
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3783
self.outf.write('%-20s %s\n' % (tag_name, target))
3786
# command-line interpretation helper for merge-related commands
3787
def _merge_helper(other_revision, base_revision,
3788
check_clean=True, ignore_zero=False,
3789
this_dir=None, backup_files=False,
3791
file_list=None, show_base=False, reprocess=False,
3794
change_reporter=None,
3795
other_rev_id=None, base_rev_id=None):
3796
"""Merge changes into a tree.
3799
list(path, revno) Base for three-way merge.
3800
If [None, None] then a base will be automatically determined.
3802
list(path, revno) Other revision for three-way merge.
3804
Directory to merge changes into; '.' by default.
3806
If true, this_dir must have no uncommitted changes before the
3808
ignore_zero - If true, suppress the "zero conflicts" message when
3809
there are no conflicts; should be set when doing something we expect
3810
to complete perfectly.
3811
file_list - If supplied, merge only changes to selected files.
3813
All available ancestors of other_revision and base_revision are
3814
automatically pulled into the branch.
3816
The revno may be -1 to indicate the last revision on the branch, which is
3819
This function is intended for use from the command line; programmatic
3820
clients might prefer to call merge.merge_inner(), which has less magic
3823
# Loading it late, so that we don't always have to import bzrlib.merge
3824
if merge_type is None:
3825
merge_type = _mod_merge.Merge3Merger
3826
if this_dir is None:
3828
this_tree = WorkingTree.open_containing(this_dir)[0]
3829
if show_base and not merge_type is _mod_merge.Merge3Merger:
3830
raise errors.BzrCommandError("Show-base is not supported for this merge"
3831
" type. %s" % merge_type)
3832
if reprocess and not merge_type.supports_reprocess:
3833
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3834
" type %s." % merge_type)
3835
if reprocess and show_base:
3836
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3837
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3838
# only want to take out a lock_tree_write() if we don't have to pull
3839
# any ancestry. But merge might fetch ancestry in the middle, in
3840
# which case we would need a lock_write().
3841
# Because we cannot upgrade locks, for now we live with the fact that
3842
# the tree will be locked multiple times during a merge. (Maybe
3843
# read-only some of the time, but it means things will get read
3846
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3847
pb=pb, change_reporter=change_reporter)
3848
merger.pp = ProgressPhase("Merge phase", 5, pb)
3849
merger.pp.next_phase()
3850
merger.check_basis(check_clean)
3851
if other_rev_id is not None:
3852
merger.set_other_revision(other_rev_id, this_tree.branch)
3854
merger.set_other(other_revision)
3855
merger.pp.next_phase()
3856
if base_rev_id is not None:
3857
merger.set_base_revision(base_rev_id, this_tree.branch)
3858
elif base_revision is not None:
3859
merger.set_base(base_revision)
3862
if merger.base_rev_id == merger.other_rev_id:
3863
note('Nothing to do.')
3865
if file_list is None:
3866
if pull and merger.base_rev_id == merger.this_rev_id:
3867
# FIXME: deduplicate with pull
3868
result = merger.this_tree.pull(merger.this_branch,
3869
False, merger.other_rev_id)
3870
if result.old_revid == result.new_revid:
3871
note('No revisions to pull.')
3873
note('Now on revision %d.' % result.new_revno)
3875
merger.backup_files = backup_files
3876
merger.merge_type = merge_type
3877
merger.set_interesting_files(file_list)
3878
merger.show_base = show_base
3879
merger.reprocess = reprocess
3880
conflicts = merger.do_merge()
3881
if file_list is None:
3882
merger.set_pending()
3888
def _create_prefix(cur_transport):
3889
needed = [cur_transport]
3890
# Recurse upwards until we can create a directory successfully
3892
new_transport = cur_transport.clone('..')
3893
if new_transport.base == cur_transport.base:
3894
raise errors.BzrCommandError("Failed to create path"
3898
new_transport.mkdir('.')
3899
except errors.NoSuchFile:
3900
needed.append(new_transport)
3901
cur_transport = new_transport
3905
# Now we only need to create child directories
3907
cur_transport = needed.pop()
3908
cur_transport.ensure_base()
3911
merge = _merge_helper
3914
# these get imported and then picked up by the scan for cmd_*
3915
# TODO: Some more consistent way to split command definitions across files;
3916
# we do need to load at least some information about them to know of
3917
# aliases. ideally we would avoid loading the implementation until the
3918
# details were needed.
3919
from bzrlib.cmd_version_info import cmd_version_info
3920
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3921
from bzrlib.bundle.commands import (
3924
from bzrlib.sign_my_commits import cmd_sign_my_commits
3925
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3926
cmd_weave_plan_merge, cmd_weave_merge_text