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(), """
47
revision as _mod_revision,
55
from bzrlib.branch import Branch
56
from bzrlib.conflicts import ConflictList
57
from bzrlib.revisionspec import RevisionSpec
58
from bzrlib.smtp_connection import SMTPConnection
59
from bzrlib.workingtree import WorkingTree
62
from bzrlib.commands import Command, display_command
63
from bzrlib.option import ListOption, Option, RegistryOption
64
from bzrlib.progress import DummyProgress, ProgressPhase
65
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
68
def tree_files(file_list, default_branch=u'.'):
70
return internal_tree_files(file_list, default_branch)
71
except errors.FileInWrongBranch, e:
72
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
(e.path, file_list[0]))
76
# XXX: Bad function name; should possibly also be a class method of
77
# WorkingTree rather than a function.
78
def internal_tree_files(file_list, default_branch=u'.'):
79
"""Convert command-line paths to a WorkingTree and relative paths.
81
This is typically used for command-line processors that take one or
82
more filenames, and infer the workingtree that contains them.
84
The filenames given are not required to exist.
86
:param file_list: Filenames to convert.
88
:param default_branch: Fallback tree path to use if file_list is empty or
91
:return: workingtree, [relative_paths]
93
if file_list is None or len(file_list) == 0:
94
return WorkingTree.open_containing(default_branch)[0], file_list
95
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
97
for filename in file_list:
99
new_list.append(tree.relpath(osutils.dereference_path(filename)))
100
except errors.PathNotChild:
101
raise errors.FileInWrongBranch(tree.branch, filename)
102
return tree, new_list
105
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
106
def get_format_type(typestring):
107
"""Parse and return a format specifier."""
108
# Have to use BzrDirMetaFormat1 directly, so that
109
# RepositoryFormat.set_default_format works
110
if typestring == "default":
111
return bzrdir.BzrDirMetaFormat1()
113
return bzrdir.format_registry.make_bzrdir(typestring)
115
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
116
raise errors.BzrCommandError(msg)
119
# TODO: Make sure no commands unconditionally use the working directory as a
120
# branch. If a filename argument is used, the first of them should be used to
121
# specify the branch. (Perhaps this can be factored out into some kind of
122
# Argument class, representing a file in a branch, where the first occurrence
125
class cmd_status(Command):
126
"""Display status summary.
128
This reports on versioned and unknown files, reporting them
129
grouped by state. Possible states are:
132
Versioned in the working copy but not in the previous revision.
135
Versioned in the previous revision but removed or deleted
139
Path of this file changed from the previous revision;
140
the text may also have changed. This includes files whose
141
parent directory was renamed.
144
Text has changed since the previous revision.
147
File kind has been changed (e.g. from file to directory).
150
Not versioned and not matching an ignore pattern.
152
To see ignored files use 'bzr ignored'. For details on the
153
changes to file texts, use 'bzr diff'.
155
--short gives a status flags for each item, similar to the SVN's status
158
If no arguments are specified, the status of the entire working
159
directory is shown. Otherwise, only the status of the specified
160
files or directories is reported. If a directory is given, status
161
is reported for everything inside that directory.
163
If a revision argument is given, the status is calculated against
164
that revision, or between two revisions if two are provided.
167
# TODO: --no-recurse, --recurse options
169
takes_args = ['file*']
170
takes_options = ['show-ids', 'revision',
171
Option('short', help='Give short SVN-style status lines.'),
172
Option('versioned', help='Only show versioned files.')]
173
aliases = ['st', 'stat']
175
encoding_type = 'replace'
176
_see_also = ['diff', 'revert', 'status-flags']
179
def run(self, show_ids=False, file_list=None, revision=None, short=False,
181
from bzrlib.status import show_tree_status
183
tree, file_list = tree_files(file_list)
185
show_tree_status(tree, show_ids=show_ids,
186
specific_files=file_list, revision=revision,
187
to_file=self.outf, short=short, versioned=versioned)
190
class cmd_cat_revision(Command):
191
"""Write out metadata for a revision.
193
The revision to print can either be specified by a specific
194
revision identifier, or you can use --revision.
198
takes_args = ['revision_id?']
199
takes_options = ['revision']
200
# cat-revision is more for frontends so should be exact
204
def run(self, revision_id=None, revision=None):
206
revision_id = osutils.safe_revision_id(revision_id, warn=False)
207
if revision_id is not None and revision is not None:
208
raise errors.BzrCommandError('You can only supply one of'
209
' revision_id or --revision')
210
if revision_id is None and revision is None:
211
raise errors.BzrCommandError('You must supply either'
212
' --revision or a revision_id')
213
b = WorkingTree.open_containing(u'.')[0].branch
215
# TODO: jam 20060112 should cat-revision always output utf-8?
216
if revision_id is not None:
217
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
218
elif revision is not None:
221
raise errors.BzrCommandError('You cannot specify a NULL'
223
revno, rev_id = rev.in_history(b)
224
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
227
class cmd_remove_tree(Command):
228
"""Remove the working tree from a given branch/checkout.
230
Since a lightweight checkout is little more than a working tree
231
this will refuse to run against one.
233
To re-create the working tree, use "bzr checkout".
235
_see_also = ['checkout', 'working-trees']
237
takes_args = ['location?']
239
def run(self, location='.'):
240
d = bzrdir.BzrDir.open(location)
243
working = d.open_workingtree()
244
except errors.NoWorkingTree:
245
raise errors.BzrCommandError("No working tree to remove")
246
except errors.NotLocalUrl:
247
raise errors.BzrCommandError("You cannot remove the working tree of a "
250
working_path = working.bzrdir.root_transport.base
251
branch_path = working.branch.bzrdir.root_transport.base
252
if working_path != branch_path:
253
raise errors.BzrCommandError("You cannot remove the working tree from "
254
"a lightweight checkout")
256
d.destroy_workingtree()
259
class cmd_revno(Command):
260
"""Show current revision number.
262
This is equal to the number of revisions on this branch.
266
takes_args = ['location?']
269
def run(self, location=u'.'):
270
self.outf.write(str(Branch.open_containing(location)[0].revno()))
271
self.outf.write('\n')
274
class cmd_revision_info(Command):
275
"""Show revision number and revision id for a given revision identifier.
278
takes_args = ['revision_info*']
279
takes_options = ['revision']
282
def run(self, revision=None, revision_info_list=[]):
285
if revision is not None:
286
revs.extend(revision)
287
if revision_info_list is not None:
288
for rev in revision_info_list:
289
revs.append(RevisionSpec.from_string(rev))
291
b = Branch.open_containing(u'.')[0]
294
revs.append(RevisionSpec.from_string('-1'))
297
revinfo = rev.in_history(b)
298
if revinfo.revno is None:
299
dotted_map = b.get_revision_id_to_revno_map()
300
revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
301
print '%s %s' % (revno, revinfo.rev_id)
303
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
306
class cmd_add(Command):
307
"""Add specified files or directories.
309
In non-recursive mode, all the named items are added, regardless
310
of whether they were previously ignored. A warning is given if
311
any of the named files are already versioned.
313
In recursive mode (the default), files are treated the same way
314
but the behaviour for directories is different. Directories that
315
are already versioned do not give a warning. All directories,
316
whether already versioned or not, are searched for files or
317
subdirectories that are neither versioned or ignored, and these
318
are added. This search proceeds recursively into versioned
319
directories. If no names are given '.' is assumed.
321
Therefore simply saying 'bzr add' will version all files that
322
are currently unknown.
324
Adding a file whose parent directory is not versioned will
325
implicitly add the parent, and so on up to the root. This means
326
you should never need to explicitly add a directory, they'll just
327
get added when you add a file in the directory.
329
--dry-run will show which files would be added, but not actually
332
--file-ids-from will try to use the file ids from the supplied path.
333
It looks up ids trying to find a matching parent directory with the
334
same filename, and then by pure path. This option is rarely needed
335
but can be useful when adding the same logical file into two
336
branches that will be merged later (without showing the two different
337
adds as a conflict). It is also useful when merging another project
338
into a subdirectory of this one.
340
takes_args = ['file*']
343
help="Don't recursively add the contents of directories."),
345
help="Show what would be done, but don't actually do anything."),
347
Option('file-ids-from',
349
help='Lookup file ids from this tree.'),
351
encoding_type = 'replace'
352
_see_also = ['remove']
354
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
359
if file_ids_from is not None:
361
base_tree, base_path = WorkingTree.open_containing(
363
except errors.NoWorkingTree:
364
base_branch, base_path = Branch.open_containing(
366
base_tree = base_branch.basis_tree()
368
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
369
to_file=self.outf, should_print=(not is_quiet()))
371
action = bzrlib.add.AddAction(to_file=self.outf,
372
should_print=(not is_quiet()))
375
base_tree.lock_read()
377
file_list = self._maybe_expand_globs(file_list)
379
tree = WorkingTree.open_containing(file_list[0])[0]
381
tree = WorkingTree.open_containing(u'.')[0]
382
added, ignored = tree.smart_add(file_list, not
383
no_recurse, action=action, save=not dry_run)
385
if base_tree is not None:
389
for glob in sorted(ignored.keys()):
390
for path in ignored[glob]:
391
self.outf.write("ignored %s matching \"%s\"\n"
395
for glob, paths in ignored.items():
396
match_len += len(paths)
397
self.outf.write("ignored %d file(s).\n" % match_len)
398
self.outf.write("If you wish to add some of these files,"
399
" please add them by name.\n")
402
class cmd_mkdir(Command):
403
"""Create a new versioned directory.
405
This is equivalent to creating the directory and then adding it.
408
takes_args = ['dir+']
409
encoding_type = 'replace'
411
def run(self, dir_list):
414
wt, dd = WorkingTree.open_containing(d)
416
self.outf.write('added %s\n' % d)
419
class cmd_relpath(Command):
420
"""Show path of a file relative to root"""
422
takes_args = ['filename']
426
def run(self, filename):
427
# TODO: jam 20050106 Can relpath return a munged path if
428
# sys.stdout encoding cannot represent it?
429
tree, relpath = WorkingTree.open_containing(filename)
430
self.outf.write(relpath)
431
self.outf.write('\n')
434
class cmd_inventory(Command):
435
"""Show inventory of the current working copy or a revision.
437
It is possible to limit the output to a particular entry
438
type using the --kind option. For example: --kind file.
440
It is also possible to restrict the list of files to a specific
441
set. For example: bzr inventory --show-ids this/file
450
help='List entries of a particular kind: file, directory, symlink.',
453
takes_args = ['file*']
456
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
457
if kind and kind not in ['file', 'directory', 'symlink']:
458
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
460
work_tree, file_list = tree_files(file_list)
461
work_tree.lock_read()
463
if revision is not None:
464
if len(revision) > 1:
465
raise errors.BzrCommandError(
466
'bzr inventory --revision takes exactly one revision'
468
revision_id = revision[0].in_history(work_tree.branch).rev_id
469
tree = work_tree.branch.repository.revision_tree(revision_id)
471
extra_trees = [work_tree]
477
if file_list is not None:
478
file_ids = tree.paths2ids(file_list, trees=extra_trees,
479
require_versioned=True)
480
# find_ids_across_trees may include some paths that don't
482
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
483
for file_id in file_ids if file_id in tree)
485
entries = tree.inventory.entries()
488
if tree is not work_tree:
491
for path, entry in entries:
492
if kind and kind != entry.kind:
495
self.outf.write('%-50s %s\n' % (path, entry.file_id))
497
self.outf.write(path)
498
self.outf.write('\n')
501
class cmd_mv(Command):
502
"""Move or rename a file.
505
bzr mv OLDNAME NEWNAME
506
bzr mv SOURCE... DESTINATION
508
If the last argument is a versioned directory, all the other names
509
are moved into it. Otherwise, there must be exactly two arguments
510
and the file is changed to a new name.
512
If OLDNAME does not exist on the filesystem but is versioned and
513
NEWNAME does exist on the filesystem but is not versioned, mv
514
assumes that the file has been manually moved and only updates
515
its internal inventory to reflect that change.
516
The same is valid when moving many SOURCE files to a DESTINATION.
518
Files cannot be moved between branches.
521
takes_args = ['names*']
522
takes_options = [Option("after", help="Move only the bzr identifier"
523
" of the file, because the file has already been moved."),
525
aliases = ['move', 'rename']
526
encoding_type = 'replace'
528
def run(self, names_list, after=False):
529
if names_list is None:
532
if len(names_list) < 2:
533
raise errors.BzrCommandError("missing file argument")
534
tree, rel_names = tree_files(names_list)
536
if os.path.isdir(names_list[-1]):
537
# move into existing directory
538
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
539
self.outf.write("%s => %s\n" % pair)
541
if len(names_list) != 2:
542
raise errors.BzrCommandError('to mv multiple files the'
543
' destination must be a versioned'
545
tree.rename_one(rel_names[0], rel_names[1], after=after)
546
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
549
class cmd_pull(Command):
550
"""Turn this branch into a mirror of another branch.
552
This command only works on branches that have not diverged. Branches are
553
considered diverged if the destination branch's most recent commit is one
554
that has not been merged (directly or indirectly) into the parent.
556
If branches have diverged, you can use 'bzr merge' to integrate the changes
557
from one into the other. Once one branch has merged, the other should
558
be able to pull it again.
560
If you want to forget your local changes and just update your branch to
561
match the remote one, use pull --overwrite.
563
If there is no default location set, the first pull will set it. After
564
that, you can omit the location to use the default. To change the
565
default, use --remember. The value will only be saved if the remote
566
location can be accessed.
569
_see_also = ['push', 'update', 'status-flags']
570
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
572
help='Branch to pull into, '
573
'rather than the one containing the working directory.',
578
takes_args = ['location?']
579
encoding_type = 'replace'
581
def run(self, location=None, remember=False, overwrite=False,
582
revision=None, verbose=False,
584
from bzrlib.tag import _merge_tags_if_possible
585
# FIXME: too much stuff is in the command class
588
if directory is None:
591
tree_to = WorkingTree.open_containing(directory)[0]
592
branch_to = tree_to.branch
593
except errors.NoWorkingTree:
595
branch_to = Branch.open_containing(directory)[0]
598
if location is not None:
600
mergeable = bundle.read_mergeable_from_url(
602
except errors.NotABundle:
603
pass # Continue on considering this url a Branch
605
stored_loc = branch_to.get_parent()
607
if stored_loc is None:
608
raise errors.BzrCommandError("No pull location known or"
611
display_url = urlutils.unescape_for_display(stored_loc,
613
self.outf.write("Using saved location: %s\n" % display_url)
614
location = stored_loc
616
if mergeable is not None:
617
if revision is not None:
618
raise errors.BzrCommandError(
619
'Cannot use -r with merge directives or bundles')
620
mergeable.install_revisions(branch_to.repository)
621
base_revision_id, revision_id, verified = \
622
mergeable.get_merge_request(branch_to.repository)
623
branch_from = branch_to
625
branch_from = Branch.open(location)
627
if branch_to.get_parent() is None or remember:
628
branch_to.set_parent(branch_from.base)
630
if revision is not None:
631
if len(revision) == 1:
632
revision_id = revision[0].in_history(branch_from).rev_id
634
raise errors.BzrCommandError(
635
'bzr pull --revision takes one value.')
638
old_rh = branch_to.revision_history()
639
if tree_to is not None:
640
result = tree_to.pull(branch_from, overwrite, revision_id,
641
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
643
result = branch_to.pull(branch_from, overwrite, revision_id)
645
result.report(self.outf)
647
from bzrlib.log import show_changed_revisions
648
new_rh = branch_to.revision_history()
649
show_changed_revisions(branch_to, old_rh, new_rh,
653
class cmd_push(Command):
654
"""Update a mirror of this branch.
656
The target branch will not have its working tree populated because this
657
is both expensive, and is not supported on remote file systems.
659
Some smart servers or protocols *may* put the working tree in place in
662
This command only works on branches that have not diverged. Branches are
663
considered diverged if the destination branch's most recent commit is one
664
that has not been merged (directly or indirectly) by the source branch.
666
If branches have diverged, you can use 'bzr push --overwrite' to replace
667
the other branch completely, discarding its unmerged changes.
669
If you want to ensure you have the different changes in the other branch,
670
do a merge (see bzr help merge) from the other branch, and commit that.
671
After that you will be able to do a push without '--overwrite'.
673
If there is no default push location set, the first push will set it.
674
After that, you can omit the location to use the default. To change the
675
default, use --remember. The value will only be saved if the remote
676
location can be accessed.
679
_see_also = ['pull', 'update', 'working-trees']
680
takes_options = ['remember', 'overwrite', 'verbose',
681
Option('create-prefix',
682
help='Create the path leading up to the branch '
683
'if it does not already exist.'),
685
help='Branch to push from, '
686
'rather than the one containing the working directory.',
690
Option('use-existing-dir',
691
help='By default push will fail if the target'
692
' directory exists, but does not already'
693
' have a control directory. This flag will'
694
' allow push to proceed.'),
696
takes_args = ['location?']
697
encoding_type = 'replace'
699
def run(self, location=None, remember=False, overwrite=False,
700
create_prefix=False, verbose=False,
701
use_existing_dir=False,
703
# FIXME: Way too big! Put this into a function called from the
705
if directory is None:
707
br_from = Branch.open_containing(directory)[0]
708
stored_loc = br_from.get_push_location()
710
if stored_loc is None:
711
raise errors.BzrCommandError("No push location known or specified.")
713
display_url = urlutils.unescape_for_display(stored_loc,
715
self.outf.write("Using saved location: %s\n" % display_url)
716
location = stored_loc
718
to_transport = transport.get_transport(location)
720
br_to = repository_to = dir_to = None
722
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
723
except errors.NotBranchError:
724
pass # Didn't find anything
726
# If we can open a branch, use its direct repository, otherwise see
727
# if there is a repository without a branch.
729
br_to = dir_to.open_branch()
730
except errors.NotBranchError:
731
# Didn't find a branch, can we find a repository?
733
repository_to = dir_to.find_repository()
734
except errors.NoRepositoryPresent:
737
# Found a branch, so we must have found a repository
738
repository_to = br_to.repository
743
# The destination doesn't exist; create it.
744
# XXX: Refactor the create_prefix/no_create_prefix code into a
745
# common helper function
747
to_transport.mkdir('.')
748
except errors.FileExists:
749
if not use_existing_dir:
750
raise errors.BzrCommandError("Target directory %s"
751
" already exists, but does not have a valid .bzr"
752
" directory. Supply --use-existing-dir to push"
753
" there anyway." % location)
754
except errors.NoSuchFile:
755
if not create_prefix:
756
raise errors.BzrCommandError("Parent directory of %s"
758
"\nYou may supply --create-prefix to create all"
759
" leading parent directories."
761
_create_prefix(to_transport)
763
# Now the target directory exists, but doesn't have a .bzr
764
# directory. So we need to create it, along with any work to create
765
# all of the dependent branches, etc.
766
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
767
revision_id=br_from.last_revision())
768
br_to = dir_to.open_branch()
769
# TODO: Some more useful message about what was copied
770
note('Created new branch.')
771
# We successfully created the target, remember it
772
if br_from.get_push_location() is None or remember:
773
br_from.set_push_location(br_to.base)
774
elif repository_to is None:
775
# we have a bzrdir but no branch or repository
776
# XXX: Figure out what to do other than complain.
777
raise errors.BzrCommandError("At %s you have a valid .bzr control"
778
" directory, but not a branch or repository. This is an"
779
" unsupported configuration. Please move the target directory"
780
" out of the way and try again."
783
# We have a repository but no branch, copy the revisions, and then
785
last_revision_id = br_from.last_revision()
786
repository_to.fetch(br_from.repository,
787
revision_id=last_revision_id)
788
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
789
note('Created new branch.')
790
if br_from.get_push_location() is None or remember:
791
br_from.set_push_location(br_to.base)
792
else: # We have a valid to branch
793
# We were able to connect to the remote location, so remember it
794
# we don't need to successfully push because of possible divergence.
795
if br_from.get_push_location() is None or remember:
796
br_from.set_push_location(br_to.base)
798
old_rh = br_to.revision_history()
801
tree_to = dir_to.open_workingtree()
802
except errors.NotLocalUrl:
803
warning("This transport does not update the working "
804
"tree of: %s. See 'bzr help working-trees' for "
805
"more information." % br_to.base)
806
push_result = br_from.push(br_to, overwrite)
807
except errors.NoWorkingTree:
808
push_result = br_from.push(br_to, overwrite)
812
push_result = br_from.push(tree_to.branch, overwrite)
816
except errors.DivergedBranches:
817
raise errors.BzrCommandError('These branches have diverged.'
818
' Try using "merge" and then "push".')
819
if push_result is not None:
820
push_result.report(self.outf)
822
new_rh = br_to.revision_history()
825
from bzrlib.log import show_changed_revisions
826
show_changed_revisions(br_to, old_rh, new_rh,
829
# we probably did a clone rather than a push, so a message was
834
class cmd_branch(Command):
835
"""Create a new copy of a branch.
837
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
838
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
839
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
840
is derived from the FROM_LOCATION by stripping a leading scheme or drive
841
identifier, if any. For example, "branch lp:foo-bar" will attempt to
844
To retrieve the branch as of a particular revision, supply the --revision
845
parameter, as in "branch foo/bar -r 5".
848
_see_also = ['checkout']
849
takes_args = ['from_location', 'to_location?']
850
takes_options = ['revision']
851
aliases = ['get', 'clone']
853
def run(self, from_location, to_location=None, revision=None):
854
from bzrlib.tag import _merge_tags_if_possible
857
elif len(revision) > 1:
858
raise errors.BzrCommandError(
859
'bzr branch --revision takes exactly 1 revision value')
861
br_from = Branch.open(from_location)
864
if len(revision) == 1 and revision[0] is not None:
865
revision_id = revision[0].in_history(br_from)[1]
867
# FIXME - wt.last_revision, fallback to branch, fall back to
868
# None or perhaps NULL_REVISION to mean copy nothing
870
revision_id = br_from.last_revision()
871
if to_location is None:
872
to_location = urlutils.derive_to_location(from_location)
875
name = os.path.basename(to_location) + '\n'
877
to_transport = transport.get_transport(to_location)
879
to_transport.mkdir('.')
880
except errors.FileExists:
881
raise errors.BzrCommandError('Target directory "%s" already'
882
' exists.' % to_location)
883
except errors.NoSuchFile:
884
raise errors.BzrCommandError('Parent of "%s" does not exist.'
887
# preserve whatever source format we have.
888
dir = br_from.bzrdir.sprout(to_transport.base, revision_id)
889
branch = dir.open_branch()
890
except errors.NoSuchRevision:
891
to_transport.delete_tree('.')
892
msg = "The branch %s has no revision %s." % (from_location, revision[0])
893
raise errors.BzrCommandError(msg)
895
branch.control_files.put_utf8('branch-name', name)
896
_merge_tags_if_possible(br_from, branch)
897
note('Branched %d revision(s).' % branch.revno())
902
class cmd_checkout(Command):
903
"""Create a new checkout of an existing branch.
905
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
906
the branch found in '.'. This is useful if you have removed the working tree
907
or if it was never created - i.e. if you pushed the branch to its current
910
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
911
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
912
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
913
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
914
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
917
To retrieve the branch as of a particular revision, supply the --revision
918
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
919
out of date [so you cannot commit] but it may be useful (i.e. to examine old
923
_see_also = ['checkouts', 'branch']
924
takes_args = ['branch_location?', 'to_location?']
925
takes_options = ['revision',
926
Option('lightweight',
927
help="Perform a lightweight checkout. Lightweight "
928
"checkouts depend on access to the branch for "
929
"every operation. Normal checkouts can perform "
930
"common operations like diff and status without "
931
"such access, and also support local commits."
936
def run(self, branch_location=None, to_location=None, revision=None,
940
elif len(revision) > 1:
941
raise errors.BzrCommandError(
942
'bzr checkout --revision takes exactly 1 revision value')
943
if branch_location is None:
944
branch_location = osutils.getcwd()
945
to_location = branch_location
946
source = Branch.open(branch_location)
947
if len(revision) == 1 and revision[0] is not None:
948
revision_id = revision[0].in_history(source)[1]
951
if to_location is None:
952
to_location = urlutils.derive_to_location(branch_location)
953
# if the source and to_location are the same,
954
# and there is no working tree,
955
# then reconstitute a branch
956
if (osutils.abspath(to_location) ==
957
osutils.abspath(branch_location)):
959
source.bzrdir.open_workingtree()
960
except errors.NoWorkingTree:
961
source.bzrdir.create_workingtree()
964
os.mkdir(to_location)
966
if e.errno == errno.EEXIST:
967
raise errors.BzrCommandError('Target directory "%s" already'
968
' exists.' % to_location)
969
if e.errno == errno.ENOENT:
970
raise errors.BzrCommandError('Parent of "%s" does not exist.'
974
source.create_checkout(to_location, revision_id, lightweight)
977
class cmd_renames(Command):
978
"""Show list of renamed files.
980
# TODO: Option to show renames between two historical versions.
982
# TODO: Only show renames under dir, rather than in the whole branch.
983
_see_also = ['status']
984
takes_args = ['dir?']
987
def run(self, dir=u'.'):
988
tree = WorkingTree.open_containing(dir)[0]
991
new_inv = tree.inventory
992
old_tree = tree.basis_tree()
995
old_inv = old_tree.inventory
996
renames = list(_mod_tree.find_renames(old_inv, new_inv))
998
for old_name, new_name in renames:
999
self.outf.write("%s => %s\n" % (old_name, new_name))
1006
class cmd_update(Command):
1007
"""Update a tree to have the latest code committed to its branch.
1009
This will perform a merge into the working tree, and may generate
1010
conflicts. If you have any local changes, you will still
1011
need to commit them after the update for the update to be complete.
1013
If you want to discard your local changes, you can just do a
1014
'bzr revert' instead of 'bzr commit' after the update.
1017
_see_also = ['pull', 'working-trees']
1018
takes_args = ['dir?']
1021
def run(self, dir='.'):
1022
tree = WorkingTree.open_containing(dir)[0]
1023
master = tree.branch.get_master_branch()
1024
if master is not None:
1027
tree.lock_tree_write()
1029
existing_pending_merges = tree.get_parent_ids()[1:]
1030
last_rev = _mod_revision.ensure_null(tree.last_revision())
1031
if last_rev == _mod_revision.ensure_null(
1032
tree.branch.last_revision()):
1033
# may be up to date, check master too.
1034
master = tree.branch.get_master_branch()
1035
if master is None or last_rev == _mod_revision.ensure_null(
1036
master.last_revision()):
1037
revno = tree.branch.revision_id_to_revno(last_rev)
1038
note("Tree is up to date at revision %d." % (revno,))
1040
conflicts = tree.update(delta._ChangeReporter(
1041
unversioned_filter=tree.is_ignored))
1042
revno = tree.branch.revision_id_to_revno(
1043
_mod_revision.ensure_null(tree.last_revision()))
1044
note('Updated to revision %d.' % (revno,))
1045
if tree.get_parent_ids()[1:] != existing_pending_merges:
1046
note('Your local commits will now show as pending merges with '
1047
"'bzr status', and can be committed with 'bzr commit'.")
1056
class cmd_info(Command):
1057
"""Show information about a working tree, branch or repository.
1059
This command will show all known locations and formats associated to the
1060
tree, branch or repository. Statistical information is included with
1063
Branches and working trees will also report any missing revisions.
1065
_see_also = ['revno', 'working-trees', 'repositories']
1066
takes_args = ['location?']
1067
takes_options = ['verbose']
1070
def run(self, location=None, verbose=0):
1071
from bzrlib.info import show_bzrdir_info
1072
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1076
class cmd_remove(Command):
1077
"""Remove files or directories.
1079
This makes bzr stop tracking changes to the specified files and
1080
delete them if they can easily be recovered using revert.
1082
You can specify one or more files, and/or --new. If you specify --new,
1083
only 'added' files will be removed. If you specify both, then new files
1084
in the specified directories will be removed. If the directories are
1085
also new, they will also be removed.
1087
takes_args = ['file*']
1088
takes_options = ['verbose',
1089
Option('new', help='Remove newly-added files.'),
1090
RegistryOption.from_kwargs('file-deletion-strategy',
1091
'The file deletion mode to be used',
1092
title='Deletion Strategy', value_switches=True, enum_switch=False,
1093
safe='Only delete files if they can be'
1094
' safely recovered (default).',
1095
keep="Don't delete any files.",
1096
force='Delete all the specified files, even if they can not be '
1097
'recovered and even if they are non-empty directories.')]
1099
encoding_type = 'replace'
1101
def run(self, file_list, verbose=False, new=False,
1102
file_deletion_strategy='safe'):
1103
tree, file_list = tree_files(file_list)
1105
if file_list is not None:
1106
file_list = [f for f in file_list if f != '']
1108
raise errors.BzrCommandError('Specify one or more files to'
1109
' remove, or use --new.')
1112
added = tree.changes_from(tree.basis_tree(),
1113
specific_files=file_list).added
1114
file_list = sorted([f[0] for f in added], reverse=True)
1115
if len(file_list) == 0:
1116
raise errors.BzrCommandError('No matching files.')
1117
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1118
keep_files=file_deletion_strategy=='keep',
1119
force=file_deletion_strategy=='force')
1122
class cmd_file_id(Command):
1123
"""Print file_id of a particular file or directory.
1125
The file_id is assigned when the file is first added and remains the
1126
same through all revisions where the file exists, even when it is
1131
_see_also = ['inventory', 'ls']
1132
takes_args = ['filename']
1135
def run(self, filename):
1136
tree, relpath = WorkingTree.open_containing(filename)
1137
i = tree.path2id(relpath)
1139
raise errors.NotVersionedError(filename)
1141
self.outf.write(i + '\n')
1144
class cmd_file_path(Command):
1145
"""Print path of file_ids to a file or directory.
1147
This prints one line for each directory down to the target,
1148
starting at the branch root.
1152
takes_args = ['filename']
1155
def run(self, filename):
1156
tree, relpath = WorkingTree.open_containing(filename)
1157
fid = tree.path2id(relpath)
1159
raise errors.NotVersionedError(filename)
1160
segments = osutils.splitpath(relpath)
1161
for pos in range(1, len(segments) + 1):
1162
path = osutils.joinpath(segments[:pos])
1163
self.outf.write("%s\n" % tree.path2id(path))
1166
class cmd_reconcile(Command):
1167
"""Reconcile bzr metadata in a branch.
1169
This can correct data mismatches that may have been caused by
1170
previous ghost operations or bzr upgrades. You should only
1171
need to run this command if 'bzr check' or a bzr developer
1172
advises you to run it.
1174
If a second branch is provided, cross-branch reconciliation is
1175
also attempted, which will check that data like the tree root
1176
id which was not present in very early bzr versions is represented
1177
correctly in both branches.
1179
At the same time it is run it may recompress data resulting in
1180
a potential saving in disk space or performance gain.
1182
The branch *MUST* be on a listable system such as local disk or sftp.
1185
_see_also = ['check']
1186
takes_args = ['branch?']
1188
def run(self, branch="."):
1189
from bzrlib.reconcile import reconcile
1190
dir = bzrdir.BzrDir.open(branch)
1194
class cmd_revision_history(Command):
1195
"""Display the list of revision ids on a branch."""
1198
takes_args = ['location?']
1203
def run(self, location="."):
1204
branch = Branch.open_containing(location)[0]
1205
for revid in branch.revision_history():
1206
self.outf.write(revid)
1207
self.outf.write('\n')
1210
class cmd_ancestry(Command):
1211
"""List all revisions merged into this branch."""
1213
_see_also = ['log', 'revision-history']
1214
takes_args = ['location?']
1219
def run(self, location="."):
1221
wt = WorkingTree.open_containing(location)[0]
1222
except errors.NoWorkingTree:
1223
b = Branch.open(location)
1224
last_revision = b.last_revision()
1227
last_revision = wt.last_revision()
1229
revision_ids = b.repository.get_ancestry(last_revision)
1230
assert revision_ids[0] is None
1232
for revision_id in revision_ids:
1233
self.outf.write(revision_id + '\n')
1236
class cmd_init(Command):
1237
"""Make a directory into a versioned branch.
1239
Use this to create an empty branch, or before importing an
1242
If there is a repository in a parent directory of the location, then
1243
the history of the branch will be stored in the repository. Otherwise
1244
init creates a standalone branch which carries its own history
1245
in the .bzr directory.
1247
If there is already a branch at the location but it has no working tree,
1248
the tree can be populated with 'bzr checkout'.
1250
Recipe for importing a tree of files:
1255
bzr commit -m 'imported project'
1258
_see_also = ['init-repo', 'branch', 'checkout']
1259
takes_args = ['location?']
1261
Option('create-prefix',
1262
help='Create the path leading up to the branch '
1263
'if it does not already exist.'),
1264
RegistryOption('format',
1265
help='Specify a format for this branch. '
1266
'See "help formats".',
1267
registry=bzrdir.format_registry,
1268
converter=bzrdir.format_registry.make_bzrdir,
1269
value_switches=True,
1270
title="Branch Format",
1272
Option('append-revisions-only',
1273
help='Never change revnos or the existing log.'
1274
' Append revisions to it only.')
1276
def run(self, location=None, format=None, append_revisions_only=False,
1277
create_prefix=False):
1279
format = bzrdir.format_registry.make_bzrdir('default')
1280
if location is None:
1283
to_transport = transport.get_transport(location)
1285
# The path has to exist to initialize a
1286
# branch inside of it.
1287
# Just using os.mkdir, since I don't
1288
# believe that we want to create a bunch of
1289
# locations if the user supplies an extended path
1291
to_transport.ensure_base()
1292
except errors.NoSuchFile:
1293
if not create_prefix:
1294
raise errors.BzrCommandError("Parent directory of %s"
1296
"\nYou may supply --create-prefix to create all"
1297
" leading parent directories."
1299
_create_prefix(to_transport)
1302
existing_bzrdir = bzrdir.BzrDir.open(location)
1303
except errors.NotBranchError:
1304
# really a NotBzrDir error...
1305
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1308
from bzrlib.transport.local import LocalTransport
1309
if existing_bzrdir.has_branch():
1310
if (isinstance(to_transport, LocalTransport)
1311
and not existing_bzrdir.has_workingtree()):
1312
raise errors.BranchExistsWithoutWorkingTree(location)
1313
raise errors.AlreadyBranchError(location)
1315
branch = existing_bzrdir.create_branch()
1316
existing_bzrdir.create_workingtree()
1317
if append_revisions_only:
1319
branch.set_append_revisions_only(True)
1320
except errors.UpgradeRequired:
1321
raise errors.BzrCommandError('This branch format cannot be set'
1322
' to append-revisions-only. Try --experimental-branch6')
1325
class cmd_init_repository(Command):
1326
"""Create a shared repository to hold branches.
1328
New branches created under the repository directory will store their
1329
revisions in the repository, not in the branch directory.
1331
If the --no-trees option is used then the branches in the repository
1332
will not have working trees by default.
1335
bzr init-repo --no-trees repo
1337
bzr checkout --lightweight repo/trunk trunk-checkout
1341
See 'bzr help repositories' for more information.
1344
_see_also = ['init', 'branch', 'checkout']
1345
takes_args = ["location"]
1346
takes_options = [RegistryOption('format',
1347
help='Specify a format for this repository. See'
1348
' "bzr help formats" for details.',
1349
registry=bzrdir.format_registry,
1350
converter=bzrdir.format_registry.make_bzrdir,
1351
value_switches=True, title='Repository format'),
1353
help='Branches in the repository will default to'
1354
' not having a working tree.'),
1356
aliases = ["init-repo"]
1358
def run(self, location, format=None, no_trees=False):
1360
format = bzrdir.format_registry.make_bzrdir('default')
1362
if location is None:
1365
to_transport = transport.get_transport(location)
1366
to_transport.ensure_base()
1368
newdir = format.initialize_on_transport(to_transport)
1369
repo = newdir.create_repository(shared=True)
1370
repo.set_make_working_trees(not no_trees)
1373
class cmd_diff(Command):
1374
"""Show differences in the working tree or between revisions.
1376
If files are listed, only the changes in those files are listed.
1377
Otherwise, all changes for the tree are listed.
1379
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1380
produces patches suitable for "patch -p1".
1384
Shows the difference in the working tree versus the last commit
1386
Difference between the working tree and revision 1
1388
Difference between revision 2 and revision 1
1389
bzr diff --prefix old/:new/
1390
Same as 'bzr diff' but prefix paths with old/ and new/
1391
bzr diff bzr.mine bzr.dev
1392
Show the differences between the two working trees
1394
Show just the differences for 'foo.c'
1396
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1397
# or a graphical diff.
1399
# TODO: Python difflib is not exactly the same as unidiff; should
1400
# either fix it up or prefer to use an external diff.
1402
# TODO: Selected-file diff is inefficient and doesn't show you
1405
# TODO: This probably handles non-Unix newlines poorly.
1407
_see_also = ['status']
1408
takes_args = ['file*']
1410
Option('diff-options', type=str,
1411
help='Pass these options to the external diff program.'),
1412
Option('prefix', type=str,
1414
help='Set prefixes to added to old and new filenames, as '
1415
'two values separated by a colon. (eg "old/:new/").'),
1418
aliases = ['di', 'dif']
1419
encoding_type = 'exact'
1422
def run(self, revision=None, file_list=None, diff_options=None,
1424
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1426
if (prefix is None) or (prefix == '0'):
1434
old_label, new_label = prefix.split(":")
1436
raise errors.BzrCommandError(
1437
'--prefix expects two values separated by a colon'
1438
' (eg "old/:new/")')
1440
if revision and len(revision) > 2:
1441
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1442
' one or two revision specifiers')
1445
tree1, file_list = internal_tree_files(file_list)
1449
except errors.FileInWrongBranch:
1450
if len(file_list) != 2:
1451
raise errors.BzrCommandError("Files are in different branches")
1453
tree1, file1 = WorkingTree.open_containing(file_list[0])
1454
tree2, file2 = WorkingTree.open_containing(file_list[1])
1455
if file1 != "" or file2 != "":
1456
# FIXME diff those two files. rbc 20051123
1457
raise errors.BzrCommandError("Files are in different branches")
1459
except errors.NotBranchError:
1460
if (revision is not None and len(revision) == 2
1461
and not revision[0].needs_branch()
1462
and not revision[1].needs_branch()):
1463
# If both revision specs include a branch, we can
1464
# diff them without needing a local working tree
1465
tree1, tree2 = None, None
1469
if tree2 is not None:
1470
if revision is not None:
1471
# FIXME: but there should be a clean way to diff between
1472
# non-default versions of two trees, it's not hard to do
1474
raise errors.BzrCommandError(
1475
"Sorry, diffing arbitrary revisions across branches "
1476
"is not implemented yet")
1477
return show_diff_trees(tree1, tree2, sys.stdout,
1478
specific_files=file_list,
1479
external_diff_options=diff_options,
1480
old_label=old_label, new_label=new_label)
1482
return diff_cmd_helper(tree1, file_list, diff_options,
1483
revision_specs=revision,
1484
old_label=old_label, new_label=new_label)
1487
class cmd_deleted(Command):
1488
"""List files deleted in the working tree.
1490
# TODO: Show files deleted since a previous revision, or
1491
# between two revisions.
1492
# TODO: Much more efficient way to do this: read in new
1493
# directories with readdir, rather than stating each one. Same
1494
# level of effort but possibly much less IO. (Or possibly not,
1495
# if the directories are very large...)
1496
_see_also = ['status', 'ls']
1497
takes_options = ['show-ids']
1500
def run(self, show_ids=False):
1501
tree = WorkingTree.open_containing(u'.')[0]
1504
old = tree.basis_tree()
1507
for path, ie in old.inventory.iter_entries():
1508
if not tree.has_id(ie.file_id):
1509
self.outf.write(path)
1511
self.outf.write(' ')
1512
self.outf.write(ie.file_id)
1513
self.outf.write('\n')
1520
class cmd_modified(Command):
1521
"""List files modified in working tree.
1525
_see_also = ['status', 'ls']
1529
tree = WorkingTree.open_containing(u'.')[0]
1530
td = tree.changes_from(tree.basis_tree())
1531
for path, id, kind, text_modified, meta_modified in td.modified:
1532
self.outf.write(path + '\n')
1535
class cmd_added(Command):
1536
"""List files added in working tree.
1540
_see_also = ['status', 'ls']
1544
wt = WorkingTree.open_containing(u'.')[0]
1547
basis = wt.basis_tree()
1550
basis_inv = basis.inventory
1553
if file_id in basis_inv:
1555
if inv.is_root(file_id) and len(basis_inv) == 0:
1557
path = inv.id2path(file_id)
1558
if not os.access(osutils.abspath(path), os.F_OK):
1560
self.outf.write(path + '\n')
1567
class cmd_root(Command):
1568
"""Show the tree root directory.
1570
The root is the nearest enclosing directory with a .bzr control
1573
takes_args = ['filename?']
1575
def run(self, filename=None):
1576
"""Print the branch root."""
1577
tree = WorkingTree.open_containing(filename)[0]
1578
self.outf.write(tree.basedir + '\n')
1581
def _parse_limit(limitstring):
1583
return int(limitstring)
1585
msg = "The limit argument must be an integer."
1586
raise errors.BzrCommandError(msg)
1589
class cmd_log(Command):
1590
"""Show log of a branch, file, or directory.
1592
By default show the log of the branch containing the working directory.
1594
To request a range of logs, you can use the command -r begin..end
1595
-r revision requests a specific revision, -r ..end or -r begin.. are
1601
bzr log -r -10.. http://server/branch
1604
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1606
takes_args = ['location?']
1609
help='Show from oldest to newest.'),
1612
help='Display timezone as local, original, or utc.'),
1615
help='Show files changed in each revision.'),
1621
help='Show revisions whose message matches this '
1622
'regular expression.',
1625
help='Limit the output to the first N revisions.',
1629
encoding_type = 'replace'
1632
def run(self, location=None, timezone='original',
1640
from bzrlib.log import show_log
1641
assert message is None or isinstance(message, basestring), \
1642
"invalid message argument %r" % message
1643
direction = (forward and 'forward') or 'reverse'
1648
# find the file id to log:
1650
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1654
tree = b.basis_tree()
1655
file_id = tree.path2id(fp)
1657
raise errors.BzrCommandError(
1658
"Path does not have any revision history: %s" %
1662
# FIXME ? log the current subdir only RBC 20060203
1663
if revision is not None \
1664
and len(revision) > 0 and revision[0].get_branch():
1665
location = revision[0].get_branch()
1668
dir, relpath = bzrdir.BzrDir.open_containing(location)
1669
b = dir.open_branch()
1673
if revision is None:
1676
elif len(revision) == 1:
1677
rev1 = rev2 = revision[0].in_history(b)
1678
elif len(revision) == 2:
1679
if revision[1].get_branch() != revision[0].get_branch():
1680
# b is taken from revision[0].get_branch(), and
1681
# show_log will use its revision_history. Having
1682
# different branches will lead to weird behaviors.
1683
raise errors.BzrCommandError(
1684
"Log doesn't accept two revisions in different"
1686
rev1 = revision[0].in_history(b)
1687
rev2 = revision[1].in_history(b)
1689
raise errors.BzrCommandError(
1690
'bzr log --revision takes one or two values.')
1692
if log_format is None:
1693
log_format = log.log_formatter_registry.get_default(b)
1695
lf = log_format(show_ids=show_ids, to_file=self.outf,
1696
show_timezone=timezone)
1702
direction=direction,
1703
start_revision=rev1,
1711
def get_log_format(long=False, short=False, line=False, default='long'):
1712
log_format = default
1716
log_format = 'short'
1722
class cmd_touching_revisions(Command):
1723
"""Return revision-ids which affected a particular file.
1725
A more user-friendly interface is "bzr log FILE".
1729
takes_args = ["filename"]
1732
def run(self, filename):
1733
tree, relpath = WorkingTree.open_containing(filename)
1735
file_id = tree.path2id(relpath)
1736
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1737
self.outf.write("%6d %s\n" % (revno, what))
1740
class cmd_ls(Command):
1741
"""List files in a tree.
1744
_see_also = ['status', 'cat']
1745
takes_args = ['path?']
1746
# TODO: Take a revision or remote path and list that tree instead.
1750
Option('non-recursive',
1751
help='Don\'t recurse into subdirectories.'),
1753
help='Print paths relative to the root of the branch.'),
1754
Option('unknown', help='Print unknown files.'),
1755
Option('versioned', help='Print versioned files.'),
1756
Option('ignored', help='Print ignored files.'),
1758
help='Write an ascii NUL (\\0) separator '
1759
'between files rather than a newline.'),
1761
help='List entries of a particular kind: file, directory, symlink.',
1766
def run(self, revision=None, verbose=False,
1767
non_recursive=False, from_root=False,
1768
unknown=False, versioned=False, ignored=False,
1769
null=False, kind=None, show_ids=False, path=None):
1771
if kind and kind not in ('file', 'directory', 'symlink'):
1772
raise errors.BzrCommandError('invalid kind specified')
1774
if verbose and null:
1775
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1776
all = not (unknown or versioned or ignored)
1778
selection = {'I':ignored, '?':unknown, 'V':versioned}
1785
raise errors.BzrCommandError('cannot specify both --from-root'
1789
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1795
if revision is not None:
1796
tree = branch.repository.revision_tree(
1797
revision[0].in_history(branch).rev_id)
1799
tree = branch.basis_tree()
1803
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1804
if fp.startswith(relpath):
1805
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1806
if non_recursive and '/' in fp:
1808
if not all and not selection[fc]:
1810
if kind is not None and fkind != kind:
1813
kindch = entry.kind_character()
1814
outstring = '%-8s %s%s' % (fc, fp, kindch)
1815
if show_ids and fid is not None:
1816
outstring = "%-50s %s" % (outstring, fid)
1817
self.outf.write(outstring + '\n')
1819
self.outf.write(fp + '\0')
1822
self.outf.write(fid)
1823
self.outf.write('\0')
1831
self.outf.write('%-50s %s\n' % (fp, my_id))
1833
self.outf.write(fp + '\n')
1838
class cmd_unknowns(Command):
1839
"""List unknown files.
1847
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1848
self.outf.write(osutils.quotefn(f) + '\n')
1851
class cmd_ignore(Command):
1852
"""Ignore specified files or patterns.
1854
To remove patterns from the ignore list, edit the .bzrignore file.
1856
Trailing slashes on patterns are ignored.
1857
If the pattern contains a slash or is a regular expression, it is compared
1858
to the whole path from the branch root. Otherwise, it is compared to only
1859
the last component of the path. To match a file only in the root
1860
directory, prepend './'.
1862
Ignore patterns specifying absolute paths are not allowed.
1864
Ignore patterns may include globbing wildcards such as:
1865
? - Matches any single character except '/'
1866
* - Matches 0 or more characters except '/'
1867
/**/ - Matches 0 or more directories in a path
1868
[a-z] - Matches a single character from within a group of characters
1870
Ignore patterns may also be Python regular expressions.
1871
Regular expression ignore patterns are identified by a 'RE:' prefix
1872
followed by the regular expression. Regular expression ignore patterns
1873
may not include named or numbered groups.
1875
Note: ignore patterns containing shell wildcards must be quoted from
1879
bzr ignore ./Makefile
1880
bzr ignore '*.class'
1881
bzr ignore 'lib/**/*.o'
1882
bzr ignore 'RE:lib/.*\.o'
1885
_see_also = ['status', 'ignored']
1886
takes_args = ['name_pattern*']
1888
Option('old-default-rules',
1889
help='Write out the ignore rules bzr < 0.9 always used.')
1892
def run(self, name_pattern_list=None, old_default_rules=None):
1893
from bzrlib.atomicfile import AtomicFile
1894
if old_default_rules is not None:
1895
# dump the rules and exit
1896
for pattern in ignores.OLD_DEFAULTS:
1899
if not name_pattern_list:
1900
raise errors.BzrCommandError("ignore requires at least one "
1901
"NAME_PATTERN or --old-default-rules")
1902
name_pattern_list = [globbing.normalize_pattern(p)
1903
for p in name_pattern_list]
1904
for name_pattern in name_pattern_list:
1905
if (name_pattern[0] == '/' or
1906
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1907
raise errors.BzrCommandError(
1908
"NAME_PATTERN should not be an absolute path")
1909
tree, relpath = WorkingTree.open_containing(u'.')
1910
ifn = tree.abspath('.bzrignore')
1911
if os.path.exists(ifn):
1914
igns = f.read().decode('utf-8')
1920
# TODO: If the file already uses crlf-style termination, maybe
1921
# we should use that for the newly added lines?
1923
if igns and igns[-1] != '\n':
1925
for name_pattern in name_pattern_list:
1926
igns += name_pattern + '\n'
1928
f = AtomicFile(ifn, 'wb')
1930
f.write(igns.encode('utf-8'))
1935
if not tree.path2id('.bzrignore'):
1936
tree.add(['.bzrignore'])
1939
class cmd_ignored(Command):
1940
"""List ignored files and the patterns that matched them.
1943
_see_also = ['ignore']
1946
tree = WorkingTree.open_containing(u'.')[0]
1949
for path, file_class, kind, file_id, entry in tree.list_files():
1950
if file_class != 'I':
1952
## XXX: Slightly inefficient since this was already calculated
1953
pat = tree.is_ignored(path)
1954
print '%-50s %s' % (path, pat)
1959
class cmd_lookup_revision(Command):
1960
"""Lookup the revision-id from a revision-number
1963
bzr lookup-revision 33
1966
takes_args = ['revno']
1969
def run(self, revno):
1973
raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1975
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1978
class cmd_export(Command):
1979
"""Export current or past revision to a destination directory or archive.
1981
If no revision is specified this exports the last committed revision.
1983
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1984
given, try to find the format with the extension. If no extension
1985
is found exports to a directory (equivalent to --format=dir).
1987
If root is supplied, it will be used as the root directory inside
1988
container formats (tar, zip, etc). If it is not supplied it will default
1989
to the exported filename. The root option has no effect for 'dir' format.
1991
If branch is omitted then the branch containing the current working
1992
directory will be used.
1994
Note: Export of tree with non-ASCII filenames to zip is not supported.
1996
Supported formats Autodetected by extension
1997
----------------- -------------------------
2000
tbz2 .tar.bz2, .tbz2
2004
takes_args = ['dest', 'branch?']
2007
help="Type of file to export to.",
2012
help="Name of the root directory inside the exported file."),
2014
def run(self, dest, branch=None, revision=None, format=None, root=None):
2015
from bzrlib.export import export
2018
tree = WorkingTree.open_containing(u'.')[0]
2021
b = Branch.open(branch)
2023
if revision is None:
2024
# should be tree.last_revision FIXME
2025
rev_id = b.last_revision()
2027
if len(revision) != 1:
2028
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2029
rev_id = revision[0].in_history(b).rev_id
2030
t = b.repository.revision_tree(rev_id)
2032
export(t, dest, format, root)
2033
except errors.NoSuchExportFormat, e:
2034
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2037
class cmd_cat(Command):
2038
"""Write the contents of a file as of a given revision to standard output.
2040
If no revision is nominated, the last revision is used.
2042
Note: Take care to redirect standard output when using this command on a
2048
Option('name-from-revision', help='The path name in the old tree.'),
2051
takes_args = ['filename']
2052
encoding_type = 'exact'
2055
def run(self, filename, revision=None, name_from_revision=False):
2056
if revision is not None and len(revision) != 1:
2057
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2062
tree, b, relpath = \
2063
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2064
except errors.NotBranchError:
2067
if revision is not None and revision[0].get_branch() is not None:
2068
b = Branch.open(revision[0].get_branch())
2070
tree = b.basis_tree()
2071
if revision is None:
2072
revision_id = b.last_revision()
2074
revision_id = revision[0].in_history(b).rev_id
2076
cur_file_id = tree.path2id(relpath)
2077
rev_tree = b.repository.revision_tree(revision_id)
2078
old_file_id = rev_tree.path2id(relpath)
2080
if name_from_revision:
2081
if old_file_id is None:
2082
raise errors.BzrCommandError("%r is not present in revision %s"
2083
% (filename, revision_id))
2085
rev_tree.print_file(old_file_id)
2086
elif cur_file_id is not None:
2087
rev_tree.print_file(cur_file_id)
2088
elif old_file_id is not None:
2089
rev_tree.print_file(old_file_id)
2091
raise errors.BzrCommandError("%r is not present in revision %s" %
2092
(filename, revision_id))
2095
class cmd_local_time_offset(Command):
2096
"""Show the offset in seconds from GMT to local time."""
2100
print osutils.local_time_offset()
2104
class cmd_commit(Command):
2105
"""Commit changes into a new revision.
2107
If no arguments are given, the entire tree is committed.
2109
If selected files are specified, only changes to those files are
2110
committed. If a directory is specified then the directory and everything
2111
within it is committed.
2113
A selected-file commit may fail in some cases where the committed
2114
tree would be invalid. Consider::
2119
bzr commit foo -m "committing foo"
2120
bzr mv foo/bar foo/baz
2123
bzr commit foo/bar -m "committing bar but not baz"
2125
In the example above, the last commit will fail by design. This gives
2126
the user the opportunity to decide whether they want to commit the
2127
rename at the same time, separately first, or not at all. (As a general
2128
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2130
Note: A selected-file commit after a merge is not yet supported.
2132
# TODO: Run hooks on tree to-be-committed, and after commit.
2134
# TODO: Strict commit that fails if there are deleted files.
2135
# (what does "deleted files" mean ??)
2137
# TODO: Give better message for -s, --summary, used by tla people
2139
# XXX: verbose currently does nothing
2141
_see_also = ['bugs', 'uncommit']
2142
takes_args = ['selected*']
2144
Option('message', type=unicode,
2146
help="Description of the new revision."),
2149
help='Commit even if nothing has changed.'),
2150
Option('file', type=str,
2153
help='Take commit message from this file.'),
2155
help="Refuse to commit if there are unknown "
2156
"files in the working tree."),
2157
ListOption('fixes', type=str,
2158
help="Mark a bug as being fixed by this revision."),
2160
help="Perform a local commit in a bound "
2161
"branch. Local commits are not pushed to "
2162
"the master branch until a normal commit "
2166
aliases = ['ci', 'checkin']
2168
def _get_bug_fix_properties(self, fixes, branch):
2170
# Configure the properties for bug fixing attributes.
2171
for fixed_bug in fixes:
2172
tokens = fixed_bug.split(':')
2173
if len(tokens) != 2:
2174
raise errors.BzrCommandError(
2175
"Invalid bug %s. Must be in the form of 'tag:id'. "
2176
"Commit refused." % fixed_bug)
2177
tag, bug_id = tokens
2179
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2180
except errors.UnknownBugTrackerAbbreviation:
2181
raise errors.BzrCommandError(
2182
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2183
except errors.MalformedBugIdentifier:
2184
raise errors.BzrCommandError(
2185
"Invalid bug identifier for %s. Commit refused."
2187
properties.append('%s fixed' % bug_url)
2188
return '\n'.join(properties)
2190
def run(self, message=None, file=None, verbose=True, selected_list=None,
2191
unchanged=False, strict=False, local=False, fixes=None):
2192
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2193
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2195
from bzrlib.msgeditor import edit_commit_message, \
2196
make_commit_message_template
2198
# TODO: Need a blackbox test for invoking the external editor; may be
2199
# slightly problematic to run this cross-platform.
2201
# TODO: do more checks that the commit will succeed before
2202
# spending the user's valuable time typing a commit message.
2206
tree, selected_list = tree_files(selected_list)
2207
if selected_list == ['']:
2208
# workaround - commit of root of tree should be exactly the same
2209
# as just default commit in that tree, and succeed even though
2210
# selected-file merge commit is not done yet
2213
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2215
properties['bugs'] = bug_property
2217
if local and not tree.branch.get_bound_location():
2218
raise errors.LocalRequiresBoundBranch()
2220
def get_message(commit_obj):
2221
"""Callback to get commit message"""
2222
my_message = message
2223
if my_message is None and not file:
2224
template = make_commit_message_template(tree, selected_list)
2225
my_message = edit_commit_message(template)
2226
if my_message is None:
2227
raise errors.BzrCommandError("please specify a commit"
2228
" message with either --message or --file")
2229
elif my_message and file:
2230
raise errors.BzrCommandError(
2231
"please specify either --message or --file")
2233
my_message = codecs.open(file, 'rt',
2234
bzrlib.user_encoding).read()
2235
if my_message == "":
2236
raise errors.BzrCommandError("empty commit message specified")
2240
reporter = ReportCommitToLog()
2242
reporter = NullCommitReporter()
2245
tree.commit(message_callback=get_message,
2246
specific_files=selected_list,
2247
allow_pointless=unchanged, strict=strict, local=local,
2248
reporter=reporter, revprops=properties)
2249
except PointlessCommit:
2250
# FIXME: This should really happen before the file is read in;
2251
# perhaps prepare the commit; get the message; then actually commit
2252
raise errors.BzrCommandError("no changes to commit."
2253
" use --unchanged to commit anyhow")
2254
except ConflictsInTree:
2255
raise errors.BzrCommandError('Conflicts detected in working '
2256
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
2258
except StrictCommitFailed:
2259
raise errors.BzrCommandError("Commit refused because there are"
2260
" unknown files in the working tree.")
2261
except errors.BoundBranchOutOfDate, e:
2262
raise errors.BzrCommandError(str(e) + "\n"
2263
'To commit to master branch, run update and then commit.\n'
2264
'You can also pass --local to commit to continue working '
2268
class cmd_check(Command):
2269
"""Validate consistency of branch history.
2271
This command checks various invariants about the branch storage to
2272
detect data corruption or bzr bugs.
2275
_see_also = ['reconcile']
2276
takes_args = ['branch?']
2277
takes_options = ['verbose']
2279
def run(self, branch=None, verbose=False):
2280
from bzrlib.check import check
2282
tree = WorkingTree.open_containing()[0]
2283
branch = tree.branch
2285
branch = Branch.open(branch)
2286
check(branch, verbose)
2289
class cmd_upgrade(Command):
2290
"""Upgrade branch storage to current format.
2292
The check command or bzr developers may sometimes advise you to run
2293
this command. When the default format has changed you may also be warned
2294
during other operations to upgrade.
2297
_see_also = ['check']
2298
takes_args = ['url?']
2300
RegistryOption('format',
2301
help='Upgrade to a specific format. See "bzr help'
2302
' formats" for details.',
2303
registry=bzrdir.format_registry,
2304
converter=bzrdir.format_registry.make_bzrdir,
2305
value_switches=True, title='Branch format'),
2308
def run(self, url='.', format=None):
2309
from bzrlib.upgrade import upgrade
2311
format = bzrdir.format_registry.make_bzrdir('default')
2312
upgrade(url, format)
2315
class cmd_whoami(Command):
2316
"""Show or set bzr user id.
2320
bzr whoami 'Frank Chu <fchu@example.com>'
2322
takes_options = [ Option('email',
2323
help='Display email address only.'),
2325
help='Set identity for the current branch instead of '
2328
takes_args = ['name?']
2329
encoding_type = 'replace'
2332
def run(self, email=False, branch=False, name=None):
2334
# use branch if we're inside one; otherwise global config
2336
c = Branch.open_containing('.')[0].get_config()
2337
except errors.NotBranchError:
2338
c = config.GlobalConfig()
2340
self.outf.write(c.user_email() + '\n')
2342
self.outf.write(c.username() + '\n')
2345
# display a warning if an email address isn't included in the given name.
2347
config.extract_email_address(name)
2348
except errors.NoEmailInUsername, e:
2349
warning('"%s" does not seem to contain an email address. '
2350
'This is allowed, but not recommended.', name)
2352
# use global config unless --branch given
2354
c = Branch.open_containing('.')[0].get_config()
2356
c = config.GlobalConfig()
2357
c.set_user_option('email', name)
2360
class cmd_nick(Command):
2361
"""Print or set the branch nickname.
2363
If unset, the tree root directory name is used as the nickname
2364
To print the current nickname, execute with no argument.
2367
_see_also = ['info']
2368
takes_args = ['nickname?']
2369
def run(self, nickname=None):
2370
branch = Branch.open_containing(u'.')[0]
2371
if nickname is None:
2372
self.printme(branch)
2374
branch.nick = nickname
2377
def printme(self, branch):
2381
class cmd_selftest(Command):
2382
"""Run internal test suite.
2384
If arguments are given, they are regular expressions that say which tests
2385
should run. Tests matching any expression are run, and other tests are
2388
Alternatively if --first is given, matching tests are run first and then
2389
all other tests are run. This is useful if you have been working in a
2390
particular area, but want to make sure nothing else was broken.
2392
If --exclude is given, tests that match that regular expression are
2393
excluded, regardless of whether they match --first or not.
2395
To help catch accidential dependencies between tests, the --randomize
2396
option is useful. In most cases, the argument used is the word 'now'.
2397
Note that the seed used for the random number generator is displayed
2398
when this option is used. The seed can be explicitly passed as the
2399
argument to this option if required. This enables reproduction of the
2400
actual ordering used if and when an order sensitive problem is encountered.
2402
If --list-only is given, the tests that would be run are listed. This is
2403
useful when combined with --first, --exclude and/or --randomize to
2404
understand their impact. The test harness reports "Listed nn tests in ..."
2405
instead of "Ran nn tests in ..." when list mode is enabled.
2407
If the global option '--no-plugins' is given, plugins are not loaded
2408
before running the selftests. This has two effects: features provided or
2409
modified by plugins will not be tested, and tests provided by plugins will
2412
Tests that need working space on disk use a common temporary directory,
2413
typically inside $TMPDIR or /tmp.
2417
run only tests relating to 'ignore'
2418
bzr --no-plugins selftest -v
2419
disable plugins and list tests as they're run
2421
# NB: this is used from the class without creating an instance, which is
2422
# why it does not have a self parameter.
2423
def get_transport_type(typestring):
2424
"""Parse and return a transport specifier."""
2425
if typestring == "sftp":
2426
from bzrlib.transport.sftp import SFTPAbsoluteServer
2427
return SFTPAbsoluteServer
2428
if typestring == "memory":
2429
from bzrlib.transport.memory import MemoryServer
2431
if typestring == "fakenfs":
2432
from bzrlib.transport.fakenfs import FakeNFSServer
2433
return FakeNFSServer
2434
msg = "No known transport type %s. Supported types are: sftp\n" %\
2436
raise errors.BzrCommandError(msg)
2439
takes_args = ['testspecs*']
2440
takes_options = ['verbose',
2442
help='Stop when one test fails.',
2446
help='Use a different transport by default '
2447
'throughout the test suite.',
2448
type=get_transport_type),
2450
help='Run the benchmarks rather than selftests.'),
2451
Option('lsprof-timed',
2452
help='Generate lsprof output for benchmarked'
2453
' sections of code.'),
2454
Option('cache-dir', type=str,
2455
help='Cache intermediate benchmark output in this '
2458
help='Run all tests, but run specified tests first.',
2462
help='List the tests instead of running them.'),
2463
Option('randomize', type=str, argname="SEED",
2464
help='Randomize the order of tests using the given'
2465
' seed or "now" for the current time.'),
2466
Option('exclude', type=str, argname="PATTERN",
2468
help='Exclude tests that match this regular'
2471
encoding_type = 'replace'
2473
def run(self, testspecs_list=None, verbose=None, one=False,
2474
transport=None, benchmark=None,
2475
lsprof_timed=None, cache_dir=None,
2476
first=False, list_only=False,
2477
randomize=None, exclude=None):
2479
from bzrlib.tests import selftest
2480
import bzrlib.benchmarks as benchmarks
2481
from bzrlib.benchmarks import tree_creator
2482
from bzrlib.version import show_version
2484
if cache_dir is not None:
2485
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2487
show_version(show_config=False, show_copyright=False)
2489
if testspecs_list is not None:
2490
pattern = '|'.join(testspecs_list)
2494
test_suite_factory = benchmarks.test_suite
2497
# TODO: should possibly lock the history file...
2498
benchfile = open(".perf_history", "at", buffering=1)
2500
test_suite_factory = None
2505
result = selftest(verbose=verbose,
2507
stop_on_failure=one,
2508
transport=transport,
2509
test_suite_factory=test_suite_factory,
2510
lsprof_timed=lsprof_timed,
2511
bench_history=benchfile,
2512
matching_tests_first=first,
2513
list_only=list_only,
2514
random_seed=randomize,
2515
exclude_pattern=exclude
2518
if benchfile is not None:
2521
info('tests passed')
2523
info('tests failed')
2524
return int(not result)
2527
class cmd_version(Command):
2528
"""Show version of bzr."""
2532
from bzrlib.version import show_version
2536
class cmd_rocks(Command):
2537
"""Statement of optimism."""
2543
print "It sure does!"
2546
class cmd_find_merge_base(Command):
2547
"""Find and print a base revision for merging two branches."""
2548
# TODO: Options to specify revisions on either side, as if
2549
# merging only part of the history.
2550
takes_args = ['branch', 'other']
2554
def run(self, branch, other):
2555
from bzrlib.revision import ensure_null, MultipleRevisionSources
2557
branch1 = Branch.open_containing(branch)[0]
2558
branch2 = Branch.open_containing(other)[0]
2560
last1 = ensure_null(branch1.last_revision())
2561
last2 = ensure_null(branch2.last_revision())
2563
graph = branch1.repository.get_graph(branch2.repository)
2564
base_rev_id = graph.find_unique_lca(last1, last2)
2566
print 'merge base is revision %s' % base_rev_id
2569
class cmd_merge(Command):
2570
"""Perform a three-way merge.
2572
The branch is the branch you will merge from. By default, it will merge
2573
the latest revision. If you specify a revision, that revision will be
2574
merged. If you specify two revisions, the first will be used as a BASE,
2575
and the second one as OTHER. Revision numbers are always relative to the
2578
By default, bzr will try to merge in all new work from the other
2579
branch, automatically determining an appropriate base. If this
2580
fails, you may need to give an explicit base.
2582
Merge will do its best to combine the changes in two branches, but there
2583
are some kinds of problems only a human can fix. When it encounters those,
2584
it will mark a conflict. A conflict means that you need to fix something,
2585
before you should commit.
2587
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2589
If there is no default branch set, the first merge will set it. After
2590
that, you can omit the branch to use the default. To change the
2591
default, use --remember. The value will only be saved if the remote
2592
location can be accessed.
2594
The results of the merge are placed into the destination working
2595
directory, where they can be reviewed (with bzr diff), tested, and then
2596
committed to record the result of the merge.
2600
To merge the latest revision from bzr.dev:
2601
bzr merge ../bzr.dev
2603
To merge changes up to and including revision 82 from bzr.dev:
2604
bzr merge -r 82 ../bzr.dev
2606
To merge the changes introduced by 82, without previous changes:
2607
bzr merge -r 81..82 ../bzr.dev
2609
merge refuses to run if there are any uncommitted changes, unless
2613
_see_also = ['update', 'remerge', 'status-flags']
2614
takes_args = ['branch?']
2618
help='Merge even if the destination tree has uncommitted changes.'),
2622
Option('show-base', help="Show base revision text in "
2624
Option('uncommitted', help='Apply uncommitted changes'
2625
' from a working copy, instead of branch changes.'),
2626
Option('pull', help='If the destination is already'
2627
' completely merged into the source, pull from the'
2628
' source rather than merging. When this happens,'
2629
' you do not need to commit the result.'),
2631
help='Branch to merge into, '
2632
'rather than the one containing the working directory.',
2638
def run(self, branch=None, revision=None, force=False, merge_type=None,
2639
show_base=False, reprocess=False, remember=False,
2640
uncommitted=False, pull=False,
2643
from bzrlib.tag import _merge_tags_if_possible
2644
other_revision_id = None
2645
base_revision_id = None
2646
if merge_type is None:
2647
merge_type = _mod_merge.Merge3Merger
2649
if directory is None: directory = u'.'
2650
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2651
# inventory. Because merge is a mutating operation, it really
2652
# should be a lock_write() for the whole cmd_merge operation.
2653
# However, cmd_merge open's its own tree in _merge_helper, which
2654
# means if we lock here, the later lock_write() will always block.
2655
# Either the merge helper code should be updated to take a tree,
2656
# (What about tree.merge_from_branch?)
2657
tree = WorkingTree.open_containing(directory)[0]
2658
change_reporter = delta._ChangeReporter(
2659
unversioned_filter=tree.is_ignored)
2661
if branch is not None:
2663
mergeable = bundle.read_mergeable_from_url(
2665
except errors.NotABundle:
2666
pass # Continue on considering this url a Branch
2668
if revision is not None:
2669
raise errors.BzrCommandError(
2670
'Cannot use -r with merge directives or bundles')
2671
mergeable.install_revisions(tree.branch.repository)
2672
base_revision_id, other_revision_id, verified =\
2673
mergeable.get_merge_request(tree.branch.repository)
2674
if base_revision_id in tree.branch.repository.get_ancestry(
2675
tree.branch.last_revision(), topo_sorted=False):
2676
base_revision_id = None
2682
if other_revision_id is None:
2683
verified = 'inapplicable'
2684
if revision is None \
2685
or len(revision) < 1 or revision[0].needs_branch():
2686
branch = self._get_remembered_parent(tree, branch,
2689
if revision is None or len(revision) < 1:
2692
other = [branch, None]
2695
other = [branch, -1]
2696
other_branch, path = Branch.open_containing(branch)
2699
raise errors.BzrCommandError('Cannot use --uncommitted and'
2700
' --revision at the same time.')
2701
branch = revision[0].get_branch() or branch
2702
if len(revision) == 1:
2704
other_branch, path = Branch.open_containing(branch)
2705
revno = revision[0].in_history(other_branch).revno
2706
other = [branch, revno]
2708
assert len(revision) == 2
2709
if None in revision:
2710
raise errors.BzrCommandError(
2711
"Merge doesn't permit empty revision specifier.")
2712
base_branch, path = Branch.open_containing(branch)
2713
branch1 = revision[1].get_branch() or branch
2714
other_branch, path1 = Branch.open_containing(branch1)
2715
if revision[0].get_branch() is not None:
2716
# then path was obtained from it, and is None.
2719
base = [branch, revision[0].in_history(base_branch).revno]
2721
revision[1].in_history(other_branch).revno]
2723
if ((tree.branch.get_parent() is None or remember) and
2724
other_branch is not None):
2725
tree.branch.set_parent(other_branch.base)
2727
# pull tags now... it's a bit inconsistent to do it ahead of copying
2728
# the history but that's done inside the merge code
2729
if other_branch is not None:
2730
_merge_tags_if_possible(other_branch, tree.branch)
2733
interesting_files = [path]
2735
interesting_files = None
2736
pb = ui.ui_factory.nested_progress_bar()
2739
conflict_count = _merge_helper(
2740
other, base, other_rev_id=other_revision_id,
2741
base_rev_id=base_revision_id,
2742
check_clean=(not force),
2743
merge_type=merge_type,
2744
reprocess=reprocess,
2745
show_base=show_base,
2748
pb=pb, file_list=interesting_files,
2749
change_reporter=change_reporter)
2752
if verified == 'failed':
2753
warning('Preview patch does not match changes')
2754
if conflict_count != 0:
2758
except errors.AmbiguousBase, e:
2759
m = ("sorry, bzr can't determine the right merge base yet\n"
2760
"candidates are:\n "
2761
+ "\n ".join(e.bases)
2763
"please specify an explicit base with -r,\n"
2764
"and (if you want) report this to the bzr developers\n")
2767
# TODO: move up to common parent; this isn't merge-specific anymore.
2768
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2769
"""Use tree.branch's parent if none was supplied.
2771
Report if the remembered location was used.
2773
if supplied_location is not None:
2774
return supplied_location
2775
stored_location = tree.branch.get_parent()
2776
mutter("%s", stored_location)
2777
if stored_location is None:
2778
raise errors.BzrCommandError("No location specified or remembered")
2779
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2780
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2781
return stored_location
2784
class cmd_remerge(Command):
2787
Use this if you want to try a different merge technique while resolving
2788
conflicts. Some merge techniques are better than others, and remerge
2789
lets you try different ones on different files.
2791
The options for remerge have the same meaning and defaults as the ones for
2792
merge. The difference is that remerge can (only) be run when there is a
2793
pending merge, and it lets you specify particular files.
2797
$ bzr remerge --show-base
2798
Re-do the merge of all conflicted files, and show the base text in
2799
conflict regions, in addition to the usual THIS and OTHER texts.
2801
$ bzr remerge --merge-type weave --reprocess foobar
2802
Re-do the merge of "foobar", using the weave merge algorithm, with
2803
additional processing to reduce the size of conflict regions.
2805
takes_args = ['file*']
2810
help="Show base revision text in conflicts."),
2813
def run(self, file_list=None, merge_type=None, show_base=False,
2815
if merge_type is None:
2816
merge_type = _mod_merge.Merge3Merger
2817
tree, file_list = tree_files(file_list)
2820
parents = tree.get_parent_ids()
2821
if len(parents) != 2:
2822
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2823
" merges. Not cherrypicking or"
2825
repository = tree.branch.repository
2826
graph = repository.get_graph()
2827
base_revision = graph.find_unique_lca(parents[0], parents[1])
2828
base_tree = repository.revision_tree(base_revision)
2829
other_tree = repository.revision_tree(parents[1])
2830
interesting_ids = None
2832
conflicts = tree.conflicts()
2833
if file_list is not None:
2834
interesting_ids = set()
2835
for filename in file_list:
2836
file_id = tree.path2id(filename)
2838
raise errors.NotVersionedError(filename)
2839
interesting_ids.add(file_id)
2840
if tree.kind(file_id) != "directory":
2843
for name, ie in tree.inventory.iter_entries(file_id):
2844
interesting_ids.add(ie.file_id)
2845
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2847
# Remerge only supports resolving contents conflicts
2848
allowed_conflicts = ('text conflict', 'contents conflict')
2849
restore_files = [c.path for c in conflicts
2850
if c.typestring in allowed_conflicts]
2851
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2852
tree.set_conflicts(ConflictList(new_conflicts))
2853
if file_list is not None:
2854
restore_files = file_list
2855
for filename in restore_files:
2857
restore(tree.abspath(filename))
2858
except errors.NotConflicted:
2860
conflicts = _mod_merge.merge_inner(
2861
tree.branch, other_tree, base_tree,
2863
interesting_ids=interesting_ids,
2864
other_rev_id=parents[1],
2865
merge_type=merge_type,
2866
show_base=show_base,
2867
reprocess=reprocess)
2876
class cmd_revert(Command):
2877
"""Revert files to a previous revision.
2879
Giving a list of files will revert only those files. Otherwise, all files
2880
will be reverted. If the revision is not specified with '--revision', the
2881
last committed revision is used.
2883
To remove only some changes, without reverting to a prior version, use
2884
merge instead. For example, "merge . --r-2..-3" will remove the changes
2885
introduced by -2, without affecting the changes introduced by -1. Or
2886
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2888
By default, any files that have been manually changed will be backed up
2889
first. (Files changed only by merge are not backed up.) Backup files have
2890
'.~#~' appended to their name, where # is a number.
2892
When you provide files, you can use their current pathname or the pathname
2893
from the target revision. So you can use revert to "undelete" a file by
2894
name. If you name a directory, all the contents of that directory will be
2898
_see_also = ['cat', 'export']
2901
Option('no-backup', "Do not save backups of reverted files."),
2903
takes_args = ['file*']
2905
def run(self, revision=None, no_backup=False, file_list=None):
2906
if file_list is not None:
2907
if len(file_list) == 0:
2908
raise errors.BzrCommandError("No files specified")
2912
tree, file_list = tree_files(file_list)
2913
if revision is None:
2914
# FIXME should be tree.last_revision
2915
rev_id = tree.last_revision()
2916
elif len(revision) != 1:
2917
raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2919
rev_id = revision[0].in_history(tree.branch).rev_id
2920
pb = ui.ui_factory.nested_progress_bar()
2922
tree.revert(file_list,
2923
tree.branch.repository.revision_tree(rev_id),
2924
not no_backup, pb, report_changes=True)
2929
class cmd_assert_fail(Command):
2930
"""Test reporting of assertion failures"""
2931
# intended just for use in testing
2936
raise AssertionError("always fails")
2939
class cmd_help(Command):
2940
"""Show help on a command or other topic.
2943
_see_also = ['topics']
2945
Option('long', 'Show help on all commands.'),
2947
takes_args = ['topic?']
2948
aliases = ['?', '--help', '-?', '-h']
2951
def run(self, topic=None, long=False):
2953
if topic is None and long:
2955
bzrlib.help.help(topic)
2958
class cmd_shell_complete(Command):
2959
"""Show appropriate completions for context.
2961
For a list of all available commands, say 'bzr shell-complete'.
2963
takes_args = ['context?']
2968
def run(self, context=None):
2969
import shellcomplete
2970
shellcomplete.shellcomplete(context)
2973
class cmd_fetch(Command):
2974
"""Copy in history from another branch but don't merge it.
2976
This is an internal method used for pull and merge.
2979
takes_args = ['from_branch', 'to_branch']
2980
def run(self, from_branch, to_branch):
2981
from bzrlib.fetch import Fetcher
2982
from_b = Branch.open(from_branch)
2983
to_b = Branch.open(to_branch)
2984
Fetcher(to_b, from_b)
2987
class cmd_missing(Command):
2988
"""Show unmerged/unpulled revisions between two branches.
2990
OTHER_BRANCH may be local or remote.
2993
_see_also = ['merge', 'pull']
2994
takes_args = ['other_branch?']
2996
Option('reverse', 'Reverse the order of revisions.'),
2998
'Display changes in the local branch only.'),
2999
Option('this' , 'Same as --mine-only.'),
3000
Option('theirs-only',
3001
'Display changes in the remote branch only.'),
3002
Option('other', 'Same as --theirs-only.'),
3007
encoding_type = 'replace'
3010
def run(self, other_branch=None, reverse=False, mine_only=False,
3011
theirs_only=False, log_format=None, long=False, short=False, line=False,
3012
show_ids=False, verbose=False, this=False, other=False):
3013
from bzrlib.missing import find_unmerged, iter_log_revisions
3014
from bzrlib.log import log_formatter
3021
local_branch = Branch.open_containing(u".")[0]
3022
parent = local_branch.get_parent()
3023
if other_branch is None:
3024
other_branch = parent
3025
if other_branch is None:
3026
raise errors.BzrCommandError("No peer location known or specified.")
3027
display_url = urlutils.unescape_for_display(parent,
3029
print "Using last location: " + display_url
3031
remote_branch = Branch.open(other_branch)
3032
if remote_branch.base == local_branch.base:
3033
remote_branch = local_branch
3034
local_branch.lock_read()
3036
remote_branch.lock_read()
3038
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
3039
if (log_format is None):
3040
log_format = log.log_formatter_registry.get_default(
3042
lf = log_format(to_file=self.outf,
3044
show_timezone='original')
3045
if reverse is False:
3046
local_extra.reverse()
3047
remote_extra.reverse()
3048
if local_extra and not theirs_only:
3049
print "You have %d extra revision(s):" % len(local_extra)
3050
for revision in iter_log_revisions(local_extra,
3051
local_branch.repository,
3053
lf.log_revision(revision)
3054
printed_local = True
3056
printed_local = False
3057
if remote_extra and not mine_only:
3058
if printed_local is True:
3060
print "You are missing %d revision(s):" % len(remote_extra)
3061
for revision in iter_log_revisions(remote_extra,
3062
remote_branch.repository,
3064
lf.log_revision(revision)
3065
if not remote_extra and not local_extra:
3067
print "Branches are up to date."
3071
remote_branch.unlock()
3073
local_branch.unlock()
3074
if not status_code and parent is None and other_branch is not None:
3075
local_branch.lock_write()
3077
# handle race conditions - a parent might be set while we run.
3078
if local_branch.get_parent() is None:
3079
local_branch.set_parent(remote_branch.base)
3081
local_branch.unlock()
3085
class cmd_pack(Command):
3086
"""Compress the data within a repository."""
3088
_see_also = ['repositories']
3089
takes_args = ['branch_or_repo?']
3091
def run(self, branch_or_repo='.'):
3092
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3094
branch = dir.open_branch()
3095
repository = branch.repository
3096
except errors.NotBranchError:
3097
repository = dir.open_repository()
3101
class cmd_plugins(Command):
3102
"""List the installed plugins.
3104
This command displays the list of installed plugins including the
3105
path where each one is located and a short description of each.
3107
A plugin is an external component for Bazaar that extends the
3108
revision control system, by adding or replacing code in Bazaar.
3109
Plugins can do a variety of things, including overriding commands,
3110
adding new commands, providing additional network transports and
3111
customizing log output.
3113
See the Bazaar web site, http://bazaar-vcs.org, for further
3114
information on plugins including where to find them and how to
3115
install them. Instructions are also provided there on how to
3116
write new plugins using the Python programming language.
3121
import bzrlib.plugin
3122
from inspect import getdoc
3123
for name, plugin in bzrlib.plugin.all_plugins().items():
3124
if getattr(plugin, '__path__', None) is not None:
3125
print plugin.__path__[0]
3126
elif getattr(plugin, '__file__', None) is not None:
3127
print plugin.__file__
3133
print '\t', d.split('\n')[0]
3136
class cmd_testament(Command):
3137
"""Show testament (signing-form) of a revision."""
3140
Option('long', help='Produce long-format testament.'),
3142
help='Produce a strict-format testament.')]
3143
takes_args = ['branch?']
3145
def run(self, branch=u'.', revision=None, long=False, strict=False):
3146
from bzrlib.testament import Testament, StrictTestament
3148
testament_class = StrictTestament
3150
testament_class = Testament
3151
b = WorkingTree.open_containing(branch)[0].branch
3154
if revision is None:
3155
rev_id = b.last_revision()
3157
rev_id = revision[0].in_history(b).rev_id
3158
t = testament_class.from_revision(b.repository, rev_id)
3160
sys.stdout.writelines(t.as_text_lines())
3162
sys.stdout.write(t.as_short_text())
3167
class cmd_annotate(Command):
3168
"""Show the origin of each line in a file.
3170
This prints out the given file with an annotation on the left side
3171
indicating which revision, author and date introduced the change.
3173
If the origin is the same for a run of consecutive lines, it is
3174
shown only at the top, unless the --all option is given.
3176
# TODO: annotate directories; showing when each file was last changed
3177
# TODO: if the working copy is modified, show annotations on that
3178
# with new uncommitted lines marked
3179
aliases = ['ann', 'blame', 'praise']
3180
takes_args = ['filename']
3181
takes_options = [Option('all', help='Show annotations on all lines.'),
3182
Option('long', help='Show commit date in annotations.'),
3186
encoding_type = 'exact'
3189
def run(self, filename, all=False, long=False, revision=None,
3191
from bzrlib.annotate import annotate_file
3192
tree, relpath = WorkingTree.open_containing(filename)
3193
branch = tree.branch
3196
if revision is None:
3197
revision_id = branch.last_revision()
3198
elif len(revision) != 1:
3199
raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3201
revision_id = revision[0].in_history(branch).rev_id
3202
file_id = tree.path2id(relpath)
3204
raise errors.NotVersionedError(filename)
3205
tree = branch.repository.revision_tree(revision_id)
3206
file_version = tree.inventory[file_id].revision
3207
annotate_file(branch, file_version, file_id, long, all, self.outf,
3213
class cmd_re_sign(Command):
3214
"""Create a digital signature for an existing revision."""
3215
# TODO be able to replace existing ones.
3217
hidden = True # is this right ?
3218
takes_args = ['revision_id*']
3219
takes_options = ['revision']
3221
def run(self, revision_id_list=None, revision=None):
3222
import bzrlib.gpg as gpg
3223
if revision_id_list is not None and revision is not None:
3224
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3225
if revision_id_list is None and revision is None:
3226
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
3227
b = WorkingTree.open_containing(u'.')[0].branch
3228
gpg_strategy = gpg.GPGStrategy(b.get_config())
3229
if revision_id_list is not None:
3230
for revision_id in revision_id_list:
3231
b.repository.sign_revision(revision_id, gpg_strategy)
3232
elif revision is not None:
3233
if len(revision) == 1:
3234
revno, rev_id = revision[0].in_history(b)
3235
b.repository.sign_revision(rev_id, gpg_strategy)
3236
elif len(revision) == 2:
3237
# are they both on rh- if so we can walk between them
3238
# might be nice to have a range helper for arbitrary
3239
# revision paths. hmm.
3240
from_revno, from_revid = revision[0].in_history(b)
3241
to_revno, to_revid = revision[1].in_history(b)
3242
if to_revid is None:
3243
to_revno = b.revno()
3244
if from_revno is None or to_revno is None:
3245
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
3246
for revno in range(from_revno, to_revno + 1):
3247
b.repository.sign_revision(b.get_rev_id(revno),
3250
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3253
class cmd_bind(Command):
3254
"""Convert the current branch into a checkout of the supplied branch.
3256
Once converted into a checkout, commits must succeed on the master branch
3257
before they will be applied to the local branch.
3260
_see_also = ['checkouts', 'unbind']
3261
takes_args = ['location?']
3264
def run(self, location=None):
3265
b, relpath = Branch.open_containing(u'.')
3266
if location is None:
3268
location = b.get_old_bound_location()
3269
except errors.UpgradeRequired:
3270
raise errors.BzrCommandError('No location supplied. '
3271
'This format does not remember old locations.')
3273
if location is None:
3274
raise errors.BzrCommandError('No location supplied and no '
3275
'previous location known')
3276
b_other = Branch.open(location)
3279
except errors.DivergedBranches:
3280
raise errors.BzrCommandError('These branches have diverged.'
3281
' Try merging, and then bind again.')
3284
class cmd_unbind(Command):
3285
"""Convert the current checkout into a regular branch.
3287
After unbinding, the local branch is considered independent and subsequent
3288
commits will be local only.
3291
_see_also = ['checkouts', 'bind']
3296
b, relpath = Branch.open_containing(u'.')
3298
raise errors.BzrCommandError('Local branch is not bound')
3301
class cmd_uncommit(Command):
3302
"""Remove the last committed revision.
3304
--verbose will print out what is being removed.
3305
--dry-run will go through all the motions, but not actually
3308
In the future, uncommit will create a revision bundle, which can then
3312
# TODO: jam 20060108 Add an option to allow uncommit to remove
3313
# unreferenced information in 'branch-as-repository' branches.
3314
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3315
# information in shared branches as well.
3316
_see_also = ['commit']
3317
takes_options = ['verbose', 'revision',
3318
Option('dry-run', help='Don\'t actually make changes.'),
3319
Option('force', help='Say yes to all questions.')]
3320
takes_args = ['location?']
3323
def run(self, location=None,
3324
dry_run=False, verbose=False,
3325
revision=None, force=False):
3326
from bzrlib.log import log_formatter, show_log
3328
from bzrlib.uncommit import uncommit
3330
if location is None:
3332
control, relpath = bzrdir.BzrDir.open_containing(location)
3334
tree = control.open_workingtree()
3336
except (errors.NoWorkingTree, errors.NotLocalUrl):
3338
b = control.open_branch()
3341
if revision is None:
3344
# 'bzr uncommit -r 10' actually means uncommit
3345
# so that the final tree is at revno 10.
3346
# but bzrlib.uncommit.uncommit() actually uncommits
3347
# the revisions that are supplied.
3348
# So we need to offset it by one
3349
revno = revision[0].in_history(b).revno+1
3351
if revno <= b.revno():
3352
rev_id = b.get_rev_id(revno)
3354
self.outf.write('No revisions to uncommit.\n')
3357
lf = log_formatter('short',
3359
show_timezone='original')
3364
direction='forward',
3365
start_revision=revno,
3366
end_revision=b.revno())
3369
print 'Dry-run, pretending to remove the above revisions.'
3371
val = raw_input('Press <enter> to continue')
3373
print 'The above revision(s) will be removed.'
3375
val = raw_input('Are you sure [y/N]? ')
3376
if val.lower() not in ('y', 'yes'):
3380
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3384
class cmd_break_lock(Command):
3385
"""Break a dead lock on a repository, branch or working directory.
3387
CAUTION: Locks should only be broken when you are sure that the process
3388
holding the lock has been stopped.
3390
You can get information on what locks are open via the 'bzr info' command.
3395
takes_args = ['location?']
3397
def run(self, location=None, show=False):
3398
if location is None:
3400
control, relpath = bzrdir.BzrDir.open_containing(location)
3402
control.break_lock()
3403
except NotImplementedError:
3407
class cmd_wait_until_signalled(Command):
3408
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3410
This just prints a line to signal when it is ready, then blocks on stdin.
3416
sys.stdout.write("running\n")
3418
sys.stdin.readline()
3421
class cmd_serve(Command):
3422
"""Run the bzr server."""
3424
aliases = ['server']
3428
help='Serve on stdin/out for use from inetd or sshd.'),
3430
help='Listen for connections on nominated port of the form '
3431
'[hostname:]portnumber. Passing 0 as the port number will '
3432
'result in a dynamically allocated port. The default port is '
3436
help='Serve contents of this directory.',
3438
Option('allow-writes',
3439
help='By default the server is a readonly server. Supplying '
3440
'--allow-writes enables write access to the contents of '
3441
'the served directory and below.'
3445
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3446
from bzrlib.smart import medium, server
3447
from bzrlib.transport import get_transport
3448
from bzrlib.transport.chroot import ChrootServer
3449
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3450
if directory is None:
3451
directory = os.getcwd()
3452
url = urlutils.local_path_to_url(directory)
3453
if not allow_writes:
3454
url = 'readonly+' + url
3455
chroot_server = ChrootServer(get_transport(url))
3456
chroot_server.setUp()
3457
t = get_transport(chroot_server.get_url())
3459
smart_server = medium.SmartServerPipeStreamMedium(
3460
sys.stdin, sys.stdout, t)
3462
host = BZR_DEFAULT_INTERFACE
3464
port = BZR_DEFAULT_PORT
3467
host, port = port.split(':')
3469
smart_server = server.SmartTCPServer(t, host=host, port=port)
3470
print 'listening on port: ', smart_server.port
3472
# for the duration of this server, no UI output is permitted.
3473
# note that this may cause problems with blackbox tests. This should
3474
# be changed with care though, as we dont want to use bandwidth sending
3475
# progress over stderr to smart server clients!
3476
old_factory = ui.ui_factory
3478
ui.ui_factory = ui.SilentUIFactory()
3479
smart_server.serve()
3481
ui.ui_factory = old_factory
3484
class cmd_join(Command):
3485
"""Combine a subtree into its containing tree.
3487
This command is for experimental use only. It requires the target tree
3488
to be in dirstate-with-subtree format, which cannot be converted into
3491
The TREE argument should be an independent tree, inside another tree, but
3492
not part of it. (Such trees can be produced by "bzr split", but also by
3493
running "bzr branch" with the target inside a tree.)
3495
The result is a combined tree, with the subtree no longer an independant
3496
part. This is marked as a merge of the subtree into the containing tree,
3497
and all history is preserved.
3499
If --reference is specified, the subtree retains its independence. It can
3500
be branched by itself, and can be part of multiple projects at the same
3501
time. But operations performed in the containing tree, such as commit
3502
and merge, will recurse into the subtree.
3505
_see_also = ['split']
3506
takes_args = ['tree']
3508
Option('reference', help='Join by reference.'),
3512
def run(self, tree, reference=False):
3513
sub_tree = WorkingTree.open(tree)
3514
parent_dir = osutils.dirname(sub_tree.basedir)
3515
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3516
repo = containing_tree.branch.repository
3517
if not repo.supports_rich_root():
3518
raise errors.BzrCommandError(
3519
"Can't join trees because %s doesn't support rich root data.\n"
3520
"You can use bzr upgrade on the repository."
3524
containing_tree.add_reference(sub_tree)
3525
except errors.BadReferenceTarget, e:
3526
# XXX: Would be better to just raise a nicely printable
3527
# exception from the real origin. Also below. mbp 20070306
3528
raise errors.BzrCommandError("Cannot join %s. %s" %
3532
containing_tree.subsume(sub_tree)
3533
except errors.BadSubsumeSource, e:
3534
raise errors.BzrCommandError("Cannot join %s. %s" %
3538
class cmd_split(Command):
3539
"""Split a tree into two trees.
3541
This command is for experimental use only. It requires the target tree
3542
to be in dirstate-with-subtree format, which cannot be converted into
3545
The TREE argument should be a subdirectory of a working tree. That
3546
subdirectory will be converted into an independent tree, with its own
3547
branch. Commits in the top-level tree will not apply to the new subtree.
3548
If you want that behavior, do "bzr join --reference TREE".
3551
_see_also = ['join']
3552
takes_args = ['tree']
3556
def run(self, tree):
3557
containing_tree, subdir = WorkingTree.open_containing(tree)
3558
sub_id = containing_tree.path2id(subdir)
3560
raise errors.NotVersionedError(subdir)
3562
containing_tree.extract(sub_id)
3563
except errors.RootNotRich:
3564
raise errors.UpgradeRequired(containing_tree.branch.base)
3568
class cmd_merge_directive(Command):
3569
"""Generate a merge directive for auto-merge tools.
3571
A directive requests a merge to be performed, and also provides all the
3572
information necessary to do so. This means it must either include a
3573
revision bundle, or the location of a branch containing the desired
3576
A submit branch (the location to merge into) must be supplied the first
3577
time the command is issued. After it has been supplied once, it will
3578
be remembered as the default.
3580
A public branch is optional if a revision bundle is supplied, but required
3581
if --diff or --plain is specified. It will be remembered as the default
3582
after the first use.
3585
takes_args = ['submit_branch?', 'public_branch?']
3589
_see_also = ['submit']
3592
RegistryOption.from_kwargs('patch-type',
3593
'The type of patch to include in the directive',
3595
value_switches=True,
3597
bundle='Bazaar revision bundle (default).',
3598
diff='Normal unified diff.',
3599
plain='No patch, just directive.'),
3600
Option('sign', help='GPG-sign the directive.'), 'revision',
3601
Option('mail-to', type=str,
3602
help='Instead of printing the directive, email to this address.'),
3603
Option('message', type=str, short_name='m',
3604
help='Message to use when committing this merge.')
3607
encoding_type = 'exact'
3609
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3610
sign=False, revision=None, mail_to=None, message=None):
3611
from bzrlib.revision import ensure_null, NULL_REVISION
3612
include_patch, include_bundle = {
3613
'plain': (False, False),
3614
'diff': (True, False),
3615
'bundle': (True, True),
3617
branch = Branch.open('.')
3618
stored_submit_branch = branch.get_submit_branch()
3619
if submit_branch is None:
3620
submit_branch = stored_submit_branch
3622
if stored_submit_branch is None:
3623
branch.set_submit_branch(submit_branch)
3624
if submit_branch is None:
3625
submit_branch = branch.get_parent()
3626
if submit_branch is None:
3627
raise errors.BzrCommandError('No submit branch specified or known')
3629
stored_public_branch = branch.get_public_branch()
3630
if public_branch is None:
3631
public_branch = stored_public_branch
3632
elif stored_public_branch is None:
3633
branch.set_public_branch(public_branch)
3634
if not include_bundle and public_branch is None:
3635
raise errors.BzrCommandError('No public branch specified or'
3637
base_revision_id = None
3638
if revision is not None:
3639
if len(revision) > 2:
3640
raise errors.BzrCommandError('bzr merge-directive takes '
3641
'at most two one revision identifiers')
3642
revision_id = revision[-1].in_history(branch).rev_id
3643
if len(revision) == 2:
3644
base_revision_id = revision[0].in_history(branch).rev_id
3645
base_revision_id = ensure_null(base_revision_id)
3647
revision_id = branch.last_revision()
3648
revision_id = ensure_null(revision_id)
3649
if revision_id == NULL_REVISION:
3650
raise errors.BzrCommandError('No revisions to bundle.')
3651
directive = merge_directive.MergeDirective2.from_objects(
3652
branch.repository, revision_id, time.time(),
3653
osutils.local_time_offset(), submit_branch,
3654
public_branch=public_branch, include_patch=include_patch,
3655
include_bundle=include_bundle, message=message,
3656
base_revision_id=base_revision_id)
3659
self.outf.write(directive.to_signed(branch))
3661
self.outf.writelines(directive.to_lines())
3663
message = directive.to_email(mail_to, branch, sign)
3664
s = SMTPConnection(branch.get_config())
3665
s.send_email(message)
3668
class cmd_submit(Command):
3669
"""Create a merge-directive for submiting changes.
3671
A merge directive provides many things needed for requesting merges:
3672
- A machine-readable description of the merge to perform
3673
- An optional patch that is a preview of the changes requested
3674
- An optional bundle of revision data, so that the changes can be applied
3675
directly from the merge directive, without retrieving data from a
3678
If --no-bundle is specified, then public_branch is needed (and must be
3679
up-to-date), so that the receiver can perform the merge using the
3680
public_branch. The public_branch is always included if known, so that
3681
people can check it later.
3683
The submit branch defaults to the parent, but can be overridden. Both
3684
submit branch and public branch will be remembered if supplied.
3686
If a public_branch is known for the submit_branch, that public submit
3687
branch is used in the merge instructions. This means that a local mirror
3688
can be used as your actual submit branch, once you have set public_branch
3692
encoding_type = 'exact'
3694
aliases = ['bundle', 'bundle-revisions']
3696
_see_also = ['merge']
3698
takes_args = ['submit_branch?', 'public_branch?']
3701
help='Do not include a bundle in the merge directive.'),
3702
Option('no-patch', help='Do not include a preview patch in the merge'
3705
help='Remember submit and public branch.'),
3707
help='Branch to generate the submission from, '
3708
'rather than the one containing the working directory.',
3711
Option('output', short_name='o', help='Write directive to this file.',
3716
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3717
no_patch=False, revision=None, remember=False, output=None,
3719
from bzrlib.revision import ensure_null, NULL_REVISION
3723
outfile = open(output, 'wb')
3725
from_ = kwargs.get('from', '.')
3726
branch = Branch.open_containing(from_)[0]
3727
if remember and submit_branch is None:
3728
raise errors.BzrCommandError(
3729
'--remember requires a branch to be specified.')
3730
stored_submit_branch = branch.get_submit_branch()
3731
remembered_submit_branch = False
3732
if submit_branch is None:
3733
submit_branch = stored_submit_branch
3734
remembered_submit_branch = True
3736
if stored_submit_branch is None or remember:
3737
branch.set_submit_branch(submit_branch)
3738
if submit_branch is None:
3739
submit_branch = branch.get_parent()
3740
remembered_submit_branch = True
3741
if submit_branch is None:
3742
raise errors.BzrCommandError('No submit branch known or'
3744
if remembered_submit_branch:
3745
note('Using saved location: %s', submit_branch)
3747
stored_public_branch = branch.get_public_branch()
3748
if public_branch is None:
3749
public_branch = stored_public_branch
3750
elif stored_public_branch is None or remember:
3751
branch.set_public_branch(public_branch)
3752
if no_bundle and public_branch is None:
3753
raise errors.BzrCommandError('No public branch specified or'
3755
base_revision_id = None
3756
if revision is not None:
3757
if len(revision) > 2:
3758
raise errors.BzrCommandError('bzr submit takes '
3759
'at most two one revision identifiers')
3760
revision_id = revision[-1].in_history(branch).rev_id
3761
if len(revision) == 2:
3762
base_revision_id = revision[0].in_history(branch).rev_id
3763
base_revision_id = ensure_null(base_revision_id)
3765
revision_id = branch.last_revision()
3766
revision_id = ensure_null(revision_id)
3767
if revision_id == NULL_REVISION:
3768
raise errors.BzrCommandError('No revisions to submit.')
3769
directive = merge_directive.MergeDirective2.from_objects(
3770
branch.repository, revision_id, time.time(),
3771
osutils.local_time_offset(), submit_branch,
3772
public_branch=public_branch, include_patch=not no_patch,
3773
include_bundle=not no_bundle, message=None,
3774
base_revision_id=base_revision_id)
3775
outfile.writelines(directive.to_lines())
3777
if output is not None:
3780
class cmd_tag(Command):
3781
"""Create a tag naming a revision.
3783
Tags give human-meaningful names to revisions. Commands that take a -r
3784
(--revision) option can be given -rtag:X, where X is any previously
3787
Tags are stored in the branch. Tags are copied from one branch to another
3788
along when you branch, push, pull or merge.
3790
It is an error to give a tag name that already exists unless you pass
3791
--force, in which case the tag is moved to point to the new revision.
3794
_see_also = ['commit', 'tags']
3795
takes_args = ['tag_name']
3798
help='Delete this tag rather than placing it.',
3801
help='Branch in which to place the tag.',
3806
help='Replace existing tags.',
3811
def run(self, tag_name,
3817
branch, relpath = Branch.open_containing(directory)
3821
branch.tags.delete_tag(tag_name)
3822
self.outf.write('Deleted tag %s.\n' % tag_name)
3825
if len(revision) != 1:
3826
raise errors.BzrCommandError(
3827
"Tags can only be placed on a single revision, "
3829
revision_id = revision[0].in_history(branch).rev_id
3831
revision_id = branch.last_revision()
3832
if (not force) and branch.tags.has_tag(tag_name):
3833
raise errors.TagAlreadyExists(tag_name)
3834
branch.tags.set_tag(tag_name, revision_id)
3835
self.outf.write('Created tag %s.\n' % tag_name)
3840
class cmd_tags(Command):
3843
This tag shows a table of tag names and the revisions they reference.
3849
help='Branch whose tags should be displayed.',
3859
branch, relpath = Branch.open_containing(directory)
3860
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3861
self.outf.write('%-20s %s\n' % (tag_name, target))
3864
# command-line interpretation helper for merge-related commands
3865
def _merge_helper(other_revision, base_revision,
3866
check_clean=True, ignore_zero=False,
3867
this_dir=None, backup_files=False,
3869
file_list=None, show_base=False, reprocess=False,
3872
change_reporter=None,
3873
other_rev_id=None, base_rev_id=None):
3874
"""Merge changes into a tree.
3877
list(path, revno) Base for three-way merge.
3878
If [None, None] then a base will be automatically determined.
3880
list(path, revno) Other revision for three-way merge.
3882
Directory to merge changes into; '.' by default.
3884
If true, this_dir must have no uncommitted changes before the
3886
ignore_zero - If true, suppress the "zero conflicts" message when
3887
there are no conflicts; should be set when doing something we expect
3888
to complete perfectly.
3889
file_list - If supplied, merge only changes to selected files.
3891
All available ancestors of other_revision and base_revision are
3892
automatically pulled into the branch.
3894
The revno may be -1 to indicate the last revision on the branch, which is
3897
This function is intended for use from the command line; programmatic
3898
clients might prefer to call merge.merge_inner(), which has less magic
3901
# Loading it late, so that we don't always have to import bzrlib.merge
3902
if merge_type is None:
3903
merge_type = _mod_merge.Merge3Merger
3904
if this_dir is None:
3906
this_tree = WorkingTree.open_containing(this_dir)[0]
3907
if show_base and not merge_type is _mod_merge.Merge3Merger:
3908
raise errors.BzrCommandError("Show-base is not supported for this merge"
3909
" type. %s" % merge_type)
3910
if reprocess and not merge_type.supports_reprocess:
3911
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3912
" type %s." % merge_type)
3913
if reprocess and show_base:
3914
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3915
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3916
# only want to take out a lock_tree_write() if we don't have to pull
3917
# any ancestry. But merge might fetch ancestry in the middle, in
3918
# which case we would need a lock_write().
3919
# Because we cannot upgrade locks, for now we live with the fact that
3920
# the tree will be locked multiple times during a merge. (Maybe
3921
# read-only some of the time, but it means things will get read
3924
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3925
pb=pb, change_reporter=change_reporter)
3926
merger.pp = ProgressPhase("Merge phase", 5, pb)
3927
merger.pp.next_phase()
3928
merger.check_basis(check_clean)
3929
if other_rev_id is not None:
3930
merger.set_other_revision(other_rev_id, this_tree.branch)
3932
merger.set_other(other_revision)
3933
merger.pp.next_phase()
3934
if base_rev_id is not None:
3935
merger.set_base_revision(base_rev_id, this_tree.branch)
3936
elif base_revision is not None:
3937
merger.set_base(base_revision)
3940
if merger.base_rev_id == merger.other_rev_id:
3941
note('Nothing to do.')
3943
if file_list is None:
3944
if pull and merger.base_rev_id == merger.this_rev_id:
3945
# FIXME: deduplicate with pull
3946
result = merger.this_tree.pull(merger.this_branch,
3947
False, merger.other_rev_id)
3948
if result.old_revid == result.new_revid:
3949
note('No revisions to pull.')
3951
note('Now on revision %d.' % result.new_revno)
3953
merger.backup_files = backup_files
3954
merger.merge_type = merge_type
3955
merger.set_interesting_files(file_list)
3956
merger.show_base = show_base
3957
merger.reprocess = reprocess
3958
conflicts = merger.do_merge()
3959
if file_list is None:
3960
merger.set_pending()
3966
def _create_prefix(cur_transport):
3967
needed = [cur_transport]
3968
# Recurse upwards until we can create a directory successfully
3970
new_transport = cur_transport.clone('..')
3971
if new_transport.base == cur_transport.base:
3972
raise errors.BzrCommandError(
3973
"Failed to create path prefix for %s."
3974
% cur_transport.base)
3976
new_transport.mkdir('.')
3977
except errors.NoSuchFile:
3978
needed.append(new_transport)
3979
cur_transport = new_transport
3982
# Now we only need to create child directories
3984
cur_transport = needed.pop()
3985
cur_transport.ensure_base()
3989
merge = _merge_helper
3992
# these get imported and then picked up by the scan for cmd_*
3993
# TODO: Some more consistent way to split command definitions across files;
3994
# we do need to load at least some information about them to know of
3995
# aliases. ideally we would avoid loading the implementation until the
3996
# details were needed.
3997
from bzrlib.cmd_version_info import cmd_version_info
3998
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3999
from bzrlib.bundle.commands import (
4002
from bzrlib.sign_my_commits import cmd_sign_my_commits
4003
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
4004
cmd_weave_plan_merge, cmd_weave_merge_text