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
57
from bzrlib.workingtree import WorkingTree
85
97
"""Parse and return a format specifier."""
86
98
if typestring == "weave":
87
99
return bzrdir.BzrDirFormat6()
88
if typestring == "metadir":
100
if typestring == "default":
89
101
return bzrdir.BzrDirMetaFormat1()
102
if typestring == "metaweave":
103
format = bzrdir.BzrDirMetaFormat1()
104
format.repository_format = repository.RepositoryFormat7()
90
106
if typestring == "knit":
91
107
format = bzrdir.BzrDirMetaFormat1()
92
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
108
format.repository_format = repository.RepositoryFormatKnit1()
94
msg = "No known bzr-dir format %s. Supported types are: weave, metadir\n" %\
110
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
111
"metaweave and weave" % typestring
96
112
raise BzrCommandError(msg)
145
157
# TODO: --no-recurse, --recurse options
147
159
takes_args = ['file*']
148
takes_options = ['all', 'show-ids', 'revision']
160
takes_options = ['show-ids', 'revision']
149
161
aliases = ['st', 'stat']
163
encoding_type = 'replace'
152
def run(self, all=False, show_ids=False, file_list=None, revision=None):
153
tree, file_list = tree_files(file_list)
166
def run(self, show_ids=False, file_list=None, revision=None):
155
167
from bzrlib.status import show_tree_status
156
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
157
specific_files=file_list, revision=revision)
169
tree, file_list = tree_files(file_list)
171
show_tree_status(tree, show_ids=show_ids,
172
specific_files=file_list, revision=revision,
160
176
class cmd_cat_revision(Command):
176
194
if revision_id is None and revision is None:
177
195
raise BzrCommandError('You must supply either --revision or a revision_id')
178
196
b = WorkingTree.open_containing(u'.')[0].branch
198
# TODO: jam 20060112 should cat-revision always output utf-8?
179
199
if revision_id is not None:
180
sys.stdout.write(b.repository.get_revision_xml(revision_id))
200
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
181
201
elif revision is not None:
182
202
for rev in revision:
184
204
raise BzrCommandError('You cannot specify a NULL revision.')
185
205
revno, rev_id = rev.in_history(b)
186
sys.stdout.write(b.repository.get_revision_xml(rev_id))
206
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
189
209
class cmd_revno(Command):
190
210
"""Show current revision number.
192
This is equal to the number of revisions on this branch."""
212
This is equal to the number of revisions on this branch.
193
215
takes_args = ['location?']
195
218
def run(self, location=u'.'):
196
print Branch.open_containing(location)[0].revno()
219
self.outf.write(str(Branch.open_containing(location)[0].revno()))
220
self.outf.write('\n')
199
223
class cmd_revision_info(Command):
253
278
takes_args = ['file*']
254
279
takes_options = ['no-recurse', 'dry-run', 'verbose']
280
encoding_type = 'replace'
256
282
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
257
283
import bzrlib.add
261
# This is pointless, but I'd rather not raise an error
262
action = bzrlib.add.add_action_null
264
action = bzrlib.add.add_action_print
266
action = bzrlib.add.add_action_add
268
action = bzrlib.add.add_action_add_and_print
285
action = bzrlib.add.AddAction(to_file=self.outf,
286
should_print=(not is_quiet()))
270
288
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
289
action=action, save=not dry_run)
272
290
if len(ignored) > 0:
273
for glob in sorted(ignored.keys()):
274
match_len = len(ignored[glob])
292
for glob in sorted(ignored.keys()):
276
293
for path in ignored[glob]:
277
print "ignored %s matching \"%s\"" % (path, glob)
279
print "ignored %d file(s) matching \"%s\"" % (match_len,
281
print "If you wish to add some of these files, please add them"\
294
self.outf.write("ignored %s matching \"%s\"\n"
298
for glob, paths in ignored.items():
299
match_len += len(paths)
300
self.outf.write("ignored %d file(s).\n" % match_len)
301
self.outf.write("If you wish to add some of these files,"
302
" please add them by name.\n")
285
305
class cmd_mkdir(Command):
383
416
from one into the other. Once one branch has merged, the other should
384
417
be able to pull it again.
386
If branches have diverged, you can use 'bzr merge' to pull the text changes
387
from one into the other. Once one branch has merged, the other should
388
be able to pull it again.
390
419
If you want to forget your local changes and just update your branch to
391
420
match the remote one, use pull --overwrite.
393
422
If there is no default location set, the first pull will set it. After
394
423
that, you can omit the location to use the default. To change the
395
default, use --remember.
424
default, use --remember. The value will only be saved if the remote
425
location can be accessed.
397
428
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
398
429
takes_args = ['location?']
430
encoding_type = 'replace'
400
432
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
401
433
# FIXME: too much stuff is in the command class
404
436
branch_to = tree_to.branch
405
437
except NoWorkingTree:
407
branch_to = Branch.open_containing(u'.')[0]
439
branch_to = Branch.open_containing(u'.')[0]
442
if location is not None:
444
reader = bundle.read_bundle_from_url(location)
446
pass # Continue on considering this url a Branch
408
448
stored_loc = branch_to.get_parent()
409
449
if location is None:
410
450
if stored_loc is None:
411
451
raise BzrCommandError("No pull location known or specified.")
413
print "Using saved location: %s" % stored_loc
453
display_url = urlutils.unescape_for_display(stored_loc,
455
self.outf.write("Using saved location: %s\n" % display_url)
414
456
location = stored_loc
416
if branch_to.get_parent() is None or remember:
417
branch_to.set_parent(location)
419
branch_from = Branch.open(location)
459
if reader is not None:
460
install_bundle(branch_to.repository, reader)
461
branch_from = branch_to
463
branch_from = Branch.open(location)
465
if branch_to.get_parent() is None or remember:
466
branch_to.set_parent(branch_from.base)
421
469
if revision is None:
470
if reader is not None:
471
rev_id = reader.target
423
472
elif len(revision) == 1:
424
473
rev_id = revision[0].in_history(branch_from).rev_id
463
513
If there is no default push location set, the first push will set it.
464
514
After that, you can omit the location to use the default. To change the
465
default, use --remember.
515
default, use --remember. The value will only be saved if the remote
516
location can be accessed.
467
takes_options = ['remember', 'overwrite',
519
takes_options = ['remember', 'overwrite', 'verbose',
468
520
Option('create-prefix',
469
521
help='Create the path leading up to the branch '
470
522
'if it does not already exist')]
471
523
takes_args = ['location?']
524
encoding_type = 'replace'
473
526
def run(self, location=None, remember=False, overwrite=False,
474
527
create_prefix=False, verbose=False):
475
528
# FIXME: Way too big! Put this into a function called from the
477
from bzrlib.transport import get_transport
479
tree_from = WorkingTree.open_containing(u'.')[0]
480
br_from = tree_from.branch
481
stored_loc = tree_from.branch.get_push_location()
531
br_from = Branch.open_containing('.')[0]
532
stored_loc = br_from.get_push_location()
482
533
if location is None:
483
534
if stored_loc is None:
484
535
raise BzrCommandError("No push location known or specified.")
486
print "Using saved location: %s" % stored_loc
537
display_url = urlutils.unescape_for_display(stored_loc,
539
self.outf.write("Using saved location: %s\n" % display_url)
487
540
location = stored_loc
488
if br_from.get_push_location() is None or remember:
489
br_from.set_push_location(location)
542
to_transport = transport.get_transport(location)
543
location_url = to_transport.base
491
dir_to = bzrlib.bzrdir.BzrDir.open(location)
547
dir_to = bzrdir.BzrDir.open(location_url)
492
548
br_to = dir_to.open_branch()
493
549
except NotBranchError:
494
550
# create a branch.
495
transport = get_transport(location).clone('..')
551
to_transport = to_transport.clone('..')
496
552
if not create_prefix:
498
transport.mkdir(transport.relpath(location))
554
relurl = to_transport.relpath(location_url)
555
mutter('creating directory %s => %s', location_url, relurl)
556
to_transport.mkdir(relurl)
499
557
except NoSuchFile:
500
558
raise BzrCommandError("Parent directory of %s "
501
559
"does not exist." % location)
503
current = transport.base
504
needed = [(transport, transport.relpath(location))]
561
current = to_transport.base
562
needed = [(to_transport, to_transport.relpath(location_url))]
507
transport, relpath = needed[-1]
508
transport.mkdir(relpath)
565
to_transport, relpath = needed[-1]
566
to_transport.mkdir(relpath)
510
568
except NoSuchFile:
511
new_transport = transport.clone('..')
569
new_transport = to_transport.clone('..')
512
570
needed.append((new_transport,
513
new_transport.relpath(transport.base)))
514
if new_transport.base == transport.base:
571
new_transport.relpath(to_transport.base)))
572
if new_transport.base == to_transport.base:
515
573
raise BzrCommandError("Could not create "
517
dir_to = br_from.bzrdir.clone(location)
575
dir_to = br_from.bzrdir.clone(location_url,
576
revision_id=br_from.last_revision())
518
577
br_to = dir_to.open_branch()
519
old_rh = br_to.revision_history()
578
count = len(br_to.revision_history())
579
# We successfully created the target, remember it
580
if br_from.get_push_location() is None or remember:
581
br_from.set_push_location(br_to.base)
583
# We were able to connect to the remote location, so remember it
584
# we don't need to successfully push because of possible divergence.
585
if br_from.get_push_location() is None or remember:
586
br_from.set_push_location(br_to.base)
587
old_rh = br_to.revision_history()
522
tree_to = dir_to.open_workingtree()
523
except errors.NotLocalUrl:
524
# TODO: This should be updated for branches which don't have a
525
# working tree, as opposed to ones where we just couldn't
527
warning('This transport does not update the working '
528
'tree of: %s' % (br_to.base,))
529
count = br_to.pull(br_from, overwrite)
530
except NoWorkingTree:
531
count = br_to.pull(br_from, overwrite)
533
count = tree_to.pull(br_from, overwrite)
534
except DivergedBranches:
535
raise BzrCommandError("These branches have diverged."
536
" Try a merge then push with overwrite.")
590
tree_to = dir_to.open_workingtree()
591
except errors.NotLocalUrl:
592
warning('This transport does not update the working '
593
'tree of: %s' % (br_to.base,))
594
count = br_to.pull(br_from, overwrite)
595
except NoWorkingTree:
596
count = br_to.pull(br_from, overwrite)
598
count = tree_to.pull(br_from, overwrite)
599
except DivergedBranches:
600
raise BzrCommandError("These branches have diverged."
601
" Try a merge then push with overwrite.")
537
602
note('%d revision(s) pushed.' % (count,))
595
661
name = os.path.basename(to_location) + '\n'
663
to_transport = transport.get_transport(to_location)
597
os.mkdir(to_location)
599
if e.errno == errno.EEXIST:
600
raise BzrCommandError('Target directory "%s" already'
601
' exists.' % to_location)
602
if e.errno == errno.ENOENT:
603
raise BzrCommandError('Parent of "%s" does not exist.' %
665
to_transport.mkdir('.')
666
except errors.FileExists:
667
raise BzrCommandError('Target directory "%s" already'
668
' exists.' % to_location)
669
except errors.NoSuchFile:
670
raise BzrCommandError('Parent of "%s" does not exist.' %
608
673
# preserve whatever source format we have.
609
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
674
dir = br_from.bzrdir.sprout(to_transport.base,
675
revision_id, basis_dir)
610
676
branch = dir.open_branch()
611
except bzrlib.errors.NoSuchRevision:
677
except errors.NoSuchRevision:
678
to_transport.delete_tree('.')
613
679
msg = "The branch %s has no revision %s." % (from_location, revision[0])
614
680
raise BzrCommandError(msg)
615
except bzrlib.errors.UnlistableBranch:
681
except errors.UnlistableBranch:
682
osutils.rmtree(to_location)
617
683
msg = "The branch %s cannot be used as a --basis" % (basis,)
618
684
raise BzrCommandError(msg)
620
686
branch.control_files.put_utf8('branch-name', name)
622
687
note('Branched %d revision(s).' % branch.revno())
743
809
'bzr revert' instead of 'bzr commit' after the update.
745
811
takes_args = ['dir?']
747
814
def run(self, dir='.'):
748
815
tree = WorkingTree.open_containing(dir)[0]
749
816
tree.lock_write()
751
if tree.last_revision() == tree.branch.last_revision():
818
last_rev = tree.last_revision()
819
if last_rev == tree.branch.last_revision():
752
820
# may be up to date, check master too.
753
821
master = tree.branch.get_master_branch()
754
if master is None or master.last_revision == tree.last_revision():
755
note("Tree is up to date.")
822
if master is None or last_rev == master.last_revision():
823
revno = tree.branch.revision_id_to_revno(last_rev)
824
note("Tree is up to date at revision %d." % (revno,))
757
826
conflicts = tree.update()
758
note('Updated to revision %d.' %
759
(tree.branch.revision_id_to_revno(tree.last_revision()),))
827
revno = tree.branch.revision_id_to_revno(tree.last_revision())
828
note('Updated to revision %d.' % (revno,))
760
829
if conflicts != 0:
783
859
This makes bzr stop tracking changes to a versioned file. It does
784
860
not delete the working copy.
862
You can specify one or more files, and/or --new. If you specify --new,
863
only 'added' files will be removed. If you specify both, then new files
864
in the specified directories will be removed. If the directories are
865
also new, they will also be removed.
786
takes_args = ['file+']
787
takes_options = ['verbose']
867
takes_args = ['file*']
868
takes_options = ['verbose', Option('new', help='remove newly-added files')]
870
encoding_type = 'replace'
790
def run(self, file_list, verbose=False):
872
def run(self, file_list, verbose=False, new=False):
791
873
tree, file_list = tree_files(file_list)
792
tree.remove(file_list, verbose=verbose)
875
if file_list is None:
876
raise BzrCommandError('Specify one or more files to remove, or'
879
added = tree.changes_from(tree.basis_tree(),
880
specific_files=file_list).added
881
file_list = sorted([f[0] for f in added], reverse=True)
882
if len(file_list) == 0:
883
raise BzrCommandError('No matching files.')
884
tree.remove(file_list, verbose=verbose, to_file=self.outf)
795
887
class cmd_file_id(Command):
852
949
def run(self, branch="."):
853
950
from bzrlib.reconcile import reconcile
854
dir = bzrlib.bzrdir.BzrDir.open(branch)
951
dir = bzrdir.BzrDir.open(branch)
858
955
class cmd_revision_history(Command):
859
"""Display list of revision ids on this branch."""
956
"""Display the list of revision ids on a branch."""
957
takes_args = ['location?']
863
branch = WorkingTree.open_containing(u'.')[0].branch
864
for patchid in branch.revision_history():
962
def run(self, location="."):
963
branch = Branch.open_containing(location)[0]
964
for revid in branch.revision_history():
965
self.outf.write(revid)
966
self.outf.write('\n')
868
969
class cmd_ancestry(Command):
869
970
"""List all revisions merged into this branch."""
971
takes_args = ['location?']
873
tree = WorkingTree.open_containing(u'.')[0]
875
# FIXME. should be tree.last_revision
876
for revision_id in b.repository.get_ancestry(b.last_revision()):
976
def run(self, location="."):
978
wt = WorkingTree.open_containing(location)[0]
979
except errors.NoWorkingTree:
980
b = Branch.open(location)
981
last_revision = b.last_revision()
984
last_revision = wt.last_revision()
986
revision_ids = b.repository.get_ancestry(last_revision)
987
assert revision_ids[0] == None
989
for revision_id in revision_ids:
990
self.outf.write(revision_id + '\n')
880
993
class cmd_init(Command):
901
1014
takes_args = ['location?']
902
1015
takes_options = [
903
1016
Option('format',
904
help='Create a specific format rather than the'
905
' current default format. Currently this '
906
' option only accepts "metadir"',
1017
help='Specify a format for this branch. Current'
1018
' formats are: default, knit, metaweave and'
1019
' weave. Default is knit; metaweave and'
1020
' weave are deprecated',
907
1021
type=get_format_type),
909
1023
def run(self, location=None, format=None):
910
from bzrlib.branch import Branch
1025
format = get_format_type('default')
911
1026
if location is None:
914
# The path has to exist to initialize a
915
# branch inside of it.
916
# Just using os.mkdir, since I don't
917
# believe that we want to create a bunch of
918
# locations if the user supplies an extended path
919
if not os.path.exists(location):
1029
to_transport = transport.get_transport(location)
1031
# The path has to exist to initialize a
1032
# branch inside of it.
1033
# Just using os.mkdir, since I don't
1034
# believe that we want to create a bunch of
1035
# locations if the user supplies an extended path
1036
# TODO: create-prefix
1038
to_transport.mkdir('.')
1039
except errors.FileExists:
922
1043
existing_bzrdir = bzrdir.BzrDir.open(location)
923
1044
except NotBranchError:
951
1072
takes_args = ["location"]
952
1073
takes_options = [Option('format',
953
help='Use a specific format rather than the'
954
' current default format. Currently this'
955
' option accepts "weave", "metadir" and "knit"',
1074
help='Specify a format for this repository.'
1075
' Current formats are: default, knit,'
1076
' metaweave and weave. Default is knit;'
1077
' metaweave and weave are deprecated',
956
1078
type=get_format_type),
958
1080
help='Allows branches in repository to have'
959
1081
' a working tree')]
960
1082
aliases = ["init-repo"]
961
1083
def run(self, location, format=None, trees=False):
962
from bzrlib.bzrdir import BzrDirMetaFormat1
963
from bzrlib.transport import get_transport
964
1084
if format is None:
965
format = BzrDirMetaFormat1()
966
transport = get_transport(location)
967
if not transport.has('.'):
969
newdir = format.initialize_on_transport(transport)
1085
format = get_format_type('default')
1087
if location is None:
1090
to_transport = transport.get_transport(location)
1092
to_transport.mkdir('.')
1093
except errors.FileExists:
1096
newdir = format.initialize_on_transport(to_transport)
970
1097
repo = newdir.create_repository(shared=True)
971
1098
repo.set_make_working_trees(trees)
974
1101
class cmd_diff(Command):
975
"""Show differences in working tree.
1102
"""Show differences in the working tree or between revisions.
977
1104
If files are listed, only the changes in those files are listed.
978
1105
Otherwise, all changes for the tree are listed.
1107
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1108
produces patches suitable for "patch -p1".
1112
Shows the difference in the working tree versus the last commit
1114
Difference between the working tree and revision 1
1116
Difference between revision 2 and revision 1
1117
bzr diff --diff-prefix old/:new/
1118
Same as 'bzr diff' but prefix paths with old/ and new/
1119
bzr diff bzr.mine bzr.dev
1120
Show the differences between the two working trees
1122
Show just the differences for 'foo.c'
985
# TODO: Allow diff across branches.
986
1124
# TODO: Option to use external diff command; could be GNU diff, wdiff,
987
1125
# or a graphical diff.
989
1127
# TODO: Python difflib is not exactly the same as unidiff; should
990
1128
# either fix it up or prefer to use an external diff.
992
# TODO: If a directory is given, diff everything under that.
994
1130
# TODO: Selected-file diff is inefficient and doesn't show you
995
1131
# deleted files.
997
1133
# TODO: This probably handles non-Unix newlines poorly.
999
1135
takes_args = ['file*']
1000
takes_options = ['revision', 'diff-options']
1136
takes_options = ['revision', 'diff-options', 'prefix']
1001
1137
aliases = ['di', 'dif']
1138
encoding_type = 'exact'
1003
1140
@display_command
1004
def run(self, revision=None, file_list=None, diff_options=None):
1141
def run(self, revision=None, file_list=None, diff_options=None,
1005
1143
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1145
if (prefix is None) or (prefix == '0'):
1153
if not ':' in prefix:
1154
raise BzrError("--diff-prefix expects two values separated by a colon")
1155
old_label, new_label = prefix.split(":")
1007
1158
tree1, file_list = internal_tree_files(file_list)
1018
1169
# FIXME diff those two files. rbc 20051123
1019
1170
raise BzrCommandError("Files are in different branches")
1020
1171
file_list = None
1172
except NotBranchError:
1173
if (revision is not None and len(revision) == 2
1174
and not revision[0].needs_branch()
1175
and not revision[1].needs_branch()):
1176
# If both revision specs include a branch, we can
1177
# diff them without needing a local working tree
1178
tree1, tree2 = None, None
1021
1181
if revision is not None:
1022
1182
if tree2 is not None:
1023
1183
raise BzrCommandError("Can't specify -r with two branches")
1024
1184
if (len(revision) == 1) or (revision[1].spec is None):
1025
1185
return diff_cmd_helper(tree1, file_list, diff_options,
1187
old_label=old_label, new_label=new_label)
1027
1188
elif len(revision) == 2:
1028
1189
return diff_cmd_helper(tree1, file_list, diff_options,
1029
revision[0], revision[1])
1190
revision[0], revision[1],
1191
old_label=old_label, new_label=new_label)
1031
1193
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1033
1195
if tree2 is not None:
1034
1196
return show_diff_trees(tree1, tree2, sys.stdout,
1035
1197
specific_files=file_list,
1036
external_diff_options=diff_options)
1198
external_diff_options=diff_options,
1199
old_label=old_label, new_label=new_label)
1038
return diff_cmd_helper(tree1, file_list, diff_options)
1201
return diff_cmd_helper(tree1, file_list, diff_options,
1202
old_label=old_label, new_label=new_label)
1041
1205
class cmd_deleted(Command):
1638
1808
takes_args = ['url?']
1639
1809
takes_options = [
1640
1810
Option('format',
1641
help='Upgrade to a specific format rather than the'
1642
' current default format. Currently this'
1643
' option accepts "weave", "metadir" and'
1811
help='Upgrade to a specific format. Current formats'
1812
' are: default, knit, metaweave and weave.'
1813
' Default is knit; metaweave and weave are'
1645
1815
type=get_format_type),
1649
1819
def run(self, url='.', format=None):
1650
1820
from bzrlib.upgrade import upgrade
1822
format = get_format_type('default')
1651
1823
upgrade(url, format)
1654
1826
class cmd_whoami(Command):
1655
"""Show bzr user id."""
1656
takes_options = ['email']
1827
"""Show or set bzr user id.
1831
bzr whoami 'Frank Chu <fchu@example.com>'
1833
takes_options = [ Option('email',
1834
help='display email address only'),
1836
help='set identity for the current branch instead of '
1839
takes_args = ['name?']
1840
encoding_type = 'replace'
1658
1842
@display_command
1659
def run(self, email=False):
1843
def run(self, email=False, branch=False, name=None):
1845
# use branch if we're inside one; otherwise global config
1847
c = Branch.open_containing('.')[0].get_config()
1848
except NotBranchError:
1849
c = config.GlobalConfig()
1851
self.outf.write(c.user_email() + '\n')
1853
self.outf.write(c.username() + '\n')
1856
# display a warning if an email address isn't included in the given name.
1661
b = WorkingTree.open_containing(u'.')[0].branch
1662
config = bzrlib.config.BranchConfig(b)
1663
except NotBranchError:
1664
config = bzrlib.config.GlobalConfig()
1858
config.extract_email_address(name)
1860
warning('"%s" does not seem to contain an email address. '
1861
'This is allowed, but not recommended.', name)
1667
print config.user_email()
1863
# use global config unless --branch given
1865
c = Branch.open_containing('.')[0].get_config()
1669
print config.username()
1867
c = config.GlobalConfig()
1868
c.set_user_option('email', name)
1672
1871
class cmd_nick(Command):
1737
1936
help='Use a different transport by default '
1738
1937
'throughout the test suite.',
1739
1938
type=get_transport_type),
1939
Option('benchmark', help='run the bzr bencharks.'),
1940
Option('lsprof-timed',
1941
help='generate lsprof output for benchmarked'
1942
' sections of code.'),
1742
def run(self, testspecs_list=None, verbose=False, one=False,
1743
keep_output=False, transport=None):
1945
def run(self, testspecs_list=None, verbose=None, one=False,
1946
keep_output=False, transport=None, benchmark=None,
1744
1948
import bzrlib.ui
1745
1949
from bzrlib.tests import selftest
1950
import bzrlib.benchmarks as benchmarks
1746
1951
# we don't want progress meters from the tests to go to the
1747
1952
# real output; and we don't want log messages cluttering up
1748
1953
# the real logs.
1749
save_ui = bzrlib.ui.ui_factory
1750
bzrlib.trace.info('running tests...')
1954
save_ui = ui.ui_factory
1955
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1956
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1958
info('running tests...')
1752
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1960
ui.ui_factory = ui.SilentUIFactory()
1753
1961
if testspecs_list is not None:
1754
1962
pattern = '|'.join(testspecs_list)
1966
test_suite_factory = benchmarks.test_suite
1970
test_suite_factory = None
1757
1973
result = selftest(verbose=verbose,
1758
1974
pattern=pattern,
1759
1975
stop_on_failure=one,
1760
1976
keep_output=keep_output,
1761
transport=transport)
1977
transport=transport,
1978
test_suite_factory=test_suite_factory,
1979
lsprof_timed=lsprof_timed)
1763
bzrlib.trace.info('tests passed')
1981
info('tests passed')
1765
bzrlib.trace.info('tests failed')
1983
info('tests failed')
1766
1984
return int(not result)
1768
bzrlib.ui.ui_factory = save_ui
1986
ui.ui_factory = save_ui
1771
1989
def _get_bzr_branch():
1772
1990
"""If bzr is run from a branch, return Branch or None"""
1773
import bzrlib.errors
1774
from bzrlib.branch import Branch
1775
from bzrlib.osutils import abspath
1776
1991
from os.path import dirname
1779
branch = Branch.open(dirname(abspath(dirname(__file__))))
1994
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1781
except bzrlib.errors.BzrError:
1996
except errors.BzrError:
1785
2000
def show_version():
1786
print "bzr (bazaar-ng) %s" % bzrlib.__version__
2002
print "Bazaar (bzr) %s" % bzrlib.__version__
1787
2003
# is bzrlib itself in a branch?
1788
2004
branch = _get_bzr_branch()
1842
2073
base_rev_id = common_ancestor(last1, last2, source)
1844
2075
print 'merge base is revision %s' % base_rev_id
1848
if base_revno is None:
1849
raise bzrlib.errors.UnrelatedBranches()
1851
print ' r%-6d in %s' % (base_revno, branch)
1853
other_revno = branch2.revision_id_to_revno(base_revid)
1855
print ' r%-6d in %s' % (other_revno, other)
1859
2078
class cmd_merge(Command):
1860
2079
"""Perform a three-way merge.
1862
The branch is the branch you will merge from. By default, it will
1863
merge the latest revision. If you specify a revision, that
1864
revision will be merged. If you specify two revisions, the first
1865
will be used as a BASE, and the second one as OTHER. Revision
1866
numbers are always relative to the specified branch.
2081
The branch is the branch you will merge from. By default, it will merge
2082
the latest revision. If you specify a revision, that revision will be
2083
merged. If you specify two revisions, the first will be used as a BASE,
2084
and the second one as OTHER. Revision numbers are always relative to the
1868
2087
By default, bzr will try to merge in all new work from the other
1869
2088
branch, automatically determining an appropriate base. If this
1894
2114
merge refuses to run if there are any uncommitted changes, unless
1895
2115
--force is given.
2117
The following merge types are available:
1897
2119
takes_args = ['branch?']
1898
2120
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
1899
2121
Option('show-base', help="Show base revision text in "
2125
from merge import merge_type_help
2126
from inspect import getdoc
2127
return getdoc(self) + '\n' + merge_type_help()
1902
2129
def run(self, branch=None, revision=None, force=False, merge_type=None,
1903
2130
show_base=False, reprocess=False, remember=False):
1904
2131
if merge_type is None:
1905
2132
merge_type = Merge3Merger
1907
2134
tree = WorkingTree.open_containing(u'.')[0]
1908
stored_loc = tree.branch.get_parent()
1910
if stored_loc is None:
1911
raise BzrCommandError("No merge branch known or specified.")
2136
if branch is not None:
2138
reader = bundle.read_bundle_from_url(branch)
2140
pass # Continue on considering this url a Branch
1913
print "Using saved branch: %s" % stored_loc
2142
conflicts = merge_bundle(reader, tree, not force, merge_type,
2143
reprocess, show_base)
1916
if tree.branch.get_parent() is None or remember:
1917
tree.branch.set_parent(branch)
2149
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1919
2151
if revision is None or len(revision) < 1:
1920
2152
base = [None, None]
1931
2163
if None in revision:
1932
2164
raise BzrCommandError(
1933
2165
"Merge doesn't permit that revision specifier.")
1934
b, path = Branch.open_containing(branch)
1936
base = [branch, revision[0].in_history(b).revno]
1937
other = [branch, revision[1].in_history(b).revno]
2166
other_branch, path = Branch.open_containing(branch)
2168
base = [branch, revision[0].in_history(other_branch).revno]
2169
other = [branch, revision[1].in_history(other_branch).revno]
2171
if tree.branch.get_parent() is None or remember:
2172
tree.branch.set_parent(other_branch.base)
1939
2175
interesting_files = [path]
1941
2177
interesting_files = None
1942
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2178
pb = ui.ui_factory.nested_progress_bar()
1945
2181
conflict_count = merge(other, base, check_clean=(not force),
1946
merge_type=merge_type,
2182
merge_type=merge_type,
1947
2183
reprocess=reprocess,
1948
show_base=show_base,
2184
show_base=show_base,
1949
2185
pb=pb, file_list=interesting_files)
1962
2198
"and (if you want) report this to the bzr developers\n")
2201
# TODO: move up to common parent; this isn't merge-specific anymore.
2202
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2203
"""Use tree.branch's parent if none was supplied.
2205
Report if the remembered location was used.
2207
if supplied_location is not None:
2208
return supplied_location
2209
stored_location = tree.branch.get_parent()
2210
mutter("%s", stored_location)
2211
if stored_location is None:
2212
raise BzrCommandError("No location specified or remembered")
2213
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2214
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2215
return stored_location
1966
2218
class cmd_remerge(Command):
1967
2219
"""Redo a merge.
2221
Use this if you want to try a different merge technique while resolving
2222
conflicts. Some merge techniques are better than others, and remerge
2223
lets you try different ones on different files.
2225
The options for remerge have the same meaning and defaults as the ones for
2226
merge. The difference is that remerge can (only) be run when there is a
2227
pending merge, and it lets you specify particular files.
2230
$ bzr remerge --show-base
2231
Re-do the merge of all conflicted files, and show the base text in
2232
conflict regions, in addition to the usual THIS and OTHER texts.
2234
$ bzr remerge --merge-type weave --reprocess foobar
2235
Re-do the merge of "foobar", using the weave merge algorithm, with
2236
additional processing to reduce the size of conflict regions.
2238
The following merge types are available:"""
1969
2239
takes_args = ['file*']
1970
2240
takes_options = ['merge-type', 'reprocess',
1971
2241
Option('show-base', help="Show base revision text in "
2245
from merge import merge_type_help
2246
from inspect import getdoc
2247
return getdoc(self) + '\n' + merge_type_help()
1974
2249
def run(self, file_list=None, merge_type=None, show_base=False,
1975
2250
reprocess=False):
1976
2251
from bzrlib.merge import merge_inner, transform_tree
2411
encoding_type = 'replace'
2134
2414
def run(self, other_branch=None, reverse=False, mine_only=False,
2135
2415
theirs_only=False, log_format=None, long=False, short=False, line=False,
2136
2416
show_ids=False, verbose=False):
2137
2417
from bzrlib.missing import find_unmerged, iter_log_data
2138
2418
from bzrlib.log import log_formatter
2139
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2419
local_branch = Branch.open_containing(u".")[0]
2140
2420
parent = local_branch.get_parent()
2141
2421
if other_branch is None:
2142
2422
other_branch = parent
2143
2423
if other_branch is None:
2144
raise BzrCommandError("No missing location known or specified.")
2424
raise BzrCommandError("No peer location known or specified.")
2145
2425
print "Using last location: " + local_branch.get_parent()
2146
remote_branch = bzrlib.branch.Branch.open(other_branch)
2426
remote_branch = Branch.open(other_branch)
2147
2427
if remote_branch.base == local_branch.base:
2148
2428
remote_branch = local_branch
2149
2429
local_branch.lock_read()
2218
2500
class cmd_testament(Command):
2219
2501
"""Show testament (signing-form) of a revision."""
2220
takes_options = ['revision', 'long']
2502
takes_options = ['revision', 'long',
2503
Option('strict', help='Produce a strict-format'
2221
2505
takes_args = ['branch?']
2222
2506
@display_command
2223
def run(self, branch=u'.', revision=None, long=False):
2224
from bzrlib.testament import Testament
2507
def run(self, branch=u'.', revision=None, long=False, strict=False):
2508
from bzrlib.testament import Testament, StrictTestament
2510
testament_class = StrictTestament
2512
testament_class = Testament
2225
2513
b = WorkingTree.open_containing(branch)[0].branch
2248
2536
shown only at the top, unless the --all option is given.
2250
2538
# TODO: annotate directories; showing when each file was last changed
2251
# TODO: annotate a previous version of a file
2252
2539
# TODO: if the working copy is modified, show annotations on that
2253
2540
# with new uncommitted lines marked
2254
aliases = ['blame', 'praise']
2541
aliases = ['ann', 'blame', 'praise']
2255
2542
takes_args = ['filename']
2256
2543
takes_options = [Option('all', help='show annotations on all lines'),
2257
2544
Option('long', help='show date in annotations'),
2260
2548
@display_command
2261
def run(self, filename, all=False, long=False):
2549
def run(self, filename, all=False, long=False, revision=None):
2262
2550
from bzrlib.annotate import annotate_file
2263
2551
tree, relpath = WorkingTree.open_containing(filename)
2264
2552
branch = tree.branch
2265
2553
branch.lock_read()
2555
if revision is None:
2556
revision_id = branch.last_revision()
2557
elif len(revision) != 1:
2558
raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2560
revision_id = revision[0].in_history(branch).rev_id
2267
2561
file_id = tree.inventory.path2id(relpath)
2268
tree = branch.repository.revision_tree(branch.last_revision())
2562
tree = branch.repository.revision_tree(revision_id)
2269
2563
file_version = tree.inventory[file_id].revision
2270
2564
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2348
2642
raise BzrCommandError('Local branch is not bound')
2351
class cmd_uncommit(bzrlib.commands.Command):
2645
class cmd_uncommit(Command):
2352
2646
"""Remove the last committed revision.
2354
By supplying the --all flag, it will not only remove the entry
2355
from revision_history, but also remove all of the entries in the
2358
2648
--verbose will print out what is being removed.
2359
2649
--dry-run will go through all the motions, but not actually
2360
2650
remove anything.
2362
In the future, uncommit will create a changeset, which can then
2652
In the future, uncommit will create a revision bundle, which can then
2366
2656
# TODO: jam 20060108 Add an option to allow uncommit to remove
2367
# unreferenced information in 'branch-as-repostory' branches.
2657
# unreferenced information in 'branch-as-repository' branches.
2368
2658
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2369
2659
# information in shared branches as well.
2370
2660
takes_options = ['verbose', 'revision',
2392
2681
b = control.open_branch()
2394
2684
if revision is None:
2395
2685
revno = b.revno()
2396
rev_id = b.last_revision()
2398
revno, rev_id = revision[0].in_history(b)
2687
# 'bzr uncommit -r 10' actually means uncommit
2688
# so that the final tree is at revno 10.
2689
# but bzrlib.uncommit.uncommit() actually uncommits
2690
# the revisions that are supplied.
2691
# So we need to offset it by one
2692
revno = revision[0].in_history(b).revno+1
2694
if revno <= b.revno():
2695
rev_id = b.get_rev_id(revno)
2399
2696
if rev_id is None:
2400
print 'No revisions to uncommit.'
2402
for r in range(revno, b.revno()+1):
2403
rev_id = b.get_rev_id(r)
2404
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2405
lf.show(r, b.repository.get_revision(rev_id), None)
2697
self.outf.write('No revisions to uncommit.\n')
2700
lf = log_formatter('short',
2702
show_timezone='original')
2707
direction='forward',
2708
start_revision=revno,
2709
end_revision=b.revno())
2408
2712
print 'Dry-run, pretending to remove the above revisions.'
2426
2730
CAUTION: Locks should only be broken when you are sure that the process
2427
2731
holding the lock has been stopped.
2733
You can get information on what locks are open via the 'bzr info' command.
2432
takes_args = ['location']
2433
takes_options = [Option('show',
2434
help="just show information on the lock, " \
2437
def run(self, location, show=False):
2438
raise NotImplementedError("sorry, break-lock is not complete yet; "
2439
"you can remove the 'held' directory manually to break the lock")
2738
takes_args = ['location?']
2740
def run(self, location=None, show=False):
2741
if location is None:
2743
control, relpath = bzrdir.BzrDir.open_containing(location)
2745
control.break_lock()
2746
except NotImplementedError:
2442
2751
# command-line interpretation helper for merge-related commands