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
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
27
from bzrlib.branch import Branch
28
import bzrlib.bzrdir as bzrdir
45
29
from bzrlib.commands import Command, display_command
30
from bzrlib.revision import common_ancestor
31
import bzrlib.errors as errors
46
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
47
33
NotBranchError, DivergedBranches, NotConflicted,
48
34
NoSuchFile, NoWorkingTree, FileInWrongBranch,
49
NotVersionedError, NotABundle)
36
from bzrlib.log import show_one_log
50
37
from bzrlib.merge import Merge3Merger
51
38
from bzrlib.option import Option
52
39
from bzrlib.progress import DummyProgress, ProgressPhase
53
from bzrlib.revision import common_ancestor
54
40
from bzrlib.revisionspec import RevisionSpec
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
42
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
56
43
from bzrlib.transport.local import LocalTransport
57
45
from bzrlib.workingtree import WorkingTree
97
85
"""Parse and return a format specifier."""
98
86
if typestring == "weave":
99
87
return bzrdir.BzrDirFormat6()
100
if typestring == "default":
88
if typestring == "metadir":
101
89
return bzrdir.BzrDirMetaFormat1()
102
if typestring == "metaweave":
103
format = bzrdir.BzrDirMetaFormat1()
104
format.repository_format = repository.RepositoryFormat7()
106
90
if typestring == "knit":
107
91
format = bzrdir.BzrDirMetaFormat1()
108
format.repository_format = repository.RepositoryFormatKnit1()
92
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
110
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
111
"metaweave and weave" % typestring
94
msg = "No known bzr-dir format %s. Supported types are: weave, metadir\n" %\
112
96
raise BzrCommandError(msg)
157
145
# TODO: --no-recurse, --recurse options
159
147
takes_args = ['file*']
160
takes_options = ['show-ids', 'revision']
148
takes_options = ['all', 'show-ids', 'revision']
161
149
aliases = ['st', 'stat']
163
encoding_type = 'replace'
166
def run(self, show_ids=False, file_list=None, revision=None):
152
def run(self, all=False, show_ids=False, file_list=None, revision=None):
153
tree, file_list = tree_files(file_list)
167
155
from bzrlib.status import show_tree_status
169
tree, file_list = tree_files(file_list)
171
show_tree_status(tree, show_ids=show_ids,
172
specific_files=file_list, revision=revision,
156
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
157
specific_files=file_list, revision=revision)
176
160
class cmd_cat_revision(Command):
194
176
if revision_id is None and revision is None:
195
177
raise BzrCommandError('You must supply either --revision or a revision_id')
196
178
b = WorkingTree.open_containing(u'.')[0].branch
198
# TODO: jam 20060112 should cat-revision always output utf-8?
199
179
if revision_id is not None:
200
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
180
sys.stdout.write(b.repository.get_revision_xml(revision_id))
201
181
elif revision is not None:
202
182
for rev in revision:
204
184
raise BzrCommandError('You cannot specify a NULL revision.')
205
185
revno, rev_id = rev.in_history(b)
206
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
186
sys.stdout.write(b.repository.get_revision_xml(rev_id))
209
189
class cmd_revno(Command):
210
190
"""Show current revision number.
212
This is equal to the number of revisions on this branch.
192
This is equal to the number of revisions on this branch."""
215
193
takes_args = ['location?']
218
195
def run(self, location=u'.'):
219
self.outf.write(str(Branch.open_containing(location)[0].revno()))
220
self.outf.write('\n')
196
print Branch.open_containing(location)[0].revno()
223
199
class cmd_revision_info(Command):
278
253
takes_args = ['file*']
279
254
takes_options = ['no-recurse', 'dry-run', 'verbose']
280
encoding_type = 'replace'
282
256
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
283
257
import bzrlib.add
285
action = bzrlib.add.AddAction(to_file=self.outf,
286
should_print=(not is_quiet()))
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
288
270
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
289
action=action, save=not dry_run)
290
272
if len(ignored) > 0:
292
for glob in sorted(ignored.keys()):
273
for glob in sorted(ignored.keys()):
274
match_len = len(ignored[glob])
293
276
for path in ignored[glob]:
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")
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"\
305
285
class cmd_mkdir(Command):
416
383
from one into the other. Once one branch has merged, the other should
417
384
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.
419
390
If you want to forget your local changes and just update your branch to
420
391
match the remote one, use pull --overwrite.
422
393
If there is no default location set, the first pull will set it. After
423
394
that, you can omit the location to use the default. To change the
424
default, use --remember. The value will only be saved if the remote
425
location can be accessed.
395
default, use --remember.
428
397
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
429
398
takes_args = ['location?']
430
encoding_type = 'replace'
432
400
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
433
401
# FIXME: too much stuff is in the command class
436
404
branch_to = tree_to.branch
437
405
except NoWorkingTree:
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
407
branch_to = Branch.open_containing(u'.')[0]
448
408
stored_loc = branch_to.get_parent()
449
409
if location is None:
450
410
if stored_loc is None:
451
411
raise BzrCommandError("No pull location known or specified.")
453
display_url = urlutils.unescape_for_display(stored_loc,
455
self.outf.write("Using saved location: %s\n" % display_url)
413
print "Using saved location: %s" % stored_loc
456
414
location = stored_loc
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)
416
if branch_to.get_parent() is None or remember:
417
branch_to.set_parent(location)
419
branch_from = Branch.open(location)
469
421
if revision is None:
470
if reader is not None:
471
rev_id = reader.target
472
423
elif len(revision) == 1:
473
424
rev_id = revision[0].in_history(branch_from).rev_id
513
463
If there is no default push location set, the first push will set it.
514
464
After that, you can omit the location to use the default. To change the
515
default, use --remember. The value will only be saved if the remote
516
location can be accessed.
465
default, use --remember.
519
takes_options = ['remember', 'overwrite', 'verbose',
467
takes_options = ['remember', 'overwrite',
520
468
Option('create-prefix',
521
469
help='Create the path leading up to the branch '
522
470
'if it does not already exist')]
523
471
takes_args = ['location?']
524
encoding_type = 'replace'
526
473
def run(self, location=None, remember=False, overwrite=False,
527
474
create_prefix=False, verbose=False):
528
475
# FIXME: Way too big! Put this into a function called from the
477
from bzrlib.transport import get_transport
531
br_from = Branch.open_containing('.')[0]
532
stored_loc = br_from.get_push_location()
479
tree_from = WorkingTree.open_containing(u'.')[0]
480
br_from = tree_from.branch
481
stored_loc = tree_from.branch.get_push_location()
533
482
if location is None:
534
483
if stored_loc is None:
535
484
raise BzrCommandError("No push location known or specified.")
537
display_url = urlutils.unescape_for_display(stored_loc,
539
self.outf.write("Using saved location: %s\n" % display_url)
486
print "Using saved location: %s" % stored_loc
540
487
location = stored_loc
542
to_transport = transport.get_transport(location)
543
location_url = to_transport.base
488
if br_from.get_push_location() is None or remember:
489
br_from.set_push_location(location)
547
dir_to = bzrdir.BzrDir.open(location_url)
491
dir_to = bzrlib.bzrdir.BzrDir.open(location)
548
492
br_to = dir_to.open_branch()
549
493
except NotBranchError:
550
494
# create a branch.
551
to_transport = to_transport.clone('..')
495
transport = get_transport(location).clone('..')
552
496
if not create_prefix:
554
relurl = to_transport.relpath(location_url)
555
mutter('creating directory %s => %s', location_url, relurl)
556
to_transport.mkdir(relurl)
498
transport.mkdir(transport.relpath(location))
557
499
except NoSuchFile:
558
500
raise BzrCommandError("Parent directory of %s "
559
501
"does not exist." % location)
561
current = to_transport.base
562
needed = [(to_transport, to_transport.relpath(location_url))]
503
current = transport.base
504
needed = [(transport, transport.relpath(location))]
565
to_transport, relpath = needed[-1]
566
to_transport.mkdir(relpath)
507
transport, relpath = needed[-1]
508
transport.mkdir(relpath)
568
510
except NoSuchFile:
569
new_transport = to_transport.clone('..')
511
new_transport = transport.clone('..')
570
512
needed.append((new_transport,
571
new_transport.relpath(to_transport.base)))
572
if new_transport.base == to_transport.base:
513
new_transport.relpath(transport.base)))
514
if new_transport.base == transport.base:
573
515
raise BzrCommandError("Could not create "
575
dir_to = br_from.bzrdir.clone(location_url,
576
revision_id=br_from.last_revision())
517
dir_to = br_from.bzrdir.clone(location)
577
518
br_to = dir_to.open_branch()
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()
519
old_rh = br_to.revision_history()
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.")
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.")
602
537
note('%d revision(s) pushed.' % (count,))
661
595
name = os.path.basename(to_location) + '\n'
663
to_transport = transport.get_transport(to_location)
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.' %
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.' %
673
608
# preserve whatever source format we have.
674
dir = br_from.bzrdir.sprout(to_transport.base,
675
revision_id, basis_dir)
609
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
676
610
branch = dir.open_branch()
677
except errors.NoSuchRevision:
678
to_transport.delete_tree('.')
611
except bzrlib.errors.NoSuchRevision:
679
613
msg = "The branch %s has no revision %s." % (from_location, revision[0])
680
614
raise BzrCommandError(msg)
681
except errors.UnlistableBranch:
682
osutils.rmtree(to_location)
615
except bzrlib.errors.UnlistableBranch:
683
617
msg = "The branch %s cannot be used as a --basis" % (basis,)
684
618
raise BzrCommandError(msg)
686
620
branch.control_files.put_utf8('branch-name', name)
687
622
note('Branched %d revision(s).' % branch.revno())
809
743
'bzr revert' instead of 'bzr commit' after the update.
811
745
takes_args = ['dir?']
814
747
def run(self, dir='.'):
815
748
tree = WorkingTree.open_containing(dir)[0]
816
749
tree.lock_write()
818
last_rev = tree.last_revision()
819
if last_rev == tree.branch.last_revision():
751
if tree.last_revision() == tree.branch.last_revision():
820
752
# may be up to date, check master too.
821
753
master = tree.branch.get_master_branch()
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,))
754
if master is None or master.last_revision == tree.last_revision():
755
note("Tree is up to date.")
826
757
conflicts = tree.update()
827
revno = tree.branch.revision_id_to_revno(tree.last_revision())
828
note('Updated to revision %d.' % (revno,))
758
note('Updated to revision %d.' %
759
(tree.branch.revision_id_to_revno(tree.last_revision()),))
829
760
if conflicts != 0:
859
783
This makes bzr stop tracking changes to a versioned file. It does
860
784
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.
867
takes_args = ['file*']
868
takes_options = ['verbose', Option('new', help='remove newly-added files')]
786
takes_args = ['file+']
787
takes_options = ['verbose']
870
encoding_type = 'replace'
872
def run(self, file_list, verbose=False, new=False):
790
def run(self, file_list, verbose=False):
873
791
tree, file_list = tree_files(file_list)
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)
792
tree.remove(file_list, verbose=verbose)
887
795
class cmd_file_id(Command):
949
852
def run(self, branch="."):
950
853
from bzrlib.reconcile import reconcile
951
dir = bzrdir.BzrDir.open(branch)
854
dir = bzrlib.bzrdir.BzrDir.open(branch)
955
858
class cmd_revision_history(Command):
956
"""Display the list of revision ids on a branch."""
957
takes_args = ['location?']
859
"""Display list of revision ids on this branch."""
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')
863
branch = WorkingTree.open_containing(u'.')[0].branch
864
for patchid in branch.revision_history():
969
868
class cmd_ancestry(Command):
970
869
"""List all revisions merged into this branch."""
971
takes_args = ['location?']
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')
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()):
993
880
class cmd_init(Command):
1014
901
takes_args = ['location?']
1015
902
takes_options = [
1016
903
Option('format',
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',
904
help='Create a specific format rather than the'
905
' current default format. Currently this '
906
' option only accepts "metadir"',
1021
907
type=get_format_type),
1023
909
def run(self, location=None, format=None):
1025
format = get_format_type('default')
910
from bzrlib.branch import Branch
1026
911
if location is None:
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:
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):
1043
922
existing_bzrdir = bzrdir.BzrDir.open(location)
1044
923
except NotBranchError:
1072
951
takes_args = ["location"]
1073
952
takes_options = [Option('format',
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',
953
help='Use a specific format rather than the'
954
' current default format. Currently this'
955
' option accepts "weave", "metadir" and "knit"',
1078
956
type=get_format_type),
1080
958
help='Allows branches in repository to have'
1081
959
' a working tree')]
1082
960
aliases = ["init-repo"]
1083
961
def run(self, location, format=None, trees=False):
962
from bzrlib.bzrdir import BzrDirMetaFormat1
963
from bzrlib.transport import get_transport
1084
964
if format is None:
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)
965
format = BzrDirMetaFormat1()
966
transport = get_transport(location)
967
if not transport.has('.'):
969
newdir = format.initialize_on_transport(transport)
1097
970
repo = newdir.create_repository(shared=True)
1098
971
repo.set_make_working_trees(trees)
1101
974
class cmd_diff(Command):
1102
"""Show differences in the working tree or between revisions.
975
"""Show differences in working tree.
1104
977
If files are listed, only the changes in those files are listed.
1105
978
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.
1124
986
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1125
987
# or a graphical diff.
1127
989
# TODO: Python difflib is not exactly the same as unidiff; should
1128
990
# either fix it up or prefer to use an external diff.
992
# TODO: If a directory is given, diff everything under that.
1130
994
# TODO: Selected-file diff is inefficient and doesn't show you
1131
995
# deleted files.
1133
997
# TODO: This probably handles non-Unix newlines poorly.
1135
999
takes_args = ['file*']
1136
takes_options = ['revision', 'diff-options', 'prefix']
1000
takes_options = ['revision', 'diff-options']
1137
1001
aliases = ['di', 'dif']
1138
encoding_type = 'exact'
1140
1003
@display_command
1141
def run(self, revision=None, file_list=None, diff_options=None,
1004
def run(self, revision=None, file_list=None, diff_options=None):
1143
1005
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(":")
1158
1007
tree1, file_list = internal_tree_files(file_list)
1169
1018
# FIXME diff those two files. rbc 20051123
1170
1019
raise BzrCommandError("Files are in different branches")
1171
1020
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
1181
1021
if revision is not None:
1182
1022
if tree2 is not None:
1183
1023
raise BzrCommandError("Can't specify -r with two branches")
1184
1024
if (len(revision) == 1) or (revision[1].spec is None):
1185
1025
return diff_cmd_helper(tree1, file_list, diff_options,
1187
old_label=old_label, new_label=new_label)
1188
1027
elif len(revision) == 2:
1189
1028
return diff_cmd_helper(tree1, file_list, diff_options,
1190
revision[0], revision[1],
1191
old_label=old_label, new_label=new_label)
1029
revision[0], revision[1])
1193
1031
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1195
1033
if tree2 is not None:
1196
1034
return show_diff_trees(tree1, tree2, sys.stdout,
1197
1035
specific_files=file_list,
1198
external_diff_options=diff_options,
1199
old_label=old_label, new_label=new_label)
1036
external_diff_options=diff_options)
1201
return diff_cmd_helper(tree1, file_list, diff_options,
1202
old_label=old_label, new_label=new_label)
1038
return diff_cmd_helper(tree1, file_list, diff_options)
1205
1041
class cmd_deleted(Command):
1808
1638
takes_args = ['url?']
1809
1639
takes_options = [
1810
1640
Option('format',
1811
help='Upgrade to a specific format. Current formats'
1812
' are: default, knit, metaweave and weave.'
1813
' Default is knit; metaweave and weave are'
1641
help='Upgrade to a specific format rather than the'
1642
' current default format. Currently this'
1643
' option accepts "weave", "metadir" and'
1815
1645
type=get_format_type),
1819
1649
def run(self, url='.', format=None):
1820
1650
from bzrlib.upgrade import upgrade
1822
format = get_format_type('default')
1823
1651
upgrade(url, format)
1826
1654
class cmd_whoami(Command):
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'
1655
"""Show bzr user id."""
1656
takes_options = ['email']
1842
1658
@display_command
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.
1659
def run(self, email=False):
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)
1661
b = WorkingTree.open_containing(u'.')[0].branch
1662
config = bzrlib.config.BranchConfig(b)
1663
except NotBranchError:
1664
config = bzrlib.config.GlobalConfig()
1863
# use global config unless --branch given
1865
c = Branch.open_containing('.')[0].get_config()
1667
print config.user_email()
1867
c = config.GlobalConfig()
1868
c.set_user_option('email', name)
1669
print config.username()
1871
1672
class cmd_nick(Command):
1936
1737
help='Use a different transport by default '
1937
1738
'throughout the test suite.',
1938
1739
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.'),
1945
def run(self, testspecs_list=None, verbose=None, one=False,
1946
keep_output=False, transport=None, benchmark=None,
1742
def run(self, testspecs_list=None, verbose=False, one=False,
1743
keep_output=False, transport=None):
1948
1744
import bzrlib.ui
1949
1745
from bzrlib.tests import selftest
1950
import bzrlib.benchmarks as benchmarks
1951
1746
# we don't want progress meters from the tests to go to the
1952
1747
# real output; and we don't want log messages cluttering up
1953
1748
# the real logs.
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...')
1749
save_ui = bzrlib.ui.ui_factory
1750
bzrlib.trace.info('running tests...')
1960
ui.ui_factory = ui.SilentUIFactory()
1752
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1961
1753
if testspecs_list is not None:
1962
1754
pattern = '|'.join(testspecs_list)
1966
test_suite_factory = benchmarks.test_suite
1970
test_suite_factory = None
1973
1757
result = selftest(verbose=verbose,
1974
1758
pattern=pattern,
1975
1759
stop_on_failure=one,
1976
1760
keep_output=keep_output,
1977
transport=transport,
1978
test_suite_factory=test_suite_factory,
1979
lsprof_timed=lsprof_timed)
1761
transport=transport)
1981
info('tests passed')
1763
bzrlib.trace.info('tests passed')
1983
info('tests failed')
1765
bzrlib.trace.info('tests failed')
1984
1766
return int(not result)
1986
ui.ui_factory = save_ui
1768
bzrlib.ui.ui_factory = save_ui
1989
1771
def _get_bzr_branch():
1990
1772
"""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
1991
1776
from os.path import dirname
1994
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1779
branch = Branch.open(dirname(abspath(dirname(__file__))))
1996
except errors.BzrError:
1781
except bzrlib.errors.BzrError:
2000
1785
def show_version():
2002
print "Bazaar (bzr) %s" % bzrlib.__version__
1786
print "bzr (bazaar-ng) %s" % bzrlib.__version__
2003
1787
# is bzrlib itself in a branch?
2004
1788
branch = _get_bzr_branch()
2073
1842
base_rev_id = common_ancestor(last1, last2, source)
2075
1844
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)
2078
1859
class cmd_merge(Command):
2079
1860
"""Perform a three-way merge.
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
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.
2087
1868
By default, bzr will try to merge in all new work from the other
2088
1869
branch, automatically determining an appropriate base. If this
2114
1894
merge refuses to run if there are any uncommitted changes, unless
2115
1895
--force is given.
2117
The following merge types are available:
2119
1897
takes_args = ['branch?']
2120
1898
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2121
1899
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()
2129
1902
def run(self, branch=None, revision=None, force=False, merge_type=None,
2130
1903
show_base=False, reprocess=False, remember=False):
2131
1904
if merge_type is None:
2132
1905
merge_type = Merge3Merger
2134
1907
tree = WorkingTree.open_containing(u'.')[0]
2136
if branch is not None:
2138
reader = bundle.read_bundle_from_url(branch)
2140
pass # Continue on considering this url a Branch
1908
stored_loc = tree.branch.get_parent()
1910
if stored_loc is None:
1911
raise BzrCommandError("No merge branch known or specified.")
2142
conflicts = merge_bundle(reader, tree, not force, merge_type,
2143
reprocess, show_base)
1913
print "Using saved branch: %s" % stored_loc
2149
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1916
if tree.branch.get_parent() is None or remember:
1917
tree.branch.set_parent(branch)
2151
1919
if revision is None or len(revision) < 1:
2152
1920
base = [None, None]
2163
1931
if None in revision:
2164
1932
raise BzrCommandError(
2165
1933
"Merge doesn't permit that revision specifier.")
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)
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]
2175
1939
interesting_files = [path]
2177
1941
interesting_files = None
2178
pb = ui.ui_factory.nested_progress_bar()
1942
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2181
1945
conflict_count = merge(other, base, check_clean=(not force),
2182
merge_type=merge_type,
1946
merge_type=merge_type,
2183
1947
reprocess=reprocess,
2184
show_base=show_base,
1948
show_base=show_base,
2185
1949
pb=pb, file_list=interesting_files)
2198
1962
"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
2218
1966
class cmd_remerge(Command):
2219
1967
"""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:"""
2239
1969
takes_args = ['file*']
2240
1970
takes_options = ['merge-type', 'reprocess',
2241
1971
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()
2249
1974
def run(self, file_list=None, merge_type=None, show_base=False,
2250
1975
reprocess=False):
2251
1976
from bzrlib.merge import merge_inner, transform_tree
2411
encoding_type = 'replace'
2414
2134
def run(self, other_branch=None, reverse=False, mine_only=False,
2415
2135
theirs_only=False, log_format=None, long=False, short=False, line=False,
2416
2136
show_ids=False, verbose=False):
2417
2137
from bzrlib.missing import find_unmerged, iter_log_data
2418
2138
from bzrlib.log import log_formatter
2419
local_branch = Branch.open_containing(u".")[0]
2139
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2420
2140
parent = local_branch.get_parent()
2421
2141
if other_branch is None:
2422
2142
other_branch = parent
2423
2143
if other_branch is None:
2424
raise BzrCommandError("No peer location known or specified.")
2144
raise BzrCommandError("No missing location known or specified.")
2425
2145
print "Using last location: " + local_branch.get_parent()
2426
remote_branch = Branch.open(other_branch)
2146
remote_branch = bzrlib.branch.Branch.open(other_branch)
2427
2147
if remote_branch.base == local_branch.base:
2428
2148
remote_branch = local_branch
2429
2149
local_branch.lock_read()
2500
2218
class cmd_testament(Command):
2501
2219
"""Show testament (signing-form) of a revision."""
2502
takes_options = ['revision', 'long',
2503
Option('strict', help='Produce a strict-format'
2220
takes_options = ['revision', 'long']
2505
2221
takes_args = ['branch?']
2506
2222
@display_command
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
2223
def run(self, branch=u'.', revision=None, long=False):
2224
from bzrlib.testament import Testament
2513
2225
b = WorkingTree.open_containing(branch)[0].branch
2536
2248
shown only at the top, unless the --all option is given.
2538
2250
# TODO: annotate directories; showing when each file was last changed
2251
# TODO: annotate a previous version of a file
2539
2252
# TODO: if the working copy is modified, show annotations on that
2540
2253
# with new uncommitted lines marked
2541
aliases = ['ann', 'blame', 'praise']
2254
aliases = ['blame', 'praise']
2542
2255
takes_args = ['filename']
2543
2256
takes_options = [Option('all', help='show annotations on all lines'),
2544
2257
Option('long', help='show date in annotations'),
2548
2260
@display_command
2549
def run(self, filename, all=False, long=False, revision=None):
2261
def run(self, filename, all=False, long=False):
2550
2262
from bzrlib.annotate import annotate_file
2551
2263
tree, relpath = WorkingTree.open_containing(filename)
2552
2264
branch = tree.branch
2553
2265
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
2561
2267
file_id = tree.inventory.path2id(relpath)
2562
tree = branch.repository.revision_tree(revision_id)
2268
tree = branch.repository.revision_tree(branch.last_revision())
2563
2269
file_version = tree.inventory[file_id].revision
2564
2270
annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2642
2348
raise BzrCommandError('Local branch is not bound')
2645
class cmd_uncommit(Command):
2351
class cmd_uncommit(bzrlib.commands.Command):
2646
2352
"""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
2648
2358
--verbose will print out what is being removed.
2649
2359
--dry-run will go through all the motions, but not actually
2650
2360
remove anything.
2652
In the future, uncommit will create a revision bundle, which can then
2362
In the future, uncommit will create a changeset, which can then
2656
2366
# TODO: jam 20060108 Add an option to allow uncommit to remove
2657
# unreferenced information in 'branch-as-repository' branches.
2367
# unreferenced information in 'branch-as-repostory' branches.
2658
2368
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2659
2369
# information in shared branches as well.
2660
2370
takes_options = ['verbose', 'revision',
2681
2392
b = control.open_branch()
2684
2394
if revision is None:
2685
2395
revno = b.revno()
2396
rev_id = b.last_revision()
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)
2398
revno, rev_id = revision[0].in_history(b)
2696
2399
if rev_id is 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())
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)
2712
2408
print 'Dry-run, pretending to remove the above revisions.'
2730
2426
CAUTION: Locks should only be broken when you are sure that the process
2731
2427
holding the lock has been stopped.
2733
You can get information on what locks are open via the 'bzr info' command.
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:
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")
2751
2442
# command-line interpretation helper for merge-related commands