1
# Copyright (C) 2004, 2005, 2006 by 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"""
23
from shutil import rmtree
28
from bzrlib.branch import Branch
29
import bzrlib.bzrdir as bzrdir
30
from bzrlib.bundle.read_bundle import BundleReader
31
from bzrlib.bundle.apply_bundle import merge_bundle
32
from bzrlib.commands import Command, display_command
33
import bzrlib.errors as errors
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
NotVersionedError, BadBundle)
38
from bzrlib.log import show_one_log
39
from bzrlib.merge import Merge3Merger
40
from bzrlib.option import Option
42
from bzrlib.progress import DummyProgress, ProgressPhase
43
from bzrlib.revision import common_ancestor
44
from bzrlib.revisionspec import RevisionSpec
46
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
47
from bzrlib.transport.local import LocalTransport
49
import bzrlib.urlutils as urlutils
50
from bzrlib.workingtree import WorkingTree
53
def tree_files(file_list, default_branch=u'.'):
55
return internal_tree_files(file_list, default_branch)
56
except FileInWrongBranch, e:
57
raise BzrCommandError("%s is not in the same branch as %s" %
58
(e.path, file_list[0]))
61
# XXX: Bad function name; should possibly also be a class method of
62
# WorkingTree rather than a function.
63
def internal_tree_files(file_list, default_branch=u'.'):
64
"""Convert command-line paths to a WorkingTree and relative paths.
66
This is typically used for command-line processors that take one or
67
more filenames, and infer the workingtree that contains them.
69
The filenames given are not required to exist.
71
:param file_list: Filenames to convert.
73
:param default_branch: Fallback tree path to use if file_list is empty or None.
75
:return: workingtree, [relative_paths]
77
if file_list is None or len(file_list) == 0:
78
return WorkingTree.open_containing(default_branch)[0], file_list
79
tree = WorkingTree.open_containing(file_list[0])[0]
81
for filename in file_list:
83
new_list.append(tree.relpath(filename))
84
except errors.PathNotChild:
85
raise FileInWrongBranch(tree.branch, filename)
89
def get_format_type(typestring):
90
"""Parse and return a format specifier."""
91
if typestring == "weave":
92
return bzrdir.BzrDirFormat6()
93
if typestring == "default":
94
return bzrdir.BzrDirMetaFormat1()
95
if typestring == "metaweave":
96
format = bzrdir.BzrDirMetaFormat1()
97
format.repository_format = bzrlib.repository.RepositoryFormat7()
99
if typestring == "knit":
100
format = bzrdir.BzrDirMetaFormat1()
101
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
103
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
104
"metaweave and weave" % typestring
105
raise BzrCommandError(msg)
108
# TODO: Make sure no commands unconditionally use the working directory as a
109
# branch. If a filename argument is used, the first of them should be used to
110
# specify the branch. (Perhaps this can be factored out into some kind of
111
# Argument class, representing a file in a branch, where the first occurrence
114
class cmd_status(Command):
115
"""Display status summary.
117
This reports on versioned and unknown files, reporting them
118
grouped by state. Possible states are:
121
Versioned in the working copy but not in the previous revision.
124
Versioned in the previous revision but removed or deleted
128
Path of this file changed from the previous revision;
129
the text may also have changed. This includes files whose
130
parent directory was renamed.
133
Text has changed since the previous revision.
136
Nothing about this file has changed since the previous revision.
137
Only shown with --all.
140
Not versioned and not matching an ignore pattern.
142
To see ignored files use 'bzr ignored'. For details in the
143
changes to file texts, use 'bzr diff'.
145
If no arguments are specified, the status of the entire working
146
directory is shown. Otherwise, only the status of the specified
147
files or directories is reported. If a directory is given, status
148
is reported for everything inside that directory.
150
If a revision argument is given, the status is calculated against
151
that revision, or between two revisions if two are provided.
154
# TODO: --no-recurse, --recurse options
156
takes_args = ['file*']
157
takes_options = ['all', 'show-ids', 'revision']
158
aliases = ['st', 'stat']
160
encoding_type = 'replace'
163
def run(self, all=False, show_ids=False, file_list=None, revision=None):
164
from bzrlib.status import show_tree_status
166
tree, file_list = tree_files(file_list)
168
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
169
specific_files=file_list, revision=revision,
173
class cmd_cat_revision(Command):
174
"""Write out metadata for a revision.
176
The revision to print can either be specified by a specific
177
revision identifier, or you can use --revision.
181
takes_args = ['revision_id?']
182
takes_options = ['revision']
185
def run(self, revision_id=None, revision=None):
187
if revision_id is not None and revision is not None:
188
raise BzrCommandError('You can only supply one of revision_id or --revision')
189
if revision_id is None and revision is None:
190
raise BzrCommandError('You must supply either --revision or a revision_id')
191
b = WorkingTree.open_containing(u'.')[0].branch
193
# TODO: jam 20060112 should cat-revision always output utf-8?
194
if revision_id is not None:
195
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
196
elif revision is not None:
199
raise BzrCommandError('You cannot specify a NULL revision.')
200
revno, rev_id = rev.in_history(b)
201
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
204
class cmd_revno(Command):
205
"""Show current revision number.
207
This is equal to the number of revisions on this branch.
210
takes_args = ['location?']
213
def run(self, location=u'.'):
214
self.outf.write(str(Branch.open_containing(location)[0].revno()))
215
self.outf.write('\n')
218
class cmd_revision_info(Command):
219
"""Show revision number and revision id for a given revision identifier.
222
takes_args = ['revision_info*']
223
takes_options = ['revision']
226
def run(self, revision=None, revision_info_list=[]):
229
if revision is not None:
230
revs.extend(revision)
231
if revision_info_list is not None:
232
for rev in revision_info_list:
233
revs.append(RevisionSpec(rev))
235
raise BzrCommandError('You must supply a revision identifier')
237
b = WorkingTree.open_containing(u'.')[0].branch
240
revinfo = rev.in_history(b)
241
if revinfo.revno is None:
242
print ' %s' % revinfo.rev_id
244
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
247
class cmd_add(Command):
248
"""Add specified files or directories.
250
In non-recursive mode, all the named items are added, regardless
251
of whether they were previously ignored. A warning is given if
252
any of the named files are already versioned.
254
In recursive mode (the default), files are treated the same way
255
but the behaviour for directories is different. Directories that
256
are already versioned do not give a warning. All directories,
257
whether already versioned or not, are searched for files or
258
subdirectories that are neither versioned or ignored, and these
259
are added. This search proceeds recursively into versioned
260
directories. If no names are given '.' is assumed.
262
Therefore simply saying 'bzr add' will version all files that
263
are currently unknown.
265
Adding a file whose parent directory is not versioned will
266
implicitly add the parent, and so on up to the root. This means
267
you should never need to explictly add a directory, they'll just
268
get added when you add a file in the directory.
270
--dry-run will show which files would be added, but not actually
273
takes_args = ['file*']
274
takes_options = ['no-recurse', 'dry-run', 'verbose']
275
encoding_type = 'replace'
277
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
280
action = bzrlib.add.AddAction(to_file=self.outf,
281
should_add=(not dry_run), should_print=(not is_quiet()))
283
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
287
for glob in sorted(ignored.keys()):
288
for path in ignored[glob]:
289
self.outf.write("ignored %s matching \"%s\"\n"
293
for glob, paths in ignored.items():
294
match_len += len(paths)
295
self.outf.write("ignored %d file(s).\n" % match_len)
296
self.outf.write("If you wish to add some of these files,"
297
" please add them by name.\n")
300
class cmd_mkdir(Command):
301
"""Create a new versioned directory.
303
This is equivalent to creating the directory and then adding it.
305
takes_args = ['dir+']
306
encoding_type = 'replace'
308
def run(self, dir_list):
311
wt, dd = WorkingTree.open_containing(d)
313
print >>self.outf, 'added', d
316
class cmd_relpath(Command):
317
"""Show path of a file relative to root"""
318
takes_args = ['filename']
322
def run(self, filename):
323
# TODO: jam 20050106 Can relpath return a munged path if
324
# sys.stdout encoding cannot represent it?
325
tree, relpath = WorkingTree.open_containing(filename)
326
self.outf.write(relpath)
327
self.outf.write('\n')
330
class cmd_inventory(Command):
331
"""Show inventory of the current working copy or a revision.
333
It is possible to limit the output to a particular entry
334
type using the --kind option. For example; --kind file.
336
takes_options = ['revision', 'show-ids', 'kind']
339
def run(self, revision=None, show_ids=False, kind=None):
340
if kind and kind not in ['file', 'directory', 'symlink']:
341
raise BzrCommandError('invalid kind specified')
342
tree = WorkingTree.open_containing(u'.')[0]
344
inv = tree.read_working_inventory()
346
if len(revision) > 1:
347
raise BzrCommandError('bzr inventory --revision takes'
348
' exactly one revision identifier')
349
inv = tree.branch.repository.get_revision_inventory(
350
revision[0].in_history(tree.branch).rev_id)
352
for path, entry in inv.entries():
353
if kind and kind != entry.kind:
356
self.outf.write('%-50s %s\n' % (path, entry.file_id))
358
self.outf.write(path)
359
self.outf.write('\n')
362
class cmd_mv(Command):
363
"""Move or rename a file.
366
bzr mv OLDNAME NEWNAME
367
bzr mv SOURCE... DESTINATION
369
If the last argument is a versioned directory, all the other names
370
are moved into it. Otherwise, there must be exactly two arguments
371
and the file is changed to a new name, which must not already exist.
373
Files cannot be moved between branches.
375
takes_args = ['names*']
376
aliases = ['move', 'rename']
378
encoding_type = 'replace'
380
def run(self, names_list):
381
if len(names_list) < 2:
382
raise BzrCommandError("missing file argument")
383
tree, rel_names = tree_files(names_list)
385
if os.path.isdir(names_list[-1]):
386
# move into existing directory
387
for pair in tree.move(rel_names[:-1], rel_names[-1]):
388
self.outf.write("%s => %s\n" % pair)
390
if len(names_list) != 2:
391
raise BzrCommandError('to mv multiple files the destination '
392
'must be a versioned directory')
393
tree.rename_one(rel_names[0], rel_names[1])
394
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
397
class cmd_pull(Command):
398
"""Turn this branch into a mirror of another branch.
400
This command only works on branches that have not diverged. Branches are
401
considered diverged if the destination branch's most recent commit is one
402
that has not been merged (directly or indirectly) into the parent.
404
If branches have diverged, you can use 'bzr merge' to integrate the changes
405
from one into the other. Once one branch has merged, the other should
406
be able to pull it again.
408
If branches have diverged, you can use 'bzr merge' to pull the text changes
409
from one into the other. Once one branch has merged, the other should
410
be able to pull it again.
412
If you want to forget your local changes and just update your branch to
413
match the remote one, use pull --overwrite.
415
If there is no default location set, the first pull will set it. After
416
that, you can omit the location to use the default. To change the
417
default, use --remember.
419
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
420
takes_args = ['location?']
421
encoding_type = 'replace'
423
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
424
# FIXME: too much stuff is in the command class
426
tree_to = WorkingTree.open_containing(u'.')[0]
427
branch_to = tree_to.branch
428
except NoWorkingTree:
430
branch_to = Branch.open_containing(u'.')[0]
431
stored_loc = branch_to.get_parent()
433
if stored_loc is None:
434
raise BzrCommandError("No pull location known or specified.")
436
display_url = urlutils.unescape_for_display(stored_loc,
438
self.outf.write("Using saved location: %s\n" % display_url)
439
location = stored_loc
441
branch_from = Branch.open(location)
443
if branch_to.get_parent() is None or remember:
444
branch_to.set_parent(branch_from.base)
449
elif len(revision) == 1:
450
rev_id = revision[0].in_history(branch_from).rev_id
452
raise BzrCommandError('bzr pull --revision takes one value.')
454
old_rh = branch_to.revision_history()
455
if tree_to is not None:
456
count = tree_to.pull(branch_from, overwrite, rev_id)
458
count = branch_to.pull(branch_from, overwrite, rev_id)
459
note('%d revision(s) pulled.' % (count,))
462
new_rh = branch_to.revision_history()
465
from bzrlib.log import show_changed_revisions
466
show_changed_revisions(branch_to, old_rh, new_rh,
470
class cmd_push(Command):
471
"""Update a mirror of this branch.
473
The target branch will not have its working tree populated because this
474
is both expensive, and is not supported on remote file systems.
476
Some smart servers or protocols *may* put the working tree in place in
479
This command only works on branches that have not diverged. Branches are
480
considered diverged if the destination branch's most recent commit is one
481
that has not been merged (directly or indirectly) by the source branch.
483
If branches have diverged, you can use 'bzr push --overwrite' to replace
484
the other branch completely, discarding its unmerged changes.
486
If you want to ensure you have the different changes in the other branch,
487
do a merge (see bzr help merge) from the other branch, and commit that.
488
After that you will be able to do a push without '--overwrite'.
490
If there is no default push location set, the first push will set it.
491
After that, you can omit the location to use the default. To change the
492
default, use --remember.
494
takes_options = ['remember', 'overwrite', 'verbose',
495
Option('create-prefix',
496
help='Create the path leading up to the branch '
497
'if it does not already exist')]
498
takes_args = ['location?']
499
encoding_type = 'replace'
501
def run(self, location=None, remember=False, overwrite=False,
502
create_prefix=False, verbose=False):
503
# FIXME: Way too big! Put this into a function called from the
505
from bzrlib.transport import get_transport
507
br_from = Branch.open_containing('.')[0]
508
stored_loc = br_from.get_push_location()
510
if stored_loc is None:
511
raise BzrCommandError("No push location known or specified.")
513
display_url = urlutils.unescape_for_display(stored_loc,
515
self.outf.write("Using saved location: %s" % display_url)
516
location = stored_loc
518
transport = get_transport(location)
519
location_url = transport.base
520
if br_from.get_push_location() is None or remember:
521
br_from.set_push_location(location_url)
523
dir_to = bzrlib.bzrdir.BzrDir.open(location_url)
524
br_to = dir_to.open_branch()
525
except NotBranchError:
527
transport = transport.clone('..')
528
if not create_prefix:
530
relurl = transport.relpath(location_url)
531
mutter('creating directory %s => %s', location_url, relurl)
532
transport.mkdir(relurl)
534
raise BzrCommandError("Parent directory of %s "
535
"does not exist." % location)
537
current = transport.base
538
needed = [(transport, transport.relpath(location_url))]
541
transport, relpath = needed[-1]
542
transport.mkdir(relpath)
545
new_transport = transport.clone('..')
546
needed.append((new_transport,
547
new_transport.relpath(transport.base)))
548
if new_transport.base == transport.base:
549
raise BzrCommandError("Could not create "
551
dir_to = br_from.bzrdir.clone(location_url,
552
revision_id=br_from.last_revision())
553
br_to = dir_to.open_branch()
554
count = len(br_to.revision_history())
556
old_rh = br_to.revision_history()
559
tree_to = dir_to.open_workingtree()
560
except errors.NotLocalUrl:
561
warning('This transport does not update the working '
562
'tree of: %s' % (br_to.base,))
563
count = br_to.pull(br_from, overwrite)
564
except NoWorkingTree:
565
count = br_to.pull(br_from, overwrite)
567
count = tree_to.pull(br_from, overwrite)
568
except DivergedBranches:
569
raise BzrCommandError("These branches have diverged."
570
" Try a merge then push with overwrite.")
571
note('%d revision(s) pushed.' % (count,))
574
new_rh = br_to.revision_history()
577
from bzrlib.log import show_changed_revisions
578
show_changed_revisions(br_to, old_rh, new_rh,
582
class cmd_branch(Command):
583
"""Create a new copy of a branch.
585
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
586
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
588
To retrieve the branch as of a particular revision, supply the --revision
589
parameter, as in "branch foo/bar -r 5".
591
--basis is to speed up branching from remote branches. When specified, it
592
copies all the file-contents, inventory and revision data from the basis
593
branch before copying anything from the remote branch.
595
takes_args = ['from_location', 'to_location?']
596
takes_options = ['revision', 'basis']
597
aliases = ['get', 'clone']
599
def run(self, from_location, to_location=None, revision=None, basis=None):
600
from bzrlib.transport import get_transport
601
from bzrlib.osutils import rmtree
604
elif len(revision) > 1:
605
raise BzrCommandError(
606
'bzr branch --revision takes exactly 1 revision value')
608
br_from = Branch.open(from_location)
610
if e.errno == errno.ENOENT:
611
raise BzrCommandError('Source location "%s" does not'
612
' exist.' % to_location)
617
if basis is not None:
618
basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
621
if len(revision) == 1 and revision[0] is not None:
622
revision_id = revision[0].in_history(br_from)[1]
624
# FIXME - wt.last_revision, fallback to branch, fall back to
625
# None or perhaps NULL_REVISION to mean copy nothing
627
revision_id = br_from.last_revision()
628
if to_location is None:
629
to_location = os.path.basename(from_location.rstrip("/\\"))
632
name = os.path.basename(to_location) + '\n'
634
to_transport = get_transport(to_location)
636
to_transport.mkdir('.')
637
except bzrlib.errors.FileExists:
638
raise BzrCommandError('Target directory "%s" already'
639
' exists.' % to_location)
640
except bzrlib.errors.NoSuchFile:
641
raise BzrCommandError('Parent of "%s" does not exist.' %
644
# preserve whatever source format we have.
645
dir = br_from.bzrdir.sprout(to_transport.base,
646
revision_id, basis_dir)
647
branch = dir.open_branch()
648
except bzrlib.errors.NoSuchRevision:
649
# TODO: jam 20060426 This only works on local paths
650
# and it would be nice if 'bzr branch' could
651
# work on a remote path
653
msg = "The branch %s has no revision %s." % (from_location, revision[0])
654
raise BzrCommandError(msg)
655
except bzrlib.errors.UnlistableBranch:
657
msg = "The branch %s cannot be used as a --basis" % (basis,)
658
raise BzrCommandError(msg)
660
branch.control_files.put_utf8('branch-name', name)
661
note('Branched %d revision(s).' % branch.revno())
666
class cmd_checkout(Command):
667
"""Create a new checkout of an existing branch.
669
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
670
the branch found in '.'. This is useful if you have removed the working tree
671
or if it was never created - i.e. if you pushed the branch to its current
674
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
675
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
677
To retrieve the branch as of a particular revision, supply the --revision
678
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
679
out of date [so you cannot commit] but it may be useful (i.e. to examine old
682
--basis is to speed up checking out from remote branches. When specified, it
683
uses the inventory and file contents from the basis branch in preference to the
684
branch being checked out.
686
takes_args = ['branch_location?', 'to_location?']
687
takes_options = ['revision', # , 'basis']
688
Option('lightweight',
689
help="perform a lightweight checkout. Lightweight "
690
"checkouts depend on access to the branch for "
691
"every operation. Normal checkouts can perform "
692
"common operations like diff and status without "
693
"such access, and also support local commits."
697
def run(self, branch_location=None, to_location=None, revision=None, basis=None,
701
elif len(revision) > 1:
702
raise BzrCommandError(
703
'bzr checkout --revision takes exactly 1 revision value')
704
if branch_location is None:
705
branch_location = bzrlib.osutils.getcwd()
706
to_location = branch_location
707
source = Branch.open(branch_location)
708
if len(revision) == 1 and revision[0] is not None:
709
revision_id = revision[0].in_history(source)[1]
712
if to_location is None:
713
to_location = os.path.basename(branch_location.rstrip("/\\"))
714
# if the source and to_location are the same,
715
# and there is no working tree,
716
# then reconstitute a branch
717
if (bzrlib.osutils.abspath(to_location) ==
718
bzrlib.osutils.abspath(branch_location)):
720
source.bzrdir.open_workingtree()
721
except errors.NoWorkingTree:
722
source.bzrdir.create_workingtree()
725
os.mkdir(to_location)
727
if e.errno == errno.EEXIST:
728
raise BzrCommandError('Target directory "%s" already'
729
' exists.' % to_location)
730
if e.errno == errno.ENOENT:
731
raise BzrCommandError('Parent of "%s" does not exist.' %
735
old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
736
bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
739
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
740
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
742
checkout_branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
743
to_location, force_new_tree=False)
744
checkout = checkout_branch.bzrdir
745
checkout_branch.bind(source)
746
if revision_id is not None:
747
rh = checkout_branch.revision_history()
748
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
749
checkout.create_workingtree(revision_id)
751
bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
754
class cmd_renames(Command):
755
"""Show list of renamed files.
757
# TODO: Option to show renames between two historical versions.
759
# TODO: Only show renames under dir, rather than in the whole branch.
760
takes_args = ['dir?']
763
def run(self, dir=u'.'):
764
tree = WorkingTree.open_containing(dir)[0]
765
old_inv = tree.basis_tree().inventory
766
new_inv = tree.read_working_inventory()
768
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
770
for old_name, new_name in renames:
771
self.outf.write("%s => %s\n" % (old_name, new_name))
774
class cmd_update(Command):
775
"""Update a tree to have the latest code committed to its branch.
777
This will perform a merge into the working tree, and may generate
778
conflicts. If you have any local changes, you will still
779
need to commit them after the update for the update to be complete.
781
If you want to discard your local changes, you can just do a
782
'bzr revert' instead of 'bzr commit' after the update.
784
takes_args = ['dir?']
786
def run(self, dir='.'):
787
tree = WorkingTree.open_containing(dir)[0]
790
if tree.last_revision() == tree.branch.last_revision():
791
# may be up to date, check master too.
792
master = tree.branch.get_master_branch()
793
if master is None or master.last_revision == tree.last_revision():
794
note("Tree is up to date.")
796
conflicts = tree.update()
797
note('Updated to revision %d.' %
798
(tree.branch.revision_id_to_revno(tree.last_revision()),))
807
class cmd_info(Command):
808
"""Show information about a working tree, branch or repository.
810
This command will show all known locations and formats associated to the
811
tree, branch or repository. Statistical information is included with
814
Branches and working trees will also report any missing revisions.
816
takes_args = ['location?']
817
takes_options = ['verbose']
820
def run(self, location=None, verbose=False):
821
from bzrlib.info import show_bzrdir_info
822
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
826
class cmd_remove(Command):
827
"""Make a file unversioned.
829
This makes bzr stop tracking changes to a versioned file. It does
830
not delete the working copy.
832
You can specify one or more files, and/or --new. If you specify --new,
833
only 'added' files will be removed. If you specify both, then new files
834
in the specified directories will be removed. If the directories are
835
also new, they will also be removed.
837
takes_args = ['file*']
838
takes_options = ['verbose', Option('new', help='remove newly-added files')]
841
def run(self, file_list, verbose=False, new=False):
842
tree, file_list = tree_files(file_list)
844
if file_list is None:
845
raise BzrCommandError('Specify one or more files to remove, or'
848
from bzrlib.delta import compare_trees
849
added = [compare_trees(tree.basis_tree(), tree,
850
specific_files=file_list).added]
851
file_list = sorted([f[0] for f in added[0]], reverse=True)
852
if len(file_list) == 0:
853
raise BzrCommandError('No matching files.')
854
tree.remove(file_list, verbose=verbose)
857
class cmd_file_id(Command):
858
"""Print file_id of a particular file or directory.
860
The file_id is assigned when the file is first added and remains the
861
same through all revisions where the file exists, even when it is
865
takes_args = ['filename']
868
def run(self, filename):
869
tree, relpath = WorkingTree.open_containing(filename)
870
i = tree.inventory.path2id(relpath)
872
raise BzrError("%r is not a versioned file" % filename)
875
self.outf.write('\n')
878
class cmd_file_path(Command):
879
"""Print path of file_ids to a file or directory.
881
This prints one line for each directory down to the target,
882
starting at the branch root.
885
takes_args = ['filename']
888
def run(self, filename):
889
tree, relpath = WorkingTree.open_containing(filename)
891
fid = inv.path2id(relpath)
893
raise BzrError("%r is not a versioned file" % filename)
894
for fip in inv.get_idpath(fid):
896
self.outf.write('\n')
899
class cmd_reconcile(Command):
900
"""Reconcile bzr metadata in a branch.
902
This can correct data mismatches that may have been caused by
903
previous ghost operations or bzr upgrades. You should only
904
need to run this command if 'bzr check' or a bzr developer
905
advises you to run it.
907
If a second branch is provided, cross-branch reconciliation is
908
also attempted, which will check that data like the tree root
909
id which was not present in very early bzr versions is represented
910
correctly in both branches.
912
At the same time it is run it may recompress data resulting in
913
a potential saving in disk space or performance gain.
915
The branch *MUST* be on a listable system such as local disk or sftp.
917
takes_args = ['branch?']
919
def run(self, branch="."):
920
from bzrlib.reconcile import reconcile
921
dir = bzrlib.bzrdir.BzrDir.open(branch)
925
class cmd_revision_history(Command):
926
"""Display list of revision ids on this branch."""
931
branch = WorkingTree.open_containing(u'.')[0].branch
932
for patchid in branch.revision_history():
933
self.outf.write(patchid)
934
self.outf.write('\n')
937
class cmd_ancestry(Command):
938
"""List all revisions merged into this branch."""
943
tree = WorkingTree.open_containing(u'.')[0]
945
# FIXME. should be tree.last_revision
946
revision_ids = b.repository.get_ancestry(b.last_revision())
947
assert revision_ids[0] == None
949
for revision_id in revision_ids:
950
self.outf.write(revision_id + '\n')
953
class cmd_init(Command):
954
"""Make a directory into a versioned branch.
956
Use this to create an empty branch, or before importing an
959
If there is a repository in a parent directory of the location, then
960
the history of the branch will be stored in the repository. Otherwise
961
init creates a standalone branch which carries its own history in
964
If there is already a branch at the location but it has no working tree,
965
the tree can be populated with 'bzr checkout'.
967
Recipe for importing a tree of files:
972
bzr commit -m 'imported project'
974
takes_args = ['location?']
977
help='Specify a format for this branch. Current'
978
' formats are: default, knit, metaweave and'
979
' weave. Default is knit; metaweave and'
980
' weave are deprecated',
981
type=get_format_type),
983
def run(self, location=None, format=None):
984
from bzrlib.branch import Branch
986
format = get_format_type('default')
990
# The path has to exist to initialize a
991
# branch inside of it.
992
# Just using os.mkdir, since I don't
993
# believe that we want to create a bunch of
994
# locations if the user supplies an extended path
995
if not os.path.exists(location):
998
existing_bzrdir = bzrdir.BzrDir.open(location)
999
except NotBranchError:
1000
# really a NotBzrDir error...
1001
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1003
if existing_bzrdir.has_branch():
1004
if existing_bzrdir.has_workingtree():
1005
raise errors.AlreadyBranchError(location)
1007
raise errors.BranchExistsWithoutWorkingTree(location)
1009
existing_bzrdir.create_branch()
1010
existing_bzrdir.create_workingtree()
1013
class cmd_init_repository(Command):
1014
"""Create a shared repository to hold branches.
1016
New branches created under the repository directory will store their revisions
1017
in the repository, not in the branch directory, if the branch format supports
1023
bzr checkout --lightweight repo/trunk trunk-checkout
1027
takes_args = ["location"]
1028
takes_options = [Option('format',
1029
help='Specify a format for this repository.'
1030
' Current formats are: default, knit,'
1031
' metaweave and weave. Default is knit;'
1032
' metaweave and weave are deprecated',
1033
type=get_format_type),
1035
help='Allows branches in repository to have'
1037
aliases = ["init-repo"]
1038
def run(self, location, format=None, trees=False):
1039
from bzrlib.transport import get_transport
1041
format = get_format_type('default')
1042
transport = get_transport(location)
1043
if not transport.has('.'):
1045
newdir = format.initialize_on_transport(transport)
1046
repo = newdir.create_repository(shared=True)
1047
repo.set_make_working_trees(trees)
1050
class cmd_diff(Command):
1051
"""Show differences in working tree.
1053
If files are listed, only the changes in those files are listed.
1054
Otherwise, all changes for the tree are listed.
1056
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1057
produces patches suitable for "patch -p1".
1063
bzr diff --diff-prefix old/:new/
1064
bzr diff bzr.mine bzr.dev
1067
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1068
# or a graphical diff.
1070
# TODO: Python difflib is not exactly the same as unidiff; should
1071
# either fix it up or prefer to use an external diff.
1073
# TODO: Selected-file diff is inefficient and doesn't show you
1076
# TODO: This probably handles non-Unix newlines poorly.
1078
takes_args = ['file*']
1079
takes_options = ['revision', 'diff-options', 'prefix']
1080
aliases = ['di', 'dif']
1081
encoding_type = 'exact'
1084
def run(self, revision=None, file_list=None, diff_options=None,
1086
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1088
if (prefix is None) or (prefix == '0'):
1096
if not ':' in prefix:
1097
raise BzrError("--diff-prefix expects two values separated by a colon")
1098
old_label, new_label = prefix.split(":")
1101
tree1, file_list = internal_tree_files(file_list)
1105
except FileInWrongBranch:
1106
if len(file_list) != 2:
1107
raise BzrCommandError("Files are in different branches")
1109
tree1, file1 = WorkingTree.open_containing(file_list[0])
1110
tree2, file2 = WorkingTree.open_containing(file_list[1])
1111
if file1 != "" or file2 != "":
1112
# FIXME diff those two files. rbc 20051123
1113
raise BzrCommandError("Files are in different branches")
1115
if revision is not None:
1116
if tree2 is not None:
1117
raise BzrCommandError("Can't specify -r with two branches")
1118
if (len(revision) == 1) or (revision[1].spec is None):
1119
return diff_cmd_helper(tree1, file_list, diff_options,
1121
old_label=old_label, new_label=new_label)
1122
elif len(revision) == 2:
1123
return diff_cmd_helper(tree1, file_list, diff_options,
1124
revision[0], revision[1],
1125
old_label=old_label, new_label=new_label)
1127
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1129
if tree2 is not None:
1130
return show_diff_trees(tree1, tree2, sys.stdout,
1131
specific_files=file_list,
1132
external_diff_options=diff_options,
1133
old_label=old_label, new_label=new_label)
1135
return diff_cmd_helper(tree1, file_list, diff_options,
1136
old_label=old_label, new_label=new_label)
1139
class cmd_deleted(Command):
1140
"""List files deleted in the working tree.
1142
# TODO: Show files deleted since a previous revision, or
1143
# between two revisions.
1144
# TODO: Much more efficient way to do this: read in new
1145
# directories with readdir, rather than stating each one. Same
1146
# level of effort but possibly much less IO. (Or possibly not,
1147
# if the directories are very large...)
1148
takes_options = ['show-ids']
1151
def run(self, show_ids=False):
1152
tree = WorkingTree.open_containing(u'.')[0]
1153
old = tree.basis_tree()
1154
for path, ie in old.inventory.iter_entries():
1155
if not tree.has_id(ie.file_id):
1156
self.outf.write(path)
1158
self.outf.write(' ')
1159
self.outf.write(ie.file_id)
1160
self.outf.write('\n')
1163
class cmd_modified(Command):
1164
"""List files modified in working tree."""
1168
from bzrlib.delta import compare_trees
1170
tree = WorkingTree.open_containing(u'.')[0]
1171
td = compare_trees(tree.basis_tree(), tree)
1173
for path, id, kind, text_modified, meta_modified in td.modified:
1174
self.outf.write(path)
1175
self.outf.write('\n')
1178
class cmd_added(Command):
1179
"""List files added in working tree."""
1183
wt = WorkingTree.open_containing(u'.')[0]
1184
basis_inv = wt.basis_tree().inventory
1187
if file_id in basis_inv:
1189
path = inv.id2path(file_id)
1190
if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1192
self.outf.write(path)
1193
self.outf.write('\n')
1196
class cmd_root(Command):
1197
"""Show the tree root directory.
1199
The root is the nearest enclosing directory with a .bzr control
1201
takes_args = ['filename?']
1203
def run(self, filename=None):
1204
"""Print the branch root."""
1205
tree = WorkingTree.open_containing(filename)[0]
1206
self.outf.write(tree.basedir)
1207
self.outf.write('\n')
1210
class cmd_log(Command):
1211
"""Show log of a branch, file, or directory.
1213
By default show the log of the branch containing the working directory.
1215
To request a range of logs, you can use the command -r begin..end
1216
-r revision requests a specific revision, -r ..end or -r begin.. are
1222
bzr log -r -10.. http://server/branch
1225
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1227
takes_args = ['location?']
1228
takes_options = [Option('forward',
1229
help='show from oldest to newest'),
1232
help='show files changed in each revision'),
1233
'show-ids', 'revision',
1237
help='show revisions whose message matches this regexp',
1241
encoding_type = 'replace'
1244
def run(self, location=None, timezone='original',
1254
from bzrlib.log import log_formatter, show_log
1255
assert message is None or isinstance(message, basestring), \
1256
"invalid message argument %r" % message
1257
direction = (forward and 'forward') or 'reverse'
1262
# find the file id to log:
1264
dir, fp = bzrdir.BzrDir.open_containing(location)
1265
b = dir.open_branch()
1269
inv = dir.open_workingtree().inventory
1270
except (errors.NotBranchError, errors.NotLocalUrl):
1271
# either no tree, or is remote.
1272
inv = b.basis_tree().inventory
1273
file_id = inv.path2id(fp)
1276
# FIXME ? log the current subdir only RBC 20060203
1277
dir, relpath = bzrdir.BzrDir.open_containing('.')
1278
b = dir.open_branch()
1280
if revision is None:
1283
elif len(revision) == 1:
1284
rev1 = rev2 = revision[0].in_history(b).revno
1285
elif len(revision) == 2:
1286
if revision[0].spec is None:
1287
# missing begin-range means first revision
1290
rev1 = revision[0].in_history(b).revno
1292
if revision[1].spec is None:
1293
# missing end-range means last known revision
1296
rev2 = revision[1].in_history(b).revno
1298
raise BzrCommandError('bzr log --revision takes one or two values.')
1300
# By this point, the revision numbers are converted to the +ve
1301
# form if they were supplied in the -ve form, so we can do
1302
# this comparison in relative safety
1304
(rev2, rev1) = (rev1, rev2)
1306
if (log_format == None):
1307
default = bzrlib.config.BranchConfig(b).log_format()
1308
log_format = get_log_format(long=long, short=short, line=line, default=default)
1309
lf = log_formatter(log_format,
1312
show_timezone=timezone)
1318
direction=direction,
1319
start_revision=rev1,
1324
def get_log_format(long=False, short=False, line=False, default='long'):
1325
log_format = default
1329
log_format = 'short'
1335
class cmd_touching_revisions(Command):
1336
"""Return revision-ids which affected a particular file.
1338
A more user-friendly interface is "bzr log FILE"."""
1340
takes_args = ["filename"]
1341
encoding_type = 'replace'
1344
def run(self, filename):
1345
tree, relpath = WorkingTree.open_containing(filename)
1347
inv = tree.read_working_inventory()
1348
file_id = inv.path2id(relpath)
1349
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1350
self.outf.write("%6d %s\n" % (revno, what))
1353
class cmd_ls(Command):
1354
"""List files in a tree.
1356
# TODO: Take a revision or remote path and list that tree instead.
1358
takes_options = ['verbose', 'revision',
1359
Option('non-recursive',
1360
help='don\'t recurse into sub-directories'),
1362
help='Print all paths from the root of the branch.'),
1363
Option('unknown', help='Print unknown files'),
1364
Option('versioned', help='Print versioned files'),
1365
Option('ignored', help='Print ignored files'),
1367
Option('null', help='Null separate the files'),
1370
def run(self, revision=None, verbose=False,
1371
non_recursive=False, from_root=False,
1372
unknown=False, versioned=False, ignored=False,
1375
if verbose and null:
1376
raise BzrCommandError('Cannot set both --verbose and --null')
1377
all = not (unknown or versioned or ignored)
1379
selection = {'I':ignored, '?':unknown, 'V':versioned}
1381
tree, relpath = WorkingTree.open_containing(u'.')
1386
if revision is not None:
1387
tree = tree.branch.repository.revision_tree(
1388
revision[0].in_history(tree.branch).rev_id)
1390
for fp, fc, kind, fid, entry in tree.list_files():
1391
if fp.startswith(relpath):
1392
fp = fp[len(relpath):]
1393
if non_recursive and '/' in fp:
1395
if not all and not selection[fc]:
1398
kindch = entry.kind_character()
1399
self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1402
self.outf.write('\0')
1406
self.outf.write('\n')
1409
class cmd_unknowns(Command):
1410
"""List unknown files."""
1413
from bzrlib.osutils import quotefn
1414
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1415
self.outf.write(quotefn(f))
1416
self.outf.write('\n')
1419
class cmd_ignore(Command):
1420
"""Ignore a command or pattern.
1422
To remove patterns from the ignore list, edit the .bzrignore file.
1424
If the pattern contains a slash, it is compared to the whole path
1425
from the branch root. Otherwise, it is compared to only the last
1426
component of the path. To match a file only in the root directory,
1429
Ignore patterns are case-insensitive on case-insensitive systems.
1431
Note: wildcards must be quoted from the shell on Unix.
1434
bzr ignore ./Makefile
1435
bzr ignore '*.class'
1437
# TODO: Complain if the filename is absolute
1438
takes_args = ['name_pattern']
1440
def run(self, name_pattern):
1441
from bzrlib.atomicfile import AtomicFile
1444
tree, relpath = WorkingTree.open_containing(u'.')
1445
ifn = tree.abspath('.bzrignore')
1447
if os.path.exists(ifn):
1450
igns = f.read().decode('utf-8')
1456
# TODO: If the file already uses crlf-style termination, maybe
1457
# we should use that for the newly added lines?
1459
if igns and igns[-1] != '\n':
1461
igns += name_pattern + '\n'
1463
f = AtomicFile(ifn, 'wt')
1465
f.write(igns.encode('utf-8'))
1470
inv = tree.inventory
1471
if inv.path2id('.bzrignore'):
1472
mutter('.bzrignore is already versioned')
1474
mutter('need to make new .bzrignore file versioned')
1475
tree.add(['.bzrignore'])
1478
class cmd_ignored(Command):
1479
"""List ignored files and the patterns that matched them.
1481
See also: bzr ignore"""
1484
tree = WorkingTree.open_containing(u'.')[0]
1485
for path, file_class, kind, file_id, entry in tree.list_files():
1486
if file_class != 'I':
1488
## XXX: Slightly inefficient since this was already calculated
1489
pat = tree.is_ignored(path)
1490
print '%-50s %s' % (path, pat)
1493
class cmd_lookup_revision(Command):
1494
"""Lookup the revision-id from a revision-number
1497
bzr lookup-revision 33
1500
takes_args = ['revno']
1503
def run(self, revno):
1507
raise BzrCommandError("not a valid revision-number: %r" % revno)
1509
print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1512
class cmd_export(Command):
1513
"""Export past revision to destination directory.
1515
If no revision is specified this exports the last committed revision.
1517
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
1518
given, try to find the format with the extension. If no extension
1519
is found exports to a directory (equivalent to --format=dir).
1521
Root may be the top directory for tar, tgz and tbz2 formats. If none
1522
is given, the top directory will be the root name of the file.
1524
Note: export of tree with non-ascii filenames to zip is not supported.
1526
Supported formats Autodetected by extension
1527
----------------- -------------------------
1530
tbz2 .tar.bz2, .tbz2
1534
takes_args = ['dest']
1535
takes_options = ['revision', 'format', 'root']
1536
def run(self, dest, revision=None, format=None, root=None):
1538
from bzrlib.export import export
1539
tree = WorkingTree.open_containing(u'.')[0]
1541
if revision is None:
1542
# should be tree.last_revision FIXME
1543
rev_id = b.last_revision()
1545
if len(revision) != 1:
1546
raise BzrError('bzr export --revision takes exactly 1 argument')
1547
rev_id = revision[0].in_history(b).rev_id
1548
t = b.repository.revision_tree(rev_id)
1550
export(t, dest, format, root)
1551
except errors.NoSuchExportFormat, e:
1552
raise BzrCommandError('Unsupported export format: %s' % e.format)
1555
class cmd_cat(Command):
1556
"""Write a file's text from a previous revision."""
1558
takes_options = ['revision']
1559
takes_args = ['filename']
1562
def run(self, filename, revision=None):
1563
if revision is not None and len(revision) != 1:
1564
raise BzrCommandError("bzr cat --revision takes exactly one number")
1567
tree, relpath = WorkingTree.open_containing(filename)
1569
except NotBranchError:
1573
b, relpath = Branch.open_containing(filename)
1574
if revision is None:
1575
revision_id = b.last_revision()
1577
revision_id = revision[0].in_history(b).rev_id
1578
b.print_file(relpath, revision_id)
1581
class cmd_local_time_offset(Command):
1582
"""Show the offset in seconds from GMT to local time."""
1586
print bzrlib.osutils.local_time_offset()
1590
class cmd_commit(Command):
1591
"""Commit changes into a new revision.
1593
If no arguments are given, the entire tree is committed.
1595
If selected files are specified, only changes to those files are
1596
committed. If a directory is specified then the directory and everything
1597
within it is committed.
1599
A selected-file commit may fail in some cases where the committed
1600
tree would be invalid, such as trying to commit a file in a
1601
newly-added directory that is not itself committed.
1603
# TODO: Run hooks on tree to-be-committed, and after commit.
1605
# TODO: Strict commit that fails if there are deleted files.
1606
# (what does "deleted files" mean ??)
1608
# TODO: Give better message for -s, --summary, used by tla people
1610
# XXX: verbose currently does nothing
1612
takes_args = ['selected*']
1613
takes_options = ['message', 'verbose',
1615
help='commit even if nothing has changed'),
1616
Option('file', type=str,
1618
help='file containing commit message'),
1620
help="refuse to commit if there are unknown "
1621
"files in the working tree."),
1623
help="perform a local only commit in a bound "
1624
"branch. Such commits are not pushed to "
1625
"the master branch until a normal commit "
1629
aliases = ['ci', 'checkin']
1631
def run(self, message=None, file=None, verbose=True, selected_list=None,
1632
unchanged=False, strict=False, local=False):
1633
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
1634
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1636
from bzrlib.msgeditor import edit_commit_message, \
1637
make_commit_message_template
1638
from tempfile import TemporaryFile
1640
# TODO: Need a blackbox test for invoking the external editor; may be
1641
# slightly problematic to run this cross-platform.
1643
# TODO: do more checks that the commit will succeed before
1644
# spending the user's valuable time typing a commit message.
1646
# TODO: if the commit *does* happen to fail, then save the commit
1647
# message to a temporary file where it can be recovered
1648
tree, selected_list = tree_files(selected_list)
1649
if selected_list == ['']:
1650
# workaround - commit of root of tree should be exactly the same
1651
# as just default commit in that tree, and succeed even though
1652
# selected-file merge commit is not done yet
1655
if local and not tree.branch.get_bound_location():
1656
raise errors.LocalRequiresBoundBranch()
1657
if message is None and not file:
1658
template = make_commit_message_template(tree, selected_list)
1659
message = edit_commit_message(template)
1661
raise BzrCommandError("please specify a commit message"
1662
" with either --message or --file")
1663
elif message and file:
1664
raise BzrCommandError("please specify either --message or --file")
1667
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1670
raise BzrCommandError("empty commit message specified")
1673
reporter = ReportCommitToLog()
1675
reporter = NullCommitReporter()
1678
tree.commit(message, specific_files=selected_list,
1679
allow_pointless=unchanged, strict=strict, local=local,
1681
except PointlessCommit:
1682
# FIXME: This should really happen before the file is read in;
1683
# perhaps prepare the commit; get the message; then actually commit
1684
raise BzrCommandError("no changes to commit",
1685
["use --unchanged to commit anyhow"])
1686
except ConflictsInTree:
1687
raise BzrCommandError("Conflicts detected in working tree. "
1688
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1689
except StrictCommitFailed:
1690
raise BzrCommandError("Commit refused because there are unknown "
1691
"files in the working tree.")
1692
except errors.BoundBranchOutOfDate, e:
1693
raise BzrCommandError(str(e)
1694
+ ' Either unbind, update, or'
1695
' pass --local to commit.')
1698
class cmd_check(Command):
1699
"""Validate consistency of branch history.
1701
This command checks various invariants about the branch storage to
1702
detect data corruption or bzr bugs.
1704
takes_args = ['branch?']
1705
takes_options = ['verbose']
1707
def run(self, branch=None, verbose=False):
1708
from bzrlib.check import check
1710
tree = WorkingTree.open_containing()[0]
1711
branch = tree.branch
1713
branch = Branch.open(branch)
1714
check(branch, verbose)
1717
class cmd_scan_cache(Command):
1720
from bzrlib.hashcache import HashCache
1726
print '%6d stats' % c.stat_count
1727
print '%6d in hashcache' % len(c._cache)
1728
print '%6d files removed from cache' % c.removed_count
1729
print '%6d hashes updated' % c.update_count
1730
print '%6d files changed too recently to cache' % c.danger_count
1736
class cmd_upgrade(Command):
1737
"""Upgrade branch storage to current format.
1739
The check command or bzr developers may sometimes advise you to run
1740
this command. When the default format has changed you may also be warned
1741
during other operations to upgrade.
1743
takes_args = ['url?']
1746
help='Upgrade to a specific format. Current formats'
1747
' are: default, knit, metaweave and weave.'
1748
' Default is knit; metaweave and weave are'
1750
type=get_format_type),
1754
def run(self, url='.', format=None):
1755
from bzrlib.upgrade import upgrade
1757
format = get_format_type('default')
1758
upgrade(url, format)
1761
class cmd_whoami(Command):
1762
"""Show bzr user id."""
1763
takes_options = ['email']
1766
def run(self, email=False):
1768
b = WorkingTree.open_containing(u'.')[0].branch
1769
config = bzrlib.config.BranchConfig(b)
1770
except NotBranchError:
1771
config = bzrlib.config.GlobalConfig()
1774
print config.user_email()
1776
print config.username()
1779
class cmd_nick(Command):
1780
"""Print or set the branch nickname.
1782
If unset, the tree root directory name is used as the nickname
1783
To print the current nickname, execute with no argument.
1785
takes_args = ['nickname?']
1786
def run(self, nickname=None):
1787
branch = Branch.open_containing(u'.')[0]
1788
if nickname is None:
1789
self.printme(branch)
1791
branch.nick = nickname
1794
def printme(self, branch):
1798
class cmd_selftest(Command):
1799
"""Run internal test suite.
1801
This creates temporary test directories in the working directory,
1802
but not existing data is affected. These directories are deleted
1803
if the tests pass, or left behind to help in debugging if they
1804
fail and --keep-output is specified.
1806
If arguments are given, they are regular expressions that say
1807
which tests should run.
1809
If the global option '--no-plugins' is given, plugins are not loaded
1810
before running the selftests. This has two effects: features provided or
1811
modified by plugins will not be tested, and tests provided by plugins will
1816
bzr --no-plugins selftest -v
1818
# TODO: --list should give a list of all available tests
1820
# NB: this is used from the class without creating an instance, which is
1821
# why it does not have a self parameter.
1822
def get_transport_type(typestring):
1823
"""Parse and return a transport specifier."""
1824
if typestring == "sftp":
1825
from bzrlib.transport.sftp import SFTPAbsoluteServer
1826
return SFTPAbsoluteServer
1827
if typestring == "memory":
1828
from bzrlib.transport.memory import MemoryServer
1830
if typestring == "fakenfs":
1831
from bzrlib.transport.fakenfs import FakeNFSServer
1832
return FakeNFSServer
1833
msg = "No known transport type %s. Supported types are: sftp\n" %\
1835
raise BzrCommandError(msg)
1838
takes_args = ['testspecs*']
1839
takes_options = ['verbose',
1840
Option('one', help='stop when one test fails'),
1841
Option('keep-output',
1842
help='keep output directories when tests fail'),
1844
help='Use a different transport by default '
1845
'throughout the test suite.',
1846
type=get_transport_type),
1847
Option('benchmark', help='run the bzr bencharks.'),
1848
Option('lsprof-timed',
1849
help='generate lsprof output for benchmarked'
1850
' sections of code.'),
1853
def run(self, testspecs_list=None, verbose=None, one=False,
1854
keep_output=False, transport=None, benchmark=None,
1857
from bzrlib.tests import selftest
1858
import bzrlib.benchmarks as benchmarks
1859
# we don't want progress meters from the tests to go to the
1860
# real output; and we don't want log messages cluttering up
1862
save_ui = bzrlib.ui.ui_factory
1863
print '%10s: %s' % ('bzr', bzrlib.osutils.realpath(sys.argv[0]))
1864
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1866
bzrlib.trace.info('running tests...')
1868
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1869
if testspecs_list is not None:
1870
pattern = '|'.join(testspecs_list)
1874
test_suite_factory = benchmarks.test_suite
1878
test_suite_factory = None
1881
result = selftest(verbose=verbose,
1883
stop_on_failure=one,
1884
keep_output=keep_output,
1885
transport=transport,
1886
test_suite_factory=test_suite_factory,
1887
lsprof_timed=lsprof_timed)
1889
bzrlib.trace.info('tests passed')
1891
bzrlib.trace.info('tests failed')
1892
return int(not result)
1894
bzrlib.ui.ui_factory = save_ui
1897
def _get_bzr_branch():
1898
"""If bzr is run from a branch, return Branch or None"""
1899
import bzrlib.errors
1900
from bzrlib.branch import Branch
1901
from bzrlib.osutils import abspath
1902
from os.path import dirname
1905
branch = Branch.open(dirname(abspath(dirname(__file__))))
1907
except bzrlib.errors.BzrError:
1912
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1913
# is bzrlib itself in a branch?
1914
branch = _get_bzr_branch()
1916
rh = branch.revision_history()
1918
print " bzr checkout, revision %d" % (revno,)
1919
print " nick: %s" % (branch.nick,)
1921
print " revid: %s" % (rh[-1],)
1922
print "Using python interpreter:", sys.executable
1924
print "Using python standard library:", os.path.dirname(site.__file__)
1925
print "Using bzrlib:",
1926
if len(bzrlib.__path__) > 1:
1927
# print repr, which is a good enough way of making it clear it's
1928
# more than one element (eg ['/foo/bar', '/foo/bzr'])
1929
print repr(bzrlib.__path__)
1931
print bzrlib.__path__[0]
1934
print bzrlib.__copyright__
1935
print "http://bazaar-vcs.org/"
1937
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1938
print "you may use, modify and redistribute it under the terms of the GNU"
1939
print "General Public License version 2 or later."
1942
class cmd_version(Command):
1943
"""Show version of bzr."""
1948
class cmd_rocks(Command):
1949
"""Statement of optimism."""
1953
print "it sure does!"
1956
class cmd_find_merge_base(Command):
1957
"""Find and print a base revision for merging two branches.
1959
# TODO: Options to specify revisions on either side, as if
1960
# merging only part of the history.
1961
takes_args = ['branch', 'other']
1965
def run(self, branch, other):
1966
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1968
branch1 = Branch.open_containing(branch)[0]
1969
branch2 = Branch.open_containing(other)[0]
1971
history_1 = branch1.revision_history()
1972
history_2 = branch2.revision_history()
1974
last1 = branch1.last_revision()
1975
last2 = branch2.last_revision()
1977
source = MultipleRevisionSources(branch1.repository,
1980
base_rev_id = common_ancestor(last1, last2, source)
1982
print 'merge base is revision %s' % base_rev_id
1986
if base_revno is None:
1987
raise bzrlib.errors.UnrelatedBranches()
1989
print ' r%-6d in %s' % (base_revno, branch)
1991
other_revno = branch2.revision_id_to_revno(base_revid)
1993
print ' r%-6d in %s' % (other_revno, other)
1997
class cmd_merge(Command):
1998
"""Perform a three-way merge.
2000
The branch is the branch you will merge from. By default, it will
2001
merge the latest revision. If you specify a revision, that
2002
revision will be merged. If you specify two revisions, the first
2003
will be used as a BASE, and the second one as OTHER. Revision
2004
numbers are always relative to the specified branch.
2006
By default, bzr will try to merge in all new work from the other
2007
branch, automatically determining an appropriate base. If this
2008
fails, you may need to give an explicit base.
2010
Merge will do its best to combine the changes in two branches, but there
2011
are some kinds of problems only a human can fix. When it encounters those,
2012
it will mark a conflict. A conflict means that you need to fix something,
2013
before you should commit.
2015
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2017
If there is no default branch set, the first merge will set it. After
2018
that, you can omit the branch to use the default. To change the
2019
default, use --remember.
2023
To merge the latest revision from bzr.dev
2024
bzr merge ../bzr.dev
2026
To merge changes up to and including revision 82 from bzr.dev
2027
bzr merge -r 82 ../bzr.dev
2029
To merge the changes introduced by 82, without previous changes:
2030
bzr merge -r 81..82 ../bzr.dev
2032
merge refuses to run if there are any uncommitted changes, unless
2035
The following merge types are available:
2037
takes_args = ['branch?']
2038
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2039
Option('show-base', help="Show base revision text in "
2043
from merge import merge_type_help
2044
from inspect import getdoc
2045
return getdoc(self) + '\n' + merge_type_help()
2047
def run(self, branch=None, revision=None, force=False, merge_type=None,
2048
show_base=False, reprocess=False, remember=False):
2049
if merge_type is None:
2050
merge_type = Merge3Merger
2052
tree = WorkingTree.open_containing(u'.')[0]
2055
if branch is not None:
2056
reader = BundleReader(file(branch, 'rb'))
2060
if e.errno not in (errno.ENOENT, errno.EISDIR):
2065
if reader is not None:
2066
conflicts = merge_bundle(reader, tree, not force, merge_type,
2067
reprocess, show_base)
2073
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2075
if tree.branch.get_parent() is None or remember:
2076
tree.branch.set_parent(branch)
2078
if revision is None or len(revision) < 1:
2080
other = [branch, -1]
2081
other_branch, path = Branch.open_containing(branch)
2083
if len(revision) == 1:
2085
other_branch, path = Branch.open_containing(branch)
2086
revno = revision[0].in_history(other_branch).revno
2087
other = [branch, revno]
2089
assert len(revision) == 2
2090
if None in revision:
2091
raise BzrCommandError(
2092
"Merge doesn't permit that revision specifier.")
2093
other_branch, path = Branch.open_containing(branch)
2095
base = [branch, revision[0].in_history(other_branch).revno]
2096
other = [branch, revision[1].in_history(other_branch).revno]
2098
if tree.branch.get_parent() is None or remember:
2099
tree.branch.set_parent(other_branch.base)
2102
interesting_files = [path]
2104
interesting_files = None
2105
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2108
conflict_count = merge(other, base, check_clean=(not force),
2109
merge_type=merge_type,
2110
reprocess=reprocess,
2111
show_base=show_base,
2112
pb=pb, file_list=interesting_files)
2115
if conflict_count != 0:
2119
except bzrlib.errors.AmbiguousBase, e:
2120
m = ("sorry, bzr can't determine the right merge base yet\n"
2121
"candidates are:\n "
2122
+ "\n ".join(e.bases)
2124
"please specify an explicit base with -r,\n"
2125
"and (if you want) report this to the bzr developers\n")
2128
# TODO: move up to common parent; this isn't merge-specific anymore.
2129
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2130
"""Use tree.branch's parent if none was supplied.
2132
Report if the remembered location was used.
2134
if supplied_location is not None:
2135
return supplied_location
2136
stored_location = tree.branch.get_parent()
2137
if stored_location is None:
2138
raise BzrCommandError("No location specified or remembered")
2139
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2140
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2141
return stored_location
2144
class cmd_remerge(Command):
2147
Use this if you want to try a different merge technique while resolving
2148
conflicts. Some merge techniques are better than others, and remerge
2149
lets you try different ones on different files.
2151
The options for remerge have the same meaning and defaults as the ones for
2152
merge. The difference is that remerge can (only) be run when there is a
2153
pending merge, and it lets you specify particular files.
2156
$ bzr remerge --show-base
2157
Re-do the merge of all conflicted files, and show the base text in
2158
conflict regions, in addition to the usual THIS and OTHER texts.
2160
$ bzr remerge --merge-type weave --reprocess foobar
2161
Re-do the merge of "foobar", using the weave merge algorithm, with
2162
additional processing to reduce the size of conflict regions.
2164
The following merge types are available:"""
2165
takes_args = ['file*']
2166
takes_options = ['merge-type', 'reprocess',
2167
Option('show-base', help="Show base revision text in "
2171
from merge import merge_type_help
2172
from inspect import getdoc
2173
return getdoc(self) + '\n' + merge_type_help()
2175
def run(self, file_list=None, merge_type=None, show_base=False,
2177
from bzrlib.merge import merge_inner, transform_tree
2178
if merge_type is None:
2179
merge_type = Merge3Merger
2180
tree, file_list = tree_files(file_list)
2183
pending_merges = tree.pending_merges()
2184
if len(pending_merges) != 1:
2185
raise BzrCommandError("Sorry, remerge only works after normal"
2186
+ " merges. Not cherrypicking or"
2188
repository = tree.branch.repository
2189
base_revision = common_ancestor(tree.branch.last_revision(),
2190
pending_merges[0], repository)
2191
base_tree = repository.revision_tree(base_revision)
2192
other_tree = repository.revision_tree(pending_merges[0])
2193
interesting_ids = None
2194
if file_list is not None:
2195
interesting_ids = set()
2196
for filename in file_list:
2197
file_id = tree.path2id(filename)
2199
raise NotVersionedError(filename)
2200
interesting_ids.add(file_id)
2201
if tree.kind(file_id) != "directory":
2204
for name, ie in tree.inventory.iter_entries(file_id):
2205
interesting_ids.add(ie.file_id)
2206
transform_tree(tree, tree.basis_tree(), interesting_ids)
2207
if file_list is None:
2208
restore_files = list(tree.iter_conflicts())
2210
restore_files = file_list
2211
for filename in restore_files:
2213
restore(tree.abspath(filename))
2214
except NotConflicted:
2216
conflicts = merge_inner(tree.branch, other_tree, base_tree,
2218
interesting_ids = interesting_ids,
2219
other_rev_id=pending_merges[0],
2220
merge_type=merge_type,
2221
show_base=show_base,
2222
reprocess=reprocess)
2230
class cmd_revert(Command):
2231
"""Reverse all changes since the last commit.
2233
Only versioned files are affected. Specify filenames to revert only
2234
those files. By default, any files that are changed will be backed up
2235
first. Backup files have a '~' appended to their name.
2237
takes_options = ['revision', 'no-backup']
2238
takes_args = ['file*']
2239
aliases = ['merge-revert']
2241
def run(self, revision=None, no_backup=False, file_list=None):
2242
from bzrlib.commands import parse_spec
2243
if file_list is not None:
2244
if len(file_list) == 0:
2245
raise BzrCommandError("No files specified")
2249
tree, file_list = tree_files(file_list)
2250
if revision is None:
2251
# FIXME should be tree.last_revision
2252
rev_id = tree.last_revision()
2253
elif len(revision) != 1:
2254
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2256
rev_id = revision[0].in_history(tree.branch).rev_id
2257
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2259
tree.revert(file_list,
2260
tree.branch.repository.revision_tree(rev_id),
2266
class cmd_assert_fail(Command):
2267
"""Test reporting of assertion failures"""
2270
assert False, "always fails"
2273
class cmd_help(Command):
2274
"""Show help on a command or other topic.
2276
For a list of all available commands, say 'bzr help commands'."""
2277
takes_options = [Option('long', 'show help on all commands')]
2278
takes_args = ['topic?']
2279
aliases = ['?', '--help', '-?', '-h']
2282
def run(self, topic=None, long=False):
2284
if topic is None and long:
2289
class cmd_shell_complete(Command):
2290
"""Show appropriate completions for context.
2292
For a list of all available commands, say 'bzr shell-complete'."""
2293
takes_args = ['context?']
2298
def run(self, context=None):
2299
import shellcomplete
2300
shellcomplete.shellcomplete(context)
2303
class cmd_fetch(Command):
2304
"""Copy in history from another branch but don't merge it.
2306
This is an internal method used for pull and merge."""
2308
takes_args = ['from_branch', 'to_branch']
2309
def run(self, from_branch, to_branch):
2310
from bzrlib.fetch import Fetcher
2311
from bzrlib.branch import Branch
2312
from_b = Branch.open(from_branch)
2313
to_b = Branch.open(to_branch)
2314
Fetcher(to_b, from_b)
2317
class cmd_missing(Command):
2318
"""Show unmerged/unpulled revisions between two branches.
2320
OTHER_BRANCH may be local or remote."""
2321
takes_args = ['other_branch?']
2322
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2324
'Display changes in the local branch only'),
2325
Option('theirs-only',
2326
'Display changes in the remote branch only'),
2335
def run(self, other_branch=None, reverse=False, mine_only=False,
2336
theirs_only=False, log_format=None, long=False, short=False, line=False,
2337
show_ids=False, verbose=False):
2338
from bzrlib.missing import find_unmerged, iter_log_data
2339
from bzrlib.log import log_formatter
2340
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2341
parent = local_branch.get_parent()
2342
if other_branch is None:
2343
other_branch = parent
2344
if other_branch is None:
2345
raise BzrCommandError("No missing location known or specified.")
2346
print "Using last location: " + local_branch.get_parent()
2347
remote_branch = bzrlib.branch.Branch.open(other_branch)
2348
if remote_branch.base == local_branch.base:
2349
remote_branch = local_branch
2350
local_branch.lock_read()
2352
remote_branch.lock_read()
2354
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2355
if (log_format == None):
2356
default = bzrlib.config.BranchConfig(local_branch).log_format()
2357
log_format = get_log_format(long=long, short=short, line=line, default=default)
2358
lf = log_formatter(log_format, sys.stdout,
2360
show_timezone='original')
2361
if reverse is False:
2362
local_extra.reverse()
2363
remote_extra.reverse()
2364
if local_extra and not theirs_only:
2365
print "You have %d extra revision(s):" % len(local_extra)
2366
for data in iter_log_data(local_extra, local_branch.repository,
2369
printed_local = True
2371
printed_local = False
2372
if remote_extra and not mine_only:
2373
if printed_local is True:
2375
print "You are missing %d revision(s):" % len(remote_extra)
2376
for data in iter_log_data(remote_extra, remote_branch.repository,
2379
if not remote_extra and not local_extra:
2381
print "Branches are up to date."
2385
remote_branch.unlock()
2387
local_branch.unlock()
2388
if not status_code and parent is None and other_branch is not None:
2389
local_branch.lock_write()
2391
# handle race conditions - a parent might be set while we run.
2392
if local_branch.get_parent() is None:
2393
local_branch.set_parent(remote_branch.base)
2395
local_branch.unlock()
2399
class cmd_plugins(Command):
2404
import bzrlib.plugin
2405
from inspect import getdoc
2406
for name, plugin in bzrlib.plugin.all_plugins().items():
2407
if hasattr(plugin, '__path__'):
2408
print plugin.__path__[0]
2409
elif hasattr(plugin, '__file__'):
2410
print plugin.__file__
2416
print '\t', d.split('\n')[0]
2419
class cmd_testament(Command):
2420
"""Show testament (signing-form) of a revision."""
2421
takes_options = ['revision', 'long']
2422
takes_args = ['branch?']
2424
def run(self, branch=u'.', revision=None, long=False):
2425
from bzrlib.testament import Testament
2426
b = WorkingTree.open_containing(branch)[0].branch
2429
if revision is None:
2430
rev_id = b.last_revision()
2432
rev_id = revision[0].in_history(b).rev_id
2433
t = Testament.from_revision(b.repository, rev_id)
2435
sys.stdout.writelines(t.as_text_lines())
2437
sys.stdout.write(t.as_short_text())
2442
class cmd_annotate(Command):
2443
"""Show the origin of each line in a file.
2445
This prints out the given file with an annotation on the left side
2446
indicating which revision, author and date introduced the change.
2448
If the origin is the same for a run of consecutive lines, it is
2449
shown only at the top, unless the --all option is given.
2451
# TODO: annotate directories; showing when each file was last changed
2452
# TODO: if the working copy is modified, show annotations on that
2453
# with new uncommitted lines marked
2454
aliases = ['blame', 'praise']
2455
takes_args = ['filename']
2456
takes_options = [Option('all', help='show annotations on all lines'),
2457
Option('long', help='show date in annotations'),
2462
def run(self, filename, all=False, long=False, revision=None):
2463
from bzrlib.annotate import annotate_file
2464
tree, relpath = WorkingTree.open_containing(filename)
2465
branch = tree.branch
2468
if revision is None:
2469
revision_id = branch.last_revision()
2470
elif len(revision) != 1:
2471
raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2473
revision_id = revision[0].in_history(branch).rev_id
2474
file_id = tree.inventory.path2id(relpath)
2475
tree = branch.repository.revision_tree(revision_id)
2476
file_version = tree.inventory[file_id].revision
2477
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2482
class cmd_re_sign(Command):
2483
"""Create a digital signature for an existing revision."""
2484
# TODO be able to replace existing ones.
2486
hidden = True # is this right ?
2487
takes_args = ['revision_id*']
2488
takes_options = ['revision']
2490
def run(self, revision_id_list=None, revision=None):
2491
import bzrlib.config as config
2492
import bzrlib.gpg as gpg
2493
if revision_id_list is not None and revision is not None:
2494
raise BzrCommandError('You can only supply one of revision_id or --revision')
2495
if revision_id_list is None and revision is None:
2496
raise BzrCommandError('You must supply either --revision or a revision_id')
2497
b = WorkingTree.open_containing(u'.')[0].branch
2498
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2499
if revision_id_list is not None:
2500
for revision_id in revision_id_list:
2501
b.repository.sign_revision(revision_id, gpg_strategy)
2502
elif revision is not None:
2503
if len(revision) == 1:
2504
revno, rev_id = revision[0].in_history(b)
2505
b.repository.sign_revision(rev_id, gpg_strategy)
2506
elif len(revision) == 2:
2507
# are they both on rh- if so we can walk between them
2508
# might be nice to have a range helper for arbitrary
2509
# revision paths. hmm.
2510
from_revno, from_revid = revision[0].in_history(b)
2511
to_revno, to_revid = revision[1].in_history(b)
2512
if to_revid is None:
2513
to_revno = b.revno()
2514
if from_revno is None or to_revno is None:
2515
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
2516
for revno in range(from_revno, to_revno + 1):
2517
b.repository.sign_revision(b.get_rev_id(revno),
2520
raise BzrCommandError('Please supply either one revision, or a range.')
2523
class cmd_bind(Command):
2524
"""Bind the current branch to a master branch.
2526
After binding, commits must succeed on the master branch
2527
before they are executed on the local one.
2530
takes_args = ['location']
2533
def run(self, location=None):
2534
b, relpath = Branch.open_containing(u'.')
2535
b_other = Branch.open(location)
2538
except DivergedBranches:
2539
raise BzrCommandError('These branches have diverged.'
2540
' Try merging, and then bind again.')
2543
class cmd_unbind(Command):
2544
"""Unbind the current branch from its master branch.
2546
After unbinding, the local branch is considered independent.
2547
All subsequent commits will be local.
2554
b, relpath = Branch.open_containing(u'.')
2556
raise BzrCommandError('Local branch is not bound')
2559
class cmd_uncommit(bzrlib.commands.Command):
2560
"""Remove the last committed revision.
2562
--verbose will print out what is being removed.
2563
--dry-run will go through all the motions, but not actually
2566
In the future, uncommit will create a revision bundle, which can then
2570
# TODO: jam 20060108 Add an option to allow uncommit to remove
2571
# unreferenced information in 'branch-as-repostory' branches.
2572
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2573
# information in shared branches as well.
2574
takes_options = ['verbose', 'revision',
2575
Option('dry-run', help='Don\'t actually make changes'),
2576
Option('force', help='Say yes to all questions.')]
2577
takes_args = ['location?']
2580
def run(self, location=None,
2581
dry_run=False, verbose=False,
2582
revision=None, force=False):
2583
from bzrlib.branch import Branch
2584
from bzrlib.log import log_formatter
2586
from bzrlib.uncommit import uncommit
2588
if location is None:
2590
control, relpath = bzrdir.BzrDir.open_containing(location)
2592
tree = control.open_workingtree()
2594
except (errors.NoWorkingTree, errors.NotLocalUrl):
2596
b = control.open_branch()
2598
if revision is None:
2600
rev_id = b.last_revision()
2602
revno, rev_id = revision[0].in_history(b)
2604
print 'No revisions to uncommit.'
2606
for r in range(revno, b.revno()+1):
2607
rev_id = b.get_rev_id(r)
2608
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2609
lf.show(r, b.repository.get_revision(rev_id), None)
2612
print 'Dry-run, pretending to remove the above revisions.'
2614
val = raw_input('Press <enter> to continue')
2616
print 'The above revision(s) will be removed.'
2618
val = raw_input('Are you sure [y/N]? ')
2619
if val.lower() not in ('y', 'yes'):
2623
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
2627
class cmd_break_lock(Command):
2628
"""Break a dead lock on a repository, branch or working directory.
2630
CAUTION: Locks should only be broken when you are sure that the process
2631
holding the lock has been stopped.
2633
You can get information on what locks are open via the 'bzr info' command.
2638
takes_args = ['location?']
2640
def run(self, location=None, show=False):
2641
if location is None:
2643
control, relpath = bzrdir.BzrDir.open_containing(location)
2645
control.break_lock()
2646
except NotImplementedError:
2651
# command-line interpretation helper for merge-related commands
2652
def merge(other_revision, base_revision,
2653
check_clean=True, ignore_zero=False,
2654
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2655
file_list=None, show_base=False, reprocess=False,
2656
pb=DummyProgress()):
2657
"""Merge changes into a tree.
2660
list(path, revno) Base for three-way merge.
2661
If [None, None] then a base will be automatically determined.
2663
list(path, revno) Other revision for three-way merge.
2665
Directory to merge changes into; '.' by default.
2667
If true, this_dir must have no uncommitted changes before the
2669
ignore_zero - If true, suppress the "zero conflicts" message when
2670
there are no conflicts; should be set when doing something we expect
2671
to complete perfectly.
2672
file_list - If supplied, merge only changes to selected files.
2674
All available ancestors of other_revision and base_revision are
2675
automatically pulled into the branch.
2677
The revno may be -1 to indicate the last revision on the branch, which is
2680
This function is intended for use from the command line; programmatic
2681
clients might prefer to call merge.merge_inner(), which has less magic
2684
from bzrlib.merge import Merger
2685
if this_dir is None:
2687
this_tree = WorkingTree.open_containing(this_dir)[0]
2688
if show_base and not merge_type is Merge3Merger:
2689
raise BzrCommandError("Show-base is not supported for this merge"
2690
" type. %s" % merge_type)
2691
if reprocess and not merge_type.supports_reprocess:
2692
raise BzrCommandError("Conflict reduction is not supported for merge"
2693
" type %s." % merge_type)
2694
if reprocess and show_base:
2695
raise BzrCommandError("Cannot do conflict reduction and show base.")
2697
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2698
merger.pp = ProgressPhase("Merge phase", 5, pb)
2699
merger.pp.next_phase()
2700
merger.check_basis(check_clean)
2701
merger.set_other(other_revision)
2702
merger.pp.next_phase()
2703
merger.set_base(base_revision)
2704
if merger.base_rev_id == merger.other_rev_id:
2705
note('Nothing to do.')
2707
merger.backup_files = backup_files
2708
merger.merge_type = merge_type
2709
merger.set_interesting_files(file_list)
2710
merger.show_base = show_base
2711
merger.reprocess = reprocess
2712
conflicts = merger.do_merge()
2713
if file_list is None:
2714
merger.set_pending()
2720
# these get imported and then picked up by the scan for cmd_*
2721
# TODO: Some more consistent way to split command definitions across files;
2722
# we do need to load at least some information about them to know of
2723
# aliases. ideally we would avoid loading the implementation until the
2724
# details were needed.
2725
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2726
from bzrlib.bundle.commands import cmd_bundle_revisions
2727
from bzrlib.sign_my_commits import cmd_sign_my_commits
2728
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2729
cmd_weave_plan_merge, cmd_weave_merge_text