1
1
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""builtin bzr commands"""
22
from shutil import rmtree
27
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
41
from bzrlib.branch import Branch, BranchReferenceFormat
42
from bzrlib.bundle import read_bundle_from_url
43
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
from bzrlib.conflicts import ConflictList
29
45
from bzrlib.commands import Command, display_command
30
from bzrlib.revision import common_ancestor
31
import bzrlib.errors as errors
32
46
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
33
47
NotBranchError, DivergedBranches, NotConflicted,
34
48
NoSuchFile, NoWorkingTree, FileInWrongBranch,
36
from bzrlib.log import show_one_log
49
NotVersionedError, NotABundle)
37
50
from bzrlib.merge import Merge3Merger
38
51
from bzrlib.option import Option
39
52
from bzrlib.progress import DummyProgress, ProgressPhase
53
from bzrlib.revision import common_ancestor
40
54
from bzrlib.revisionspec import RevisionSpec
42
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
43
56
from bzrlib.transport.local import LocalTransport
45
58
from bzrlib.workingtree import WorkingTree
84
97
def get_format_type(typestring):
85
98
"""Parse and return a format specifier."""
86
if typestring == "metadir":
99
if typestring == "weave":
100
return bzrdir.BzrDirFormat6()
101
if typestring == "default":
87
102
return bzrdir.BzrDirMetaFormat1()
103
if typestring == "metaweave":
104
format = bzrdir.BzrDirMetaFormat1()
105
format.repository_format = repository.RepositoryFormat7()
88
107
if typestring == "knit":
89
108
format = bzrdir.BzrDirMetaFormat1()
90
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
92
msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
109
format.repository_format = repository.RepositoryFormatKnit1()
111
if typestring == "experimental-knit2":
112
format = bzrdir.BzrDirMetaFormat1()
113
format.repository_format = repository.RepositoryFormatKnit2()
115
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
116
"metaweave and weave" % typestring
94
117
raise BzrCommandError(msg)
143
162
# TODO: --no-recurse, --recurse options
145
164
takes_args = ['file*']
146
takes_options = ['all', 'show-ids', 'revision']
165
takes_options = ['show-ids', 'revision']
147
166
aliases = ['st', 'stat']
168
encoding_type = 'replace'
150
def run(self, all=False, show_ids=False, file_list=None, revision=None):
151
tree, file_list = tree_files(file_list)
171
def run(self, show_ids=False, file_list=None, revision=None):
153
172
from bzrlib.status import show_tree_status
154
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
155
specific_files=file_list, revision=revision)
174
tree, file_list = tree_files(file_list)
176
show_tree_status(tree, show_ids=show_ids,
177
specific_files=file_list, revision=revision,
158
181
class cmd_cat_revision(Command):
174
199
if revision_id is None and revision is None:
175
200
raise BzrCommandError('You must supply either --revision or a revision_id')
176
201
b = WorkingTree.open_containing(u'.')[0].branch
203
# TODO: jam 20060112 should cat-revision always output utf-8?
177
204
if revision_id is not None:
178
sys.stdout.write(b.repository.get_revision_xml(revision_id))
205
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
179
206
elif revision is not None:
180
207
for rev in revision:
182
209
raise BzrCommandError('You cannot specify a NULL revision.')
183
210
revno, rev_id = rev.in_history(b)
184
sys.stdout.write(b.repository.get_revision_xml(rev_id))
211
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
187
214
class cmd_revno(Command):
188
215
"""Show current revision number.
190
This is equal to the number of revisions on this branch."""
217
This is equal to the number of revisions on this branch.
191
220
takes_args = ['location?']
193
223
def run(self, location=u'.'):
194
print Branch.open_containing(location)[0].revno()
224
self.outf.write(str(Branch.open_containing(location)[0].revno()))
225
self.outf.write('\n')
197
228
class cmd_revision_info(Command):
243
275
Adding a file whose parent directory is not versioned will
244
276
implicitly add the parent, and so on up to the root. This means
245
you should never need to explictly add a directory, they'll just
277
you should never need to explicitly add a directory, they'll just
246
278
get added when you add a file in the directory.
248
280
--dry-run will show which files would be added, but not actually
283
--file-ids-from will try to use the file ids from the supplied path.
284
It looks up ids trying to find a matching parent directory with the
285
same filename, and then by pure path.
251
287
takes_args = ['file*']
252
takes_options = ['no-recurse', 'dry-run', 'verbose']
288
takes_options = ['no-recurse', 'dry-run', 'verbose',
289
Option('file-ids-from', type=unicode,
290
help='Lookup file ids from here')]
291
encoding_type = 'replace'
254
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
293
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
255
295
import bzrlib.add
259
# This is pointless, but I'd rather not raise an error
260
action = bzrlib.add.add_action_null
262
action = bzrlib.add.add_action_print
264
action = bzrlib.add.add_action_add
297
if file_ids_from is not None:
299
base_tree, base_path = WorkingTree.open_containing(
301
except errors.NoWorkingTree:
302
base_branch, base_path = branch.Branch.open_containing(
304
base_tree = base_branch.basis_tree()
306
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
307
to_file=self.outf, should_print=(not is_quiet()))
266
action = bzrlib.add.add_action_add_and_print
309
action = bzrlib.add.AddAction(to_file=self.outf,
310
should_print=(not is_quiet()))
268
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
312
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
313
action=action, save=not dry_run)
270
314
if len(ignored) > 0:
271
for glob in sorted(ignored.keys()):
272
match_len = len(ignored[glob])
316
for glob in sorted(ignored.keys()):
274
317
for path in ignored[glob]:
275
print "ignored %s matching \"%s\"" % (path, glob)
277
print "ignored %d file(s) matching \"%s\"" % (match_len,
279
print "If you wish to add some of these files, please add them"\
318
self.outf.write("ignored %s matching \"%s\"\n"
322
for glob, paths in ignored.items():
323
match_len += len(paths)
324
self.outf.write("ignored %d file(s).\n" % match_len)
325
self.outf.write("If you wish to add some of these files,"
326
" please add them by name.\n")
283
329
class cmd_mkdir(Command):
286
332
This is equivalent to creating the directory and then adding it.
288
335
takes_args = ['dir+']
336
encoding_type = 'replace'
290
338
def run(self, dir_list):
291
339
for d in dir_list:
293
341
wt, dd = WorkingTree.open_containing(d)
343
self.outf.write('added %s\n' % d)
298
346
class cmd_relpath(Command):
299
347
"""Show path of a file relative to root"""
300
349
takes_args = ['filename']
304
353
def run(self, filename):
354
# TODO: jam 20050106 Can relpath return a munged path if
355
# sys.stdout encoding cannot represent it?
305
356
tree, relpath = WorkingTree.open_containing(filename)
357
self.outf.write(relpath)
358
self.outf.write('\n')
309
361
class cmd_inventory(Command):
310
362
"""Show inventory of the current working copy or a revision.
312
364
It is possible to limit the output to a particular entry
313
type using the --kind option. For example; --kind file.
365
type using the --kind option. For example: --kind file.
367
It is also possible to restrict the list of files to a specific
368
set. For example: bzr inventory --show-ids this/file
315
371
takes_options = ['revision', 'show-ids', 'kind']
372
takes_args = ['file*']
318
def run(self, revision=None, show_ids=False, kind=None):
375
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
319
376
if kind and kind not in ['file', 'directory', 'symlink']:
320
377
raise BzrCommandError('invalid kind specified')
321
tree = WorkingTree.open_containing(u'.')[0]
323
inv = tree.read_working_inventory()
379
work_tree, file_list = tree_files(file_list)
381
if revision is not None:
325
382
if len(revision) > 1:
326
383
raise BzrCommandError('bzr inventory --revision takes'
327
' exactly one revision identifier')
328
inv = tree.branch.repository.get_revision_inventory(
329
revision[0].in_history(tree.branch).rev_id)
331
for path, entry in inv.entries():
384
' exactly one revision identifier')
385
revision_id = revision[0].in_history(work_tree.branch).rev_id
386
tree = work_tree.branch.repository.revision_tree(revision_id)
388
# We include work_tree as well as 'tree' here
389
# So that doing '-r 10 path/foo' will lookup whatever file
390
# exists now at 'path/foo' even if it has been renamed, as
391
# well as whatever files existed in revision 10 at path/foo
392
trees = [tree, work_tree]
397
if file_list is not None:
398
file_ids = bzrlib.tree.find_ids_across_trees(file_list, trees,
399
require_versioned=True)
400
# find_ids_across_trees may include some paths that don't
402
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
403
for file_id in file_ids if file_id in tree)
405
entries = tree.inventory.entries()
407
for path, entry in entries:
332
408
if kind and kind != entry.kind:
335
print '%-50s %s' % (path, entry.file_id)
411
self.outf.write('%-50s %s\n' % (path, entry.file_id))
413
self.outf.write(path)
414
self.outf.write('\n')
340
417
class cmd_mv(Command):
381
463
from one into the other. Once one branch has merged, the other should
382
464
be able to pull it again.
384
If branches have diverged, you can use 'bzr merge' to pull the text changes
385
from one into the other. Once one branch has merged, the other should
386
be able to pull it again.
388
466
If you want to forget your local changes and just update your branch to
389
467
match the remote one, use pull --overwrite.
391
469
If there is no default location set, the first pull will set it. After
392
470
that, you can omit the location to use the default. To change the
393
default, use --remember.
471
default, use --remember. The value will only be saved if the remote
472
location can be accessed.
395
475
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
396
476
takes_args = ['location?']
477
encoding_type = 'replace'
398
479
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
399
480
# FIXME: too much stuff is in the command class
402
483
branch_to = tree_to.branch
403
484
except NoWorkingTree:
405
branch_to = Branch.open_containing(u'.')[0]
486
branch_to = Branch.open_containing(u'.')[0]
489
if location is not None:
491
reader = bundle.read_bundle_from_url(location)
493
pass # Continue on considering this url a Branch
406
495
stored_loc = branch_to.get_parent()
407
496
if location is None:
408
497
if stored_loc is None:
409
498
raise BzrCommandError("No pull location known or specified.")
411
print "Using saved location: %s" % stored_loc
500
display_url = urlutils.unescape_for_display(stored_loc,
502
self.outf.write("Using saved location: %s\n" % display_url)
412
503
location = stored_loc
414
if branch_to.get_parent() is None or remember:
415
branch_to.set_parent(location)
417
branch_from = Branch.open(location)
506
if reader is not None:
507
install_bundle(branch_to.repository, reader)
508
branch_from = branch_to
510
branch_from = Branch.open(location)
512
if branch_to.get_parent() is None or remember:
513
branch_to.set_parent(branch_from.base)
419
516
if revision is None:
517
if reader is not None:
518
rev_id = reader.target
421
519
elif len(revision) == 1:
422
520
rev_id = revision[0].in_history(branch_from).rev_id
461
560
If there is no default push location set, the first push will set it.
462
561
After that, you can omit the location to use the default. To change the
463
default, use --remember.
562
default, use --remember. The value will only be saved if the remote
563
location can be accessed.
465
takes_options = ['remember', 'overwrite',
566
takes_options = ['remember', 'overwrite', 'verbose',
466
567
Option('create-prefix',
467
568
help='Create the path leading up to the branch '
468
569
'if it does not already exist')]
469
570
takes_args = ['location?']
571
encoding_type = 'replace'
471
573
def run(self, location=None, remember=False, overwrite=False,
472
574
create_prefix=False, verbose=False):
473
575
# FIXME: Way too big! Put this into a function called from the
475
from bzrlib.transport import get_transport
477
tree_from = WorkingTree.open_containing(u'.')[0]
478
br_from = tree_from.branch
479
stored_loc = tree_from.branch.get_push_location()
578
br_from = Branch.open_containing('.')[0]
579
stored_loc = br_from.get_push_location()
480
580
if location is None:
481
581
if stored_loc is None:
482
582
raise BzrCommandError("No push location known or specified.")
484
print "Using saved location: %s" % stored_loc
584
display_url = urlutils.unescape_for_display(stored_loc,
586
self.outf.write("Using saved location: %s\n" % display_url)
485
587
location = stored_loc
486
if br_from.get_push_location() is None or remember:
487
br_from.set_push_location(location)
589
to_transport = transport.get_transport(location)
590
location_url = to_transport.base
489
dir_to = bzrlib.bzrdir.BzrDir.open(location)
594
dir_to = bzrdir.BzrDir.open(location_url)
490
595
br_to = dir_to.open_branch()
491
596
except NotBranchError:
492
597
# create a branch.
493
transport = get_transport(location).clone('..')
598
to_transport = to_transport.clone('..')
494
599
if not create_prefix:
496
transport.mkdir(transport.relpath(location))
601
relurl = to_transport.relpath(location_url)
602
mutter('creating directory %s => %s', location_url, relurl)
603
to_transport.mkdir(relurl)
497
604
except NoSuchFile:
498
605
raise BzrCommandError("Parent directory of %s "
499
606
"does not exist." % location)
501
current = transport.base
502
needed = [(transport, transport.relpath(location))]
608
current = to_transport.base
609
needed = [(to_transport, to_transport.relpath(location_url))]
505
transport, relpath = needed[-1]
506
transport.mkdir(relpath)
612
to_transport, relpath = needed[-1]
613
to_transport.mkdir(relpath)
508
615
except NoSuchFile:
509
new_transport = transport.clone('..')
616
new_transport = to_transport.clone('..')
510
617
needed.append((new_transport,
511
new_transport.relpath(transport.base)))
512
if new_transport.base == transport.base:
618
new_transport.relpath(to_transport.base)))
619
if new_transport.base == to_transport.base:
513
620
raise BzrCommandError("Could not create "
515
dir_to = br_from.bzrdir.clone(location)
622
dir_to = br_from.bzrdir.clone(location_url,
623
revision_id=br_from.last_revision())
516
624
br_to = dir_to.open_branch()
517
old_rh = br_to.revision_history()
625
count = len(br_to.revision_history())
626
# We successfully created the target, remember it
627
if br_from.get_push_location() is None or remember:
628
br_from.set_push_location(br_to.base)
630
# We were able to connect to the remote location, so remember it
631
# we don't need to successfully push because of possible divergence.
632
if br_from.get_push_location() is None or remember:
633
br_from.set_push_location(br_to.base)
634
old_rh = br_to.revision_history()
520
tree_to = dir_to.open_workingtree()
521
except errors.NotLocalUrl:
522
# TODO: This should be updated for branches which don't have a
523
# working tree, as opposed to ones where we just couldn't
525
warning('This transport does not update the working '
526
'tree of: %s' % (br_to.base,))
527
count = br_to.pull(br_from, overwrite)
528
except NoWorkingTree:
529
count = br_to.pull(br_from, overwrite)
531
count = tree_to.pull(br_from, overwrite)
532
except DivergedBranches:
533
raise BzrCommandError("These branches have diverged."
534
" Try a merge then push with overwrite.")
637
tree_to = dir_to.open_workingtree()
638
except errors.NotLocalUrl:
639
warning('This transport does not update the working '
640
'tree of: %s' % (br_to.base,))
641
count = br_to.pull(br_from, overwrite)
642
except NoWorkingTree:
643
count = br_to.pull(br_from, overwrite)
645
count = tree_to.pull(br_from, overwrite)
646
except DivergedBranches:
647
raise BzrCommandError("These branches have diverged."
648
" Try a merge then push with overwrite.")
535
649
note('%d revision(s) pushed.' % (count,))
593
708
name = os.path.basename(to_location) + '\n'
710
to_transport = transport.get_transport(to_location)
595
os.mkdir(to_location)
597
if e.errno == errno.EEXIST:
598
raise BzrCommandError('Target directory "%s" already'
599
' exists.' % to_location)
600
if e.errno == errno.ENOENT:
601
raise BzrCommandError('Parent of "%s" does not exist.' %
712
to_transport.mkdir('.')
713
except errors.FileExists:
714
raise BzrCommandError('Target directory "%s" already'
715
' exists.' % to_location)
716
except errors.NoSuchFile:
717
raise BzrCommandError('Parent of "%s" does not exist.' %
606
720
# preserve whatever source format we have.
607
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
721
dir = br_from.bzrdir.sprout(to_transport.base,
722
revision_id, basis_dir)
608
723
branch = dir.open_branch()
609
except bzrlib.errors.NoSuchRevision:
724
except errors.NoSuchRevision:
725
to_transport.delete_tree('.')
611
726
msg = "The branch %s has no revision %s." % (from_location, revision[0])
612
727
raise BzrCommandError(msg)
613
except bzrlib.errors.UnlistableBranch:
728
except errors.UnlistableBranch:
729
osutils.rmtree(to_location)
615
730
msg = "The branch %s cannot be used as a --basis" % (basis,)
616
731
raise BzrCommandError(msg)
618
733
branch.control_files.put_utf8('branch-name', name)
620
734
note('Branched %d revision(s).' % branch.revno())
694
old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
695
bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
809
old_format = bzrdir.BzrDirFormat.get_default_format()
810
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
698
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
699
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
701
checkout_branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
702
to_location, force_new_tree=False)
703
checkout = checkout_branch.bzrdir
704
checkout_branch.bind(source)
705
if revision_id is not None:
706
rh = checkout_branch.revision_history()
707
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
708
checkout.create_workingtree(revision_id)
812
source.create_checkout(to_location, revision_id, lightweight)
710
bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
814
bzrdir.BzrDirFormat.set_default_format(old_format)
713
817
class cmd_renames(Command):
741
845
'bzr revert' instead of 'bzr commit' after the update.
743
847
takes_args = ['dir?']
745
850
def run(self, dir='.'):
746
851
tree = WorkingTree.open_containing(dir)[0]
747
852
tree.lock_write()
749
if tree.last_revision() == tree.branch.last_revision():
854
existing_pending_merges = tree.get_parent_ids()[1:]
855
last_rev = tree.last_revision()
856
if last_rev == tree.branch.last_revision():
750
857
# may be up to date, check master too.
751
858
master = tree.branch.get_master_branch()
752
if master is None or master.last_revision == tree.last_revision():
753
note("Tree is up to date.")
859
if master is None or last_rev == master.last_revision():
860
revno = tree.branch.revision_id_to_revno(last_rev)
861
note("Tree is up to date at revision %d." % (revno,))
755
863
conflicts = tree.update()
756
note('Updated to revision %d.' %
757
(tree.branch.revision_id_to_revno(tree.last_revision()),))
864
revno = tree.branch.revision_id_to_revno(tree.last_revision())
865
note('Updated to revision %d.' % (revno,))
866
if tree.get_parent_ids()[1:] != existing_pending_merges:
867
note('Your local commits will now show as pending merges with '
868
"'bzr status', and can be committed with 'bzr commit'.")
758
869
if conflicts != 0:
781
899
This makes bzr stop tracking changes to a versioned file. It does
782
900
not delete the working copy.
902
You can specify one or more files, and/or --new. If you specify --new,
903
only 'added' files will be removed. If you specify both, then new files
904
in the specified directories will be removed. If the directories are
905
also new, they will also be removed.
784
takes_args = ['file+']
785
takes_options = ['verbose']
907
takes_args = ['file*']
908
takes_options = ['verbose', Option('new', help='remove newly-added files')]
910
encoding_type = 'replace'
788
def run(self, file_list, verbose=False):
912
def run(self, file_list, verbose=False, new=False):
789
913
tree, file_list = tree_files(file_list)
790
tree.remove(file_list, verbose=verbose)
915
if file_list is None:
916
raise BzrCommandError('Specify one or more files to remove, or'
919
added = tree.changes_from(tree.basis_tree(),
920
specific_files=file_list).added
921
file_list = sorted([f[0] for f in added], reverse=True)
922
if len(file_list) == 0:
923
raise BzrCommandError('No matching files.')
924
tree.remove(file_list, verbose=verbose, to_file=self.outf)
793
927
class cmd_file_id(Command):
797
931
same through all revisions where the file exists, even when it is
798
932
moved or renamed.
801
936
takes_args = ['filename']
803
939
def run(self, filename):
804
940
tree, relpath = WorkingTree.open_containing(filename)
805
941
i = tree.inventory.path2id(relpath)
807
943
raise BzrError("%r is not a versioned file" % filename)
945
self.outf.write(i + '\n')
812
948
class cmd_file_path(Command):
813
949
"""Print path of file_ids to a file or directory.
815
951
This prints one line for each directory down to the target,
816
starting at the branch root."""
952
starting at the branch root.
818
956
takes_args = ['filename']
820
959
def run(self, filename):
821
960
tree, relpath = WorkingTree.open_containing(filename)
822
961
inv = tree.inventory
823
962
fid = inv.path2id(relpath)
825
964
raise BzrError("%r is not a versioned file" % filename)
826
965
for fip in inv.get_idpath(fid):
966
self.outf.write(fip + '\n')
830
969
class cmd_reconcile(Command):
850
989
def run(self, branch="."):
851
990
from bzrlib.reconcile import reconcile
852
dir = bzrlib.bzrdir.BzrDir.open(branch)
991
dir = bzrdir.BzrDir.open(branch)
856
995
class cmd_revision_history(Command):
857
"""Display list of revision ids on this branch."""
996
"""Display the list of revision ids on a branch."""
997
takes_args = ['location?']
859
1001
@display_command
861
branch = WorkingTree.open_containing(u'.')[0].branch
862
for patchid in branch.revision_history():
1002
def run(self, location="."):
1003
branch = Branch.open_containing(location)[0]
1004
for revid in branch.revision_history():
1005
self.outf.write(revid)
1006
self.outf.write('\n')
866
1009
class cmd_ancestry(Command):
867
1010
"""List all revisions merged into this branch."""
1011
takes_args = ['location?']
869
1015
@display_command
871
tree = WorkingTree.open_containing(u'.')[0]
873
# FIXME. should be tree.last_revision
874
for revision_id in b.repository.get_ancestry(b.last_revision()):
1016
def run(self, location="."):
1018
wt = WorkingTree.open_containing(location)[0]
1019
except errors.NoWorkingTree:
1020
b = Branch.open(location)
1021
last_revision = b.last_revision()
1024
last_revision = wt.last_revision()
1026
revision_ids = b.repository.get_ancestry(last_revision)
1027
assert revision_ids[0] is None
1029
for revision_id in revision_ids:
1030
self.outf.write(revision_id + '\n')
878
1033
class cmd_init(Command):
891
1054
takes_args = ['location?']
892
1055
takes_options = [
893
1056
Option('format',
894
help='Create a specific format rather than the'
895
' current default format. Currently this '
896
' option only accepts "metadir"',
1057
help='Specify a format for this branch. Current'
1058
' formats are: default, knit, metaweave and'
1059
' weave. Default is knit; metaweave and'
1060
' weave are deprecated',
897
1061
type=get_format_type),
899
1063
def run(self, location=None, format=None):
900
from bzrlib.branch import Branch
1065
format = get_format_type('default')
901
1066
if location is None:
904
# The path has to exist to initialize a
905
# branch inside of it.
906
# Just using os.mkdir, since I don't
907
# believe that we want to create a bunch of
908
# locations if the user supplies an extended path
909
if not os.path.exists(location):
912
existing = bzrdir.BzrDir.open(location)
1069
to_transport = transport.get_transport(location)
1071
# The path has to exist to initialize a
1072
# branch inside of it.
1073
# Just using os.mkdir, since I don't
1074
# believe that we want to create a bunch of
1075
# locations if the user supplies an extended path
1076
# TODO: create-prefix
1078
to_transport.mkdir('.')
1079
except errors.FileExists:
1083
existing_bzrdir = bzrdir.BzrDir.open(location)
913
1084
except NotBranchError:
1085
# really a NotBzrDir error...
914
1086
bzrdir.BzrDir.create_branch_convenience(location, format=format)
917
existing.open_branch()
918
except NotBranchError:
919
existing.create_branch()
920
existing.create_workingtree()
1088
if existing_bzrdir.has_branch():
1089
if (isinstance(to_transport, LocalTransport)
1090
and not existing_bzrdir.has_workingtree()):
1091
raise errors.BranchExistsWithoutWorkingTree(location)
922
1092
raise errors.AlreadyBranchError(location)
1094
existing_bzrdir.create_branch()
1095
existing_bzrdir.create_workingtree()
925
1098
class cmd_init_repository(Command):
929
1102
in the repository, not in the branch directory, if the branch format supports
933
1106
bzr init-repo repo
934
bzr init --format=metadir repo/trunk
1108
bzr checkout --lightweight repo/trunk trunk-checkout
936
1110
(add files here)
938
1112
takes_args = ["location"]
939
1113
takes_options = [Option('format',
940
help='Use a specific format rather than the'
941
' current default format. Currently this'
942
' option only accepts "metadir" and "knit"'
943
' WARNING: the knit format is currently unstable'
944
' and only for experimental use.',
1114
help='Specify a format for this repository.'
1115
' Current formats are: default, knit,'
1116
' metaweave and weave. Default is knit;'
1117
' metaweave and weave are deprecated',
945
1118
type=get_format_type),
947
1120
help='Allows branches in repository to have'
948
1121
' a working tree')]
949
1122
aliases = ["init-repo"]
950
1123
def run(self, location, format=None, trees=False):
951
from bzrlib.bzrdir import BzrDirMetaFormat1
952
from bzrlib.transport import get_transport
953
1124
if format is None:
954
format = BzrDirMetaFormat1()
955
transport = get_transport(location)
956
if not transport.has('.'):
958
newdir = format.initialize_on_transport(transport)
1125
format = get_format_type('default')
1127
if location is None:
1130
to_transport = transport.get_transport(location)
1132
to_transport.mkdir('.')
1133
except errors.FileExists:
1136
newdir = format.initialize_on_transport(to_transport)
959
1137
repo = newdir.create_repository(shared=True)
960
1138
repo.set_make_working_trees(trees)
963
1141
class cmd_diff(Command):
964
"""Show differences in working tree.
1142
"""Show differences in the working tree or between revisions.
966
1144
If files are listed, only the changes in those files are listed.
967
1145
Otherwise, all changes for the tree are listed.
1147
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1148
produces patches suitable for "patch -p1".
1152
Shows the difference in the working tree versus the last commit
1154
Difference between the working tree and revision 1
1156
Difference between revision 2 and revision 1
1157
bzr diff --diff-prefix old/:new/
1158
Same as 'bzr diff' but prefix paths with old/ and new/
1159
bzr diff bzr.mine bzr.dev
1160
Show the differences between the two working trees
1162
Show just the differences for 'foo.c'
974
# TODO: Allow diff across branches.
975
1164
# TODO: Option to use external diff command; could be GNU diff, wdiff,
976
1165
# or a graphical diff.
978
1167
# TODO: Python difflib is not exactly the same as unidiff; should
979
1168
# either fix it up or prefer to use an external diff.
981
# TODO: If a directory is given, diff everything under that.
983
1170
# TODO: Selected-file diff is inefficient and doesn't show you
984
1171
# deleted files.
986
1173
# TODO: This probably handles non-Unix newlines poorly.
988
1175
takes_args = ['file*']
989
takes_options = ['revision', 'diff-options']
1176
takes_options = ['revision', 'diff-options', 'prefix']
990
1177
aliases = ['di', 'dif']
1178
encoding_type = 'exact'
992
1180
@display_command
993
def run(self, revision=None, file_list=None, diff_options=None):
1181
def run(self, revision=None, file_list=None, diff_options=None,
994
1183
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1185
if (prefix is None) or (prefix == '0'):
1193
if not ':' in prefix:
1194
raise BzrError("--diff-prefix expects two values separated by a colon")
1195
old_label, new_label = prefix.split(":")
996
1198
tree1, file_list = internal_tree_files(file_list)
1007
1209
# FIXME diff those two files. rbc 20051123
1008
1210
raise BzrCommandError("Files are in different branches")
1009
1211
file_list = None
1212
except NotBranchError:
1213
if (revision is not None and len(revision) == 2
1214
and not revision[0].needs_branch()
1215
and not revision[1].needs_branch()):
1216
# If both revision specs include a branch, we can
1217
# diff them without needing a local working tree
1218
tree1, tree2 = None, None
1010
1221
if revision is not None:
1011
1222
if tree2 is not None:
1012
1223
raise BzrCommandError("Can't specify -r with two branches")
1013
1224
if (len(revision) == 1) or (revision[1].spec is None):
1014
1225
return diff_cmd_helper(tree1, file_list, diff_options,
1227
old_label=old_label, new_label=new_label)
1016
1228
elif len(revision) == 2:
1017
1229
return diff_cmd_helper(tree1, file_list, diff_options,
1018
revision[0], revision[1])
1230
revision[0], revision[1],
1231
old_label=old_label, new_label=new_label)
1020
1233
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1022
1235
if tree2 is not None:
1023
1236
return show_diff_trees(tree1, tree2, sys.stdout,
1024
1237
specific_files=file_list,
1025
external_diff_options=diff_options)
1238
external_diff_options=diff_options,
1239
old_label=old_label, new_label=new_label)
1027
return diff_cmd_helper(tree1, file_list, diff_options)
1241
return diff_cmd_helper(tree1, file_list, diff_options,
1242
old_label=old_label, new_label=new_label)
1030
1245
class cmd_deleted(Command):
1627
1861
takes_args = ['url?']
1628
1862
takes_options = [
1629
1863
Option('format',
1630
help='Upgrade to a specific format rather than the'
1631
' current default format. Currently this'
1632
' option only accepts "metadir" and "knit".'
1633
' WARNING: the knit format is currently'
1634
' unstable and only for experimental use.',
1864
help='Upgrade to a specific format. Current formats'
1865
' are: default, knit, metaweave and weave.'
1866
' Default is knit; metaweave and weave are'
1635
1868
type=get_format_type),
1639
1872
def run(self, url='.', format=None):
1640
1873
from bzrlib.upgrade import upgrade
1875
format = get_format_type('default')
1641
1876
upgrade(url, format)
1644
1879
class cmd_whoami(Command):
1645
"""Show bzr user id."""
1646
takes_options = ['email']
1880
"""Show or set bzr user id.
1884
bzr whoami 'Frank Chu <fchu@example.com>'
1886
takes_options = [ Option('email',
1887
help='display email address only'),
1889
help='set identity for the current branch instead of '
1892
takes_args = ['name?']
1893
encoding_type = 'replace'
1648
1895
@display_command
1649
def run(self, email=False):
1896
def run(self, email=False, branch=False, name=None):
1898
# use branch if we're inside one; otherwise global config
1900
c = Branch.open_containing('.')[0].get_config()
1901
except NotBranchError:
1902
c = config.GlobalConfig()
1904
self.outf.write(c.user_email() + '\n')
1906
self.outf.write(c.username() + '\n')
1909
# display a warning if an email address isn't included in the given name.
1651
b = WorkingTree.open_containing(u'.')[0].branch
1652
config = bzrlib.config.BranchConfig(b)
1653
except NotBranchError:
1654
config = bzrlib.config.GlobalConfig()
1911
config.extract_email_address(name)
1913
warning('"%s" does not seem to contain an email address. '
1914
'This is allowed, but not recommended.', name)
1657
print config.user_email()
1916
# use global config unless --branch given
1918
c = Branch.open_containing('.')[0].get_config()
1659
print config.username()
1920
c = config.GlobalConfig()
1921
c.set_user_option('email', name)
1662
1924
class cmd_nick(Command):
1727
1989
help='Use a different transport by default '
1728
1990
'throughout the test suite.',
1729
1991
type=get_transport_type),
1992
Option('benchmark', help='run the bzr bencharks.'),
1993
Option('lsprof-timed',
1994
help='generate lsprof output for benchmarked'
1995
' sections of code.'),
1996
Option('cache-dir', type=str,
1997
help='a directory to cache intermediate'
1998
' benchmark steps'),
1732
def run(self, testspecs_list=None, verbose=False, one=False,
1733
keep_output=False, transport=None):
2001
def run(self, testspecs_list=None, verbose=None, one=False,
2002
keep_output=False, transport=None, benchmark=None,
2003
lsprof_timed=None, cache_dir=None):
1734
2004
import bzrlib.ui
1735
2005
from bzrlib.tests import selftest
2006
import bzrlib.benchmarks as benchmarks
2007
from bzrlib.benchmarks import tree_creator
2009
if cache_dir is not None:
2010
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1736
2011
# we don't want progress meters from the tests to go to the
1737
2012
# real output; and we don't want log messages cluttering up
1738
2013
# the real logs.
1739
save_ui = bzrlib.ui.ui_factory
1740
bzrlib.trace.info('running tests...')
2014
save_ui = ui.ui_factory
2015
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2016
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2018
info('running tests...')
1742
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
2020
ui.ui_factory = ui.SilentUIFactory()
1743
2021
if testspecs_list is not None:
1744
2022
pattern = '|'.join(testspecs_list)
1747
result = selftest(verbose=verbose,
1749
stop_on_failure=one,
1750
keep_output=keep_output,
1751
transport=transport)
2026
test_suite_factory = benchmarks.test_suite
2029
# TODO: should possibly lock the history file...
2030
benchfile = open(".perf_history", "at")
2032
test_suite_factory = None
2037
result = selftest(verbose=verbose,
2039
stop_on_failure=one,
2040
keep_output=keep_output,
2041
transport=transport,
2042
test_suite_factory=test_suite_factory,
2043
lsprof_timed=lsprof_timed,
2044
bench_history=benchfile)
2046
if benchfile is not None:
1753
bzrlib.trace.info('tests passed')
2049
info('tests passed')
1755
bzrlib.trace.info('tests failed')
2051
info('tests failed')
1756
2052
return int(not result)
1758
bzrlib.ui.ui_factory = save_ui
1761
def _get_bzr_branch():
1762
"""If bzr is run from a branch, return Branch or None"""
1763
import bzrlib.errors
1764
from bzrlib.branch import Branch
1765
from bzrlib.osutils import abspath
1766
from os.path import dirname
1769
branch = Branch.open(dirname(abspath(dirname(__file__))))
1771
except bzrlib.errors.BzrError:
1776
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1777
# is bzrlib itself in a branch?
1778
branch = _get_bzr_branch()
1780
rh = branch.revision_history()
1782
print " bzr checkout, revision %d" % (revno,)
1783
print " nick: %s" % (branch.nick,)
1785
print " revid: %s" % (rh[-1],)
1786
print bzrlib.__copyright__
1787
print "http://bazaar-ng.org/"
1789
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1790
print "you may use, modify and redistribute it under the terms of the GNU"
1791
print "General Public License version 2 or later."
2054
ui.ui_factory = save_ui
1794
2057
class cmd_version(Command):
1795
2058
"""Show version of bzr."""
1796
2060
@display_command
2062
from bzrlib.version import show_version
1800
2066
class cmd_rocks(Command):
1801
2067
"""Statement of optimism."""
1803
2071
@display_command
1805
2073
print "it sure does!"
1808
2076
class cmd_find_merge_base(Command):
1809
"""Find and print a base revision for merging two branches.
2077
"""Find and print a base revision for merging two branches."""
1811
2078
# TODO: Options to specify revisions on either side, as if
1812
2079
# merging only part of the history.
1813
2080
takes_args = ['branch', 'other']
1832
2099
base_rev_id = common_ancestor(last1, last2, source)
1834
2101
print 'merge base is revision %s' % base_rev_id
1838
if base_revno is None:
1839
raise bzrlib.errors.UnrelatedBranches()
1841
print ' r%-6d in %s' % (base_revno, branch)
1843
other_revno = branch2.revision_id_to_revno(base_revid)
1845
print ' r%-6d in %s' % (other_revno, other)
1849
2104
class cmd_merge(Command):
1850
2105
"""Perform a three-way merge.
1852
The branch is the branch you will merge from. By default, it will
1853
merge the latest revision. If you specify a revision, that
1854
revision will be merged. If you specify two revisions, the first
1855
will be used as a BASE, and the second one as OTHER. Revision
1856
numbers are always relative to the specified branch.
2107
The branch is the branch you will merge from. By default, it will merge
2108
the latest revision. If you specify a revision, that revision will be
2109
merged. If you specify two revisions, the first will be used as a BASE,
2110
and the second one as OTHER. Revision numbers are always relative to the
1858
2113
By default, bzr will try to merge in all new work from the other
1859
2114
branch, automatically determining an appropriate base. If this
1884
2140
merge refuses to run if there are any uncommitted changes, unless
1885
2141
--force is given.
2143
The following merge types are available:
1887
2145
takes_args = ['branch?']
1888
2146
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
1889
2147
Option('show-base', help="Show base revision text in "
2149
Option('uncommitted', help='Apply uncommitted changes'
2150
' from a working copy, instead of branch changes')]
2153
from merge import merge_type_help
2154
from inspect import getdoc
2155
return getdoc(self) + '\n' + merge_type_help()
1892
2157
def run(self, branch=None, revision=None, force=False, merge_type=None,
1893
show_base=False, reprocess=False, remember=False):
2158
show_base=False, reprocess=False, remember=False,
1894
2160
if merge_type is None:
1895
2161
merge_type = Merge3Merger
1897
2163
tree = WorkingTree.open_containing(u'.')[0]
1898
stored_loc = tree.branch.get_parent()
1900
if stored_loc is None:
1901
raise BzrCommandError("No merge branch known or specified.")
2165
if branch is not None:
2167
reader = bundle.read_bundle_from_url(branch)
2169
pass # Continue on considering this url a Branch
1903
print "Using saved branch: %s" % stored_loc
2171
conflicts = merge_bundle(reader, tree, not force, merge_type,
2172
reprocess, show_base)
1906
if tree.branch.get_parent() is None or remember:
1907
tree.branch.set_parent(branch)
2178
if revision is None \
2179
or len(revision) < 1 or revision[0].needs_branch():
2180
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1909
2182
if revision is None or len(revision) < 1:
1911
other = [branch, -1]
2185
other = [branch, None]
2188
other = [branch, -1]
1912
2189
other_branch, path = Branch.open_containing(branch)
2192
raise BzrCommandError('Cannot use --uncommitted and --revision'
2193
' at the same time.')
2194
branch = revision[0].get_branch() or branch
1914
2195
if len(revision) == 1:
1915
2196
base = [None, None]
1916
2197
other_branch, path = Branch.open_containing(branch)
1920
2201
assert len(revision) == 2
1921
2202
if None in revision:
1922
2203
raise BzrCommandError(
1923
"Merge doesn't permit that revision specifier.")
1924
b, path = Branch.open_containing(branch)
1926
base = [branch, revision[0].in_history(b).revno]
1927
other = [branch, revision[1].in_history(b).revno]
2204
"Merge doesn't permit empty revision specifier.")
2205
base_branch, path = Branch.open_containing(branch)
2206
branch1 = revision[1].get_branch() or branch
2207
other_branch, path1 = Branch.open_containing(branch1)
2208
if revision[0].get_branch() is not None:
2209
# then path was obtained from it, and is None.
2212
base = [branch, revision[0].in_history(base_branch).revno]
2213
other = [branch1, revision[1].in_history(other_branch).revno]
2215
if tree.branch.get_parent() is None or remember:
2216
tree.branch.set_parent(other_branch.base)
1929
2219
interesting_files = [path]
1931
2221
interesting_files = None
1932
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2222
pb = ui.ui_factory.nested_progress_bar()
1935
2225
conflict_count = merge(other, base, check_clean=(not force),
1936
merge_type=merge_type,
2226
merge_type=merge_type,
1937
2227
reprocess=reprocess,
1938
show_base=show_base,
2228
show_base=show_base,
1939
2229
pb=pb, file_list=interesting_files)
1952
2242
"and (if you want) report this to the bzr developers\n")
2245
# TODO: move up to common parent; this isn't merge-specific anymore.
2246
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2247
"""Use tree.branch's parent if none was supplied.
2249
Report if the remembered location was used.
2251
if supplied_location is not None:
2252
return supplied_location
2253
stored_location = tree.branch.get_parent()
2254
mutter("%s", stored_location)
2255
if stored_location is None:
2256
raise BzrCommandError("No location specified or remembered")
2257
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2258
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2259
return stored_location
1956
2262
class cmd_remerge(Command):
1957
2263
"""Redo a merge.
2265
Use this if you want to try a different merge technique while resolving
2266
conflicts. Some merge techniques are better than others, and remerge
2267
lets you try different ones on different files.
2269
The options for remerge have the same meaning and defaults as the ones for
2270
merge. The difference is that remerge can (only) be run when there is a
2271
pending merge, and it lets you specify particular files.
2274
$ bzr remerge --show-base
2275
Re-do the merge of all conflicted files, and show the base text in
2276
conflict regions, in addition to the usual THIS and OTHER texts.
2278
$ bzr remerge --merge-type weave --reprocess foobar
2279
Re-do the merge of "foobar", using the weave merge algorithm, with
2280
additional processing to reduce the size of conflict regions.
2282
The following merge types are available:"""
1959
2283
takes_args = ['file*']
1960
2284
takes_options = ['merge-type', 'reprocess',
1961
2285
Option('show-base', help="Show base revision text in "
2289
from merge import merge_type_help
2290
from inspect import getdoc
2291
return getdoc(self) + '\n' + merge_type_help()
1964
2293
def run(self, file_list=None, merge_type=None, show_base=False,
1965
2294
reprocess=False):
1966
2295
from bzrlib.merge import merge_inner, transform_tree
1969
2298
tree, file_list = tree_files(file_list)
1970
2299
tree.lock_write()
1972
pending_merges = tree.pending_merges()
1973
if len(pending_merges) != 1:
2301
parents = tree.get_parent_ids()
2302
if len(parents) != 2:
1974
2303
raise BzrCommandError("Sorry, remerge only works after normal"
1975
+ " merges. Not cherrypicking or"
2304
" merges. Not cherrypicking or"
1977
2306
repository = tree.branch.repository
1978
base_revision = common_ancestor(tree.branch.last_revision(),
1979
pending_merges[0], repository)
2307
base_revision = common_ancestor(parents[0],
2308
parents[1], repository)
1980
2309
base_tree = repository.revision_tree(base_revision)
1981
other_tree = repository.revision_tree(pending_merges[0])
2310
other_tree = repository.revision_tree(parents[1])
1982
2311
interesting_ids = None
2313
conflicts = tree.conflicts()
1983
2314
if file_list is not None:
1984
2315
interesting_ids = set()
1985
2316
for filename in file_list:
2019
2352
class cmd_revert(Command):
2020
"""Reverse all changes since the last commit.
2022
Only versioned files are affected. Specify filenames to revert only
2023
those files. By default, any files that are changed will be backed up
2024
first. Backup files have a '~' appended to their name.
2353
"""Revert files to a previous revision.
2355
Giving a list of files will revert only those files. Otherwise, all files
2356
will be reverted. If the revision is not specified with '--revision', the
2357
last committed revision is used.
2359
To remove only some changes, without reverting to a prior version, use
2360
merge instead. For example, "merge . --r-2..-3" will remove the changes
2361
introduced by -2, without affecting the changes introduced by -1. Or
2362
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2364
By default, any files that have been manually changed will be backed up
2365
first. (Files changed only by merge are not backed up.) Backup files have
2366
'.~#~' appended to their name, where # is a number.
2368
When you provide files, you can use their current pathname or the pathname
2369
from the target revision. So you can use revert to "undelete" a file by
2370
name. If you name a directory, all the contents of that directory will be
2026
2373
takes_options = ['revision', 'no-backup']
2027
2374
takes_args = ['file*']
2469
encoding_type = 'replace'
2124
2472
def run(self, other_branch=None, reverse=False, mine_only=False,
2125
2473
theirs_only=False, log_format=None, long=False, short=False, line=False,
2126
2474
show_ids=False, verbose=False):
2127
2475
from bzrlib.missing import find_unmerged, iter_log_data
2128
2476
from bzrlib.log import log_formatter
2129
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2477
local_branch = Branch.open_containing(u".")[0]
2130
2478
parent = local_branch.get_parent()
2131
2479
if other_branch is None:
2132
2480
other_branch = parent
2133
2481
if other_branch is None:
2134
raise BzrCommandError("No missing location known or specified.")
2482
raise BzrCommandError("No peer location known or specified.")
2135
2483
print "Using last location: " + local_branch.get_parent()
2136
remote_branch = bzrlib.branch.Branch.open(other_branch)
2137
local_branch.lock_write()
2484
remote_branch = Branch.open(other_branch)
2138
2485
if remote_branch.base == local_branch.base:
2139
2486
remote_branch = local_branch
2487
local_branch.lock_read()
2141
2489
remote_branch.lock_read()
2143
2491
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2144
if (log_format == None):
2145
default = bzrlib.config.BranchConfig(local_branch).log_format()
2146
log_format = get_log_format(long=long, short=short, line=line, default=default)
2147
lf = log_formatter(log_format, sys.stdout,
2492
if (log_format is None):
2493
default = local_branch.get_config().log_format()
2494
log_format = get_log_format(long=long, short=short,
2495
line=line, default=default)
2496
lf = log_formatter(log_format,
2148
2498
show_ids=show_ids,
2149
2499
show_timezone='original')
2150
2500
if reverse is False:
2202
2558
class cmd_testament(Command):
2203
2559
"""Show testament (signing-form) of a revision."""
2204
takes_options = ['revision', 'long']
2560
takes_options = ['revision',
2561
Option('long', help='Produce long-format testament'),
2562
Option('strict', help='Produce a strict-format'
2205
2564
takes_args = ['branch?']
2206
2565
@display_command
2207
def run(self, branch=u'.', revision=None, long=False):
2208
from bzrlib.testament import Testament
2566
def run(self, branch=u'.', revision=None, long=False, strict=False):
2567
from bzrlib.testament import Testament, StrictTestament
2569
testament_class = StrictTestament
2571
testament_class = Testament
2209
2572
b = WorkingTree.open_containing(branch)[0].branch
2232
2595
shown only at the top, unless the --all option is given.
2234
2597
# TODO: annotate directories; showing when each file was last changed
2235
# TODO: annotate a previous version of a file
2236
2598
# TODO: if the working copy is modified, show annotations on that
2237
2599
# with new uncommitted lines marked
2238
aliases = ['blame', 'praise']
2600
aliases = ['ann', 'blame', 'praise']
2239
2601
takes_args = ['filename']
2240
2602
takes_options = [Option('all', help='show annotations on all lines'),
2241
2603
Option('long', help='show date in annotations'),
2244
2607
@display_command
2245
def run(self, filename, all=False, long=False):
2608
def run(self, filename, all=False, long=False, revision=None):
2246
2609
from bzrlib.annotate import annotate_file
2247
2610
tree, relpath = WorkingTree.open_containing(filename)
2248
2611
branch = tree.branch
2249
2612
branch.lock_read()
2614
if revision is None:
2615
revision_id = branch.last_revision()
2616
elif len(revision) != 1:
2617
raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2619
revision_id = revision[0].in_history(branch).rev_id
2251
2620
file_id = tree.inventory.path2id(relpath)
2252
tree = branch.repository.revision_tree(branch.last_revision())
2621
tree = branch.repository.revision_tree(revision_id)
2253
2622
file_version = tree.inventory[file_id].revision
2254
2623
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2332
2701
raise BzrCommandError('Local branch is not bound')
2335
class cmd_uncommit(bzrlib.commands.Command):
2704
class cmd_uncommit(Command):
2336
2705
"""Remove the last committed revision.
2338
By supplying the --all flag, it will not only remove the entry
2339
from revision_history, but also remove all of the entries in the
2342
2707
--verbose will print out what is being removed.
2343
2708
--dry-run will go through all the motions, but not actually
2344
2709
remove anything.
2346
In the future, uncommit will create a changeset, which can then
2711
In the future, uncommit will create a revision bundle, which can then
2350
2715
# TODO: jam 20060108 Add an option to allow uncommit to remove
2351
# unreferenced information in 'branch-as-repostory' branches.
2716
# unreferenced information in 'branch-as-repository' branches.
2352
2717
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2353
2718
# information in shared branches as well.
2354
2719
takes_options = ['verbose', 'revision',
2376
2740
b = control.open_branch()
2378
2743
if revision is None:
2379
2744
revno = b.revno()
2380
rev_id = b.last_revision()
2382
revno, rev_id = revision[0].in_history(b)
2746
# 'bzr uncommit -r 10' actually means uncommit
2747
# so that the final tree is at revno 10.
2748
# but bzrlib.uncommit.uncommit() actually uncommits
2749
# the revisions that are supplied.
2750
# So we need to offset it by one
2751
revno = revision[0].in_history(b).revno+1
2753
if revno <= b.revno():
2754
rev_id = b.get_rev_id(revno)
2383
2755
if rev_id is None:
2384
print 'No revisions to uncommit.'
2386
for r in range(revno, b.revno()+1):
2387
rev_id = b.get_rev_id(r)
2388
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2389
lf.show(r, b.repository.get_revision(rev_id), None)
2756
self.outf.write('No revisions to uncommit.\n')
2759
lf = log_formatter('short',
2761
show_timezone='original')
2766
direction='forward',
2767
start_revision=revno,
2768
end_revision=b.revno())
2392
2771
print 'Dry-run, pretending to remove the above revisions.'
2410
2789
CAUTION: Locks should only be broken when you are sure that the process
2411
2790
holding the lock has been stopped.
2792
You can get information on what locks are open via the 'bzr info' command.
2416
takes_args = ['location']
2417
takes_options = [Option('show',
2418
help="just show information on the lock, " \
2421
def run(self, location, show=False):
2422
raise NotImplementedError("sorry, break-lock is not complete yet; "
2423
"you can remove the 'held' directory manually to break the lock")
2797
takes_args = ['location?']
2799
def run(self, location=None, show=False):
2800
if location is None:
2802
control, relpath = bzrdir.BzrDir.open_containing(location)
2804
control.break_lock()
2805
except NotImplementedError:
2809
class cmd_wait_until_signalled(Command):
2810
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
2812
This just prints a line to signal when it is ready, then blocks on stdin.
2818
sys.stdout.write("running\n")
2820
sys.stdin.readline()
2823
class cmd_serve(Command):
2824
"""Run the bzr server."""
2826
aliases = ['server']
2830
help='serve on stdin/out for use from inetd or sshd'),
2832
help='listen for connections on nominated port of the form '
2833
'[hostname:]portnumber. Passing 0 as the port number will '
2834
'result in a dynamically allocated port.',
2837
help='serve contents of directory',
2839
Option('allow-writes',
2840
help='By default the server is a readonly server. Supplying '
2841
'--allow-writes enables write access to the contents of '
2842
'the served directory and below. '
2846
def run(self, port=None, inet=False, directory=None, allow_writes=False):
2847
from bzrlib.transport import smart
2848
from bzrlib.transport import get_transport
2849
if directory is None:
2850
directory = os.getcwd()
2851
url = urlutils.local_path_to_url(directory)
2852
if not allow_writes:
2853
url = 'readonly+' + url
2854
t = get_transport(url)
2856
server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
2857
elif port is not None:
2859
host, port = port.split(':')
2862
server = smart.SmartTCPServer(t, host=host, port=int(port))
2863
print 'listening on port: ', server.port
2866
raise BzrCommandError("bzr serve requires one of --inet or --port")
2426
2870
# command-line interpretation helper for merge-related commands