17
17
"""builtin bzr commands"""
26
from bzrlib.branch import Branch
27
import bzrlib.bzrdir as bzrdir
26
from bzrlib.branch import Branch, BranchReferenceFormat
27
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
28
29
from bzrlib.bundle.read_bundle import BundleReader
29
from bzrlib.bundle.apply_bundle import merge_bundle
30
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
30
31
from bzrlib.commands import Command, display_command
31
import bzrlib.errors as errors
32
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
33
33
NotBranchError, DivergedBranches, NotConflicted,
34
34
NoSuchFile, NoWorkingTree, FileInWrongBranch,
35
NotVersionedError, BadBundle)
36
from bzrlib.log import show_one_log
35
NotVersionedError, NotABundle)
37
36
from bzrlib.merge import Merge3Merger
38
37
from bzrlib.option import Option
39
38
from bzrlib.progress import DummyProgress, ProgressPhase
40
39
from bzrlib.revision import common_ancestor
41
40
from bzrlib.revisionspec import RevisionSpec
43
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
42
from bzrlib.transport.local import LocalTransport
43
import bzrlib.urlutils as urlutils
46
44
from bzrlib.workingtree import WorkingTree
90
88
return bzrdir.BzrDirMetaFormat1()
91
89
if typestring == "metaweave":
92
90
format = bzrdir.BzrDirMetaFormat1()
93
format.repository_format = bzrlib.repository.RepositoryFormat7()
91
format.repository_format = repository.RepositoryFormat7()
95
93
if typestring == "knit":
96
94
format = bzrdir.BzrDirMetaFormat1()
97
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
95
format.repository_format = repository.RepositoryFormatKnit1()
99
97
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
98
"metaweave and weave" % typestring
150
144
# TODO: --no-recurse, --recurse options
152
146
takes_args = ['file*']
153
takes_options = ['all', 'show-ids', 'revision']
147
takes_options = ['show-ids', 'revision']
154
148
aliases = ['st', 'stat']
150
encoding_type = 'replace'
157
def run(self, all=False, show_ids=False, file_list=None, revision=None):
158
tree, file_list = tree_files(file_list)
153
def run(self, show_ids=False, file_list=None, revision=None):
160
154
from bzrlib.status import show_tree_status
161
show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
162
specific_files=file_list, revision=revision)
156
tree, file_list = tree_files(file_list)
158
show_tree_status(tree, show_ids=show_ids,
159
specific_files=file_list, revision=revision,
165
163
class cmd_cat_revision(Command):
173
171
takes_args = ['revision_id?']
174
172
takes_options = ['revision']
173
# cat-revision is more for frontends so should be exact
177
177
def run(self, revision_id=None, revision=None):
181
181
if revision_id is None and revision is None:
182
182
raise BzrCommandError('You must supply either --revision or a revision_id')
183
183
b = WorkingTree.open_containing(u'.')[0].branch
185
# TODO: jam 20060112 should cat-revision always output utf-8?
184
186
if revision_id is not None:
185
sys.stdout.write(b.repository.get_revision_xml(revision_id))
187
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
186
188
elif revision is not None:
187
189
for rev in revision:
189
191
raise BzrCommandError('You cannot specify a NULL revision.')
190
192
revno, rev_id = rev.in_history(b)
191
sys.stdout.write(b.repository.get_revision_xml(rev_id))
193
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
194
196
class cmd_revno(Command):
195
197
"""Show current revision number.
197
This is equal to the number of revisions on this branch."""
199
This is equal to the number of revisions on this branch.
198
202
takes_args = ['location?']
200
205
def run(self, location=u'.'):
201
print Branch.open_containing(location)[0].revno()
206
self.outf.write(str(Branch.open_containing(location)[0].revno()))
207
self.outf.write('\n')
204
210
class cmd_revision_info(Command):
250
257
Adding a file whose parent directory is not versioned will
251
258
implicitly add the parent, and so on up to the root. This means
252
you should never need to explictly add a directory, they'll just
259
you should never need to explicitly add a directory, they'll just
253
260
get added when you add a file in the directory.
255
262
--dry-run will show which files would be added, but not actually
258
265
takes_args = ['file*']
259
266
takes_options = ['no-recurse', 'dry-run', 'verbose']
267
encoding_type = 'replace'
261
269
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
262
270
import bzrlib.add
266
# This is pointless, but I'd rather not raise an error
267
action = bzrlib.add.add_action_null
269
action = bzrlib.add.add_action_print
271
action = bzrlib.add.add_action_add
273
action = bzrlib.add.add_action_add_and_print
272
action = bzrlib.add.AddAction(to_file=self.outf,
273
should_print=(not is_quiet()))
275
275
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
276
action=action, save=not dry_run)
277
277
if len(ignored) > 0:
279
279
for glob in sorted(ignored.keys()):
280
280
for path in ignored[glob]:
281
print "ignored %s matching \"%s\"" % (path, glob)
281
self.outf.write("ignored %s matching \"%s\"\n"
284
285
for glob, paths in ignored.items():
285
286
match_len += len(paths)
286
print "ignored %d file(s)." % match_len
287
print "If you wish to add some of these files, please add them"\
287
self.outf.write("ignored %d file(s).\n" % match_len)
288
self.outf.write("If you wish to add some of these files,"
289
" please add them by name.\n")
291
292
class cmd_mkdir(Command):
294
295
This is equivalent to creating the directory and then adding it.
296
298
takes_args = ['dir+']
299
encoding_type = 'replace'
298
301
def run(self, dir_list):
299
302
for d in dir_list:
301
304
wt, dd = WorkingTree.open_containing(d)
306
self.outf.write('added %s\n' % d)
306
309
class cmd_relpath(Command):
307
310
"""Show path of a file relative to root"""
308
312
takes_args = ['filename']
312
316
def run(self, filename):
317
# TODO: jam 20050106 Can relpath return a munged path if
318
# sys.stdout encoding cannot represent it?
313
319
tree, relpath = WorkingTree.open_containing(filename)
320
self.outf.write(relpath)
321
self.outf.write('\n')
317
324
class cmd_inventory(Command):
359
368
Files cannot be moved between branches.
361
371
takes_args = ['names*']
362
372
aliases = ['move', 'rename']
373
encoding_type = 'replace'
364
375
def run(self, names_list):
365
376
if len(names_list) < 2:
369
380
if os.path.isdir(names_list[-1]):
370
381
# move into existing directory
371
382
for pair in tree.move(rel_names[:-1], rel_names[-1]):
372
print "%s => %s" % pair
383
self.outf.write("%s => %s\n" % pair)
374
385
if len(names_list) != 2:
375
386
raise BzrCommandError('to mv multiple files the destination '
376
387
'must be a versioned directory')
377
388
tree.rename_one(rel_names[0], rel_names[1])
378
print "%s => %s" % (rel_names[0], rel_names[1])
389
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
381
392
class cmd_pull(Command):
399
410
If there is no default location set, the first pull will set it. After
400
411
that, you can omit the location to use the default. To change the
401
default, use --remember.
412
default, use --remember. The value will only be saved if the remote
413
location can be accessed.
403
416
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
404
417
takes_args = ['location?']
418
encoding_type = 'replace'
406
420
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
407
421
# FIXME: too much stuff is in the command class
410
424
branch_to = tree_to.branch
411
425
except NoWorkingTree:
413
branch_to = Branch.open_containing(u'.')[0]
427
branch_to = Branch.open_containing(u'.')[0]
430
if location is not None:
432
reader = bundle.read_bundle_from_url(location)
434
pass # Continue on considering this url a Branch
414
436
stored_loc = branch_to.get_parent()
415
437
if location is None:
416
438
if stored_loc is None:
417
439
raise BzrCommandError("No pull location known or specified.")
419
print "Using saved location: %s" % stored_loc
441
display_url = urlutils.unescape_for_display(stored_loc,
443
self.outf.write("Using saved location: %s\n" % display_url)
420
444
location = stored_loc
422
if branch_to.get_parent() is None or remember:
423
branch_to.set_parent(location)
425
branch_from = Branch.open(location)
447
if reader is not None:
448
install_bundle(branch_to.repository, reader)
449
branch_from = branch_to
451
branch_from = Branch.open(location)
453
if branch_to.get_parent() is None or remember:
454
branch_to.set_parent(branch_from.base)
427
457
if revision is None:
458
if reader is not None:
459
rev_id = reader.info.target
429
460
elif len(revision) == 1:
430
461
rev_id = revision[0].in_history(branch_from).rev_id
443
474
if old_rh != new_rh:
444
475
# Something changed
445
476
from bzrlib.log import show_changed_revisions
446
show_changed_revisions(branch_to, old_rh, new_rh)
477
show_changed_revisions(branch_to, old_rh, new_rh,
449
481
class cmd_push(Command):
469
501
If there is no default push location set, the first push will set it.
470
502
After that, you can omit the location to use the default. To change the
471
default, use --remember.
503
default, use --remember. The value will only be saved if the remote
504
location can be accessed.
473
takes_options = ['remember', 'overwrite',
507
takes_options = ['remember', 'overwrite', 'verbose',
474
508
Option('create-prefix',
475
509
help='Create the path leading up to the branch '
476
510
'if it does not already exist')]
477
511
takes_args = ['location?']
512
encoding_type = 'replace'
479
514
def run(self, location=None, remember=False, overwrite=False,
480
515
create_prefix=False, verbose=False):
488
523
if stored_loc is None:
489
524
raise BzrCommandError("No push location known or specified.")
491
print "Using saved location: %s" % stored_loc
526
display_url = urlutils.unescape_for_display(stored_loc,
528
self.outf.write("Using saved location: %s\n" % display_url)
492
529
location = stored_loc
493
if br_from.get_push_location() is None or remember:
494
br_from.set_push_location(location)
531
transport = get_transport(location)
532
location_url = transport.base
496
dir_to = bzrlib.bzrdir.BzrDir.open(location)
536
dir_to = bzrdir.BzrDir.open(location_url)
497
537
br_to = dir_to.open_branch()
498
538
except NotBranchError:
499
539
# create a branch.
500
transport = get_transport(location).clone('..')
540
transport = transport.clone('..')
501
541
if not create_prefix:
503
transport.mkdir(transport.relpath(location))
543
relurl = transport.relpath(location_url)
544
mutter('creating directory %s => %s', location_url, relurl)
545
transport.mkdir(relurl)
504
546
except NoSuchFile:
505
547
raise BzrCommandError("Parent directory of %s "
506
548
"does not exist." % location)
508
550
current = transport.base
509
needed = [(transport, transport.relpath(location))]
551
needed = [(transport, transport.relpath(location_url))]
512
554
transport, relpath = needed[-1]
519
561
if new_transport.base == transport.base:
520
562
raise BzrCommandError("Could not create "
522
dir_to = br_from.bzrdir.clone(location,
564
dir_to = br_from.bzrdir.clone(location_url,
523
565
revision_id=br_from.last_revision())
524
566
br_to = dir_to.open_branch()
525
567
count = len(br_to.revision_history())
568
# We successfully created the target, remember it
569
if br_from.get_push_location() is None or remember:
570
br_from.set_push_location(br_to.base)
572
# We were able to connect to the remote location, so remember it
573
# we don't need to successfully push because of possible divergence.
574
if br_from.get_push_location() is None or remember:
575
br_from.set_push_location(br_to.base)
527
576
old_rh = br_to.revision_history()
546
595
if old_rh != new_rh:
547
596
# Something changed
548
597
from bzrlib.log import show_changed_revisions
549
show_changed_revisions(br_to, old_rh, new_rh)
598
show_changed_revisions(br_to, old_rh, new_rh,
552
602
class cmd_branch(Command):
567
617
aliases = ['get', 'clone']
569
619
def run(self, from_location, to_location=None, revision=None, basis=None):
570
from bzrlib.osutils import rmtree
620
from bzrlib.transport import get_transport
571
621
if revision is None:
572
622
revision = [None]
573
623
elif len(revision) > 1:
601
651
name = os.path.basename(to_location) + '\n'
653
to_transport = get_transport(to_location)
603
os.mkdir(to_location)
605
if e.errno == errno.EEXIST:
606
raise BzrCommandError('Target directory "%s" already'
607
' exists.' % to_location)
608
if e.errno == errno.ENOENT:
609
raise BzrCommandError('Parent of "%s" does not exist.' %
655
to_transport.mkdir('.')
656
except errors.FileExists:
657
raise BzrCommandError('Target directory "%s" already'
658
' exists.' % to_location)
659
except errors.NoSuchFile:
660
raise BzrCommandError('Parent of "%s" does not exist.' %
614
663
# preserve whatever source format we have.
615
dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
664
dir = br_from.bzrdir.sprout(to_transport.base,
665
revision_id, basis_dir)
616
666
branch = dir.open_branch()
617
except bzrlib.errors.NoSuchRevision:
667
except errors.NoSuchRevision:
668
to_transport.delete_tree('.')
619
669
msg = "The branch %s has no revision %s." % (from_location, revision[0])
620
670
raise BzrCommandError(msg)
621
except bzrlib.errors.UnlistableBranch:
671
except errors.UnlistableBranch:
672
osutils.rmtree(to_location)
623
673
msg = "The branch %s cannot be used as a --basis" % (basis,)
624
674
raise BzrCommandError(msg)
626
676
branch.control_files.put_utf8('branch-name', name)
628
677
note('Branched %d revision(s).' % branch.revno())
669
718
raise BzrCommandError(
670
719
'bzr checkout --revision takes exactly 1 revision value')
671
720
if branch_location is None:
672
branch_location = bzrlib.osutils.getcwd()
721
branch_location = osutils.getcwd()
673
722
to_location = branch_location
674
723
source = Branch.open(branch_location)
675
724
if len(revision) == 1 and revision[0] is not None:
681
730
# if the source and to_location are the same,
682
731
# and there is no working tree,
683
732
# then reconstitute a branch
684
if (bzrlib.osutils.abspath(to_location) ==
685
bzrlib.osutils.abspath(branch_location)):
733
if (osutils.abspath(to_location) ==
734
osutils.abspath(branch_location)):
687
736
source.bzrdir.open_workingtree()
688
737
except errors.NoWorkingTree:
702
old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
703
bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
751
old_format = bzrdir.BzrDirFormat.get_default_format()
752
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
706
755
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
707
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
756
branch.BranchReferenceFormat().initialize(checkout, source)
709
checkout_branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
758
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
710
759
to_location, force_new_tree=False)
711
760
checkout = checkout_branch.bzrdir
712
761
checkout_branch.bind(source)
715
764
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
716
765
checkout.create_workingtree(revision_id)
718
bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
767
bzrdir.BzrDirFormat.set_default_format(old_format)
721
770
class cmd_renames(Command):
730
779
def run(self, dir=u'.'):
780
from bzrlib.tree import find_renames
731
781
tree = WorkingTree.open_containing(dir)[0]
732
782
old_inv = tree.basis_tree().inventory
733
783
new_inv = tree.read_working_inventory()
735
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
784
renames = list(find_renames(old_inv, new_inv))
737
786
for old_name, new_name in renames:
738
print "%s => %s" % (old_name, new_name)
787
self.outf.write("%s => %s\n" % (old_name, new_name))
741
790
class cmd_update(Command):
804
853
takes_args = ['file*']
805
854
takes_options = ['verbose', Option('new', help='remove newly-added files')]
856
encoding_type = 'replace'
808
858
def run(self, file_list, verbose=False, new=False):
809
859
tree, file_list = tree_files(file_list)
818
868
file_list = sorted([f[0] for f in added[0]], reverse=True)
819
869
if len(file_list) == 0:
820
870
raise BzrCommandError('No matching files.')
821
tree.remove(file_list, verbose=verbose)
871
tree.remove(file_list, verbose=verbose, to_file=self.outf)
824
874
class cmd_file_id(Command):
838
890
raise BzrError("%r is not a versioned file" % filename)
892
self.outf.write(i + '\n')
843
895
class cmd_file_path(Command):
844
896
"""Print path of file_ids to a file or directory.
846
898
This prints one line for each directory down to the target,
847
starting at the branch root."""
899
starting at the branch root.
849
903
takes_args = ['filename']
851
906
def run(self, filename):
852
907
tree, relpath = WorkingTree.open_containing(filename)
881
936
def run(self, branch="."):
882
937
from bzrlib.reconcile import reconcile
883
dir = bzrlib.bzrdir.BzrDir.open(branch)
938
dir = bzrdir.BzrDir.open(branch)
887
942
class cmd_revision_history(Command):
888
"""Display list of revision ids on this branch."""
943
"""Display the list of revision ids on a branch."""
944
takes_args = ['location?']
892
branch = WorkingTree.open_containing(u'.')[0].branch
893
for patchid in branch.revision_history():
949
def run(self, location="."):
950
branch = Branch.open_containing(location)[0]
951
for revid in branch.revision_history():
952
self.outf.write(revid)
953
self.outf.write('\n')
897
956
class cmd_ancestry(Command):
898
957
"""List all revisions merged into this branch."""
958
takes_args = ['location?']
902
tree = WorkingTree.open_containing(u'.')[0]
904
# FIXME. should be tree.last_revision
905
revision_ids = b.repository.get_ancestry(b.last_revision())
963
def run(self, location="."):
965
wt = WorkingTree.open_containing(location)[0]
966
except errors.NoWorkingTree:
967
b = Branch.open(location)
968
last_revision = b.last_revision()
971
last_revision = wt.last_revision()
973
revision_ids = b.repository.get_ancestry(last_revision)
906
974
assert revision_ids[0] == None
907
975
revision_ids.pop(0)
908
976
for revision_id in revision_ids:
977
self.outf.write(revision_id + '\n')
912
980
class cmd_init(Command):
1037
1104
takes_args = ['file*']
1038
1105
takes_options = ['revision', 'diff-options', 'prefix']
1039
1106
aliases = ['di', 'dif']
1107
encoding_type = 'exact'
1041
1109
@display_command
1042
1110
def run(self, revision=None, file_list=None, diff_options=None,
1103
1171
# directories with readdir, rather than stating each one. Same
1104
1172
# level of effort but possibly much less IO. (Or possibly not,
1105
1173
# if the directories are very large...)
1174
takes_options = ['show-ids']
1106
1176
@display_command
1107
1177
def run(self, show_ids=False):
1108
1178
tree = WorkingTree.open_containing(u'.')[0]
1109
1179
old = tree.basis_tree()
1110
1180
for path, ie in old.inventory.iter_entries():
1111
1181
if not tree.has_id(ie.file_id):
1182
self.outf.write(path)
1113
print '%-50s %s' % (path, ie.file_id)
1184
self.outf.write(' ')
1185
self.outf.write(ie.file_id)
1186
self.outf.write('\n')
1118
1189
class cmd_modified(Command):
1126
1197
td = compare_trees(tree.basis_tree(), tree)
1128
1199
for path, id, kind, text_modified, meta_modified in td.modified:
1200
self.outf.write(path + '\n')
1133
1203
class cmd_added(Command):
1142
1212
if file_id in basis_inv:
1144
1214
path = inv.id2path(file_id)
1145
if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1215
if not os.access(osutils.abspath(path), os.F_OK):
1217
self.outf.write(path + '\n')
1151
1220
class cmd_root(Command):
1152
1221
"""Show the tree root directory.
1206
1277
from bzrlib.log import log_formatter, show_log
1208
1278
assert message is None or isinstance(message, basestring), \
1209
1279
"invalid message argument %r" % message
1210
1280
direction = (forward and 'forward') or 'reverse'
1256
1326
if rev1 > rev2:
1257
1327
(rev2, rev1) = (rev1, rev2)
1259
mutter('encoding log as %r', bzrlib.user_encoding)
1261
# use 'replace' so that we don't abort if trying to write out
1262
# in e.g. the default C locale.
1263
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1265
1329
if (log_format == None):
1266
default = bzrlib.config.BranchConfig(b).log_format()
1330
default = config.BranchConfig(b).log_format()
1267
1331
log_format = get_log_format(long=long, short=short, line=line, default=default)
1269
1332
lf = log_formatter(log_format,
1270
1333
show_ids=show_ids,
1272
1335
show_timezone=timezone)
1295
1358
class cmd_touching_revisions(Command):
1296
1359
"""Return revision-ids which affected a particular file.
1298
A more user-friendly interface is "bzr log FILE"."""
1361
A more user-friendly interface is "bzr log FILE".
1300
1365
takes_args = ["filename"]
1301
1367
@display_command
1302
1368
def run(self, filename):
1303
1369
tree, relpath = WorkingTree.open_containing(filename)
1304
1370
b = tree.branch
1305
1371
inv = tree.read_working_inventory()
1306
1372
file_id = inv.path2id(relpath)
1307
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1308
print "%6d %s" % (revno, what)
1373
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1374
self.outf.write("%6d %s\n" % (revno, what))
1311
1377
class cmd_ls(Command):
1344
1410
if revision is not None:
1345
1411
tree = tree.branch.repository.revision_tree(
1346
1412
revision[0].in_history(tree.branch).rev_id)
1347
1414
for fp, fc, kind, fid, entry in tree.list_files():
1348
1415
if fp.startswith(relpath):
1349
1416
fp = fp[len(relpath):]
1355
1422
kindch = entry.kind_character()
1356
print '%-8s %s%s' % (fc, fp, kindch)
1423
self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1358
sys.stdout.write(fp)
1359
sys.stdout.write('\0')
1425
self.outf.write(fp + '\0')
1428
self.outf.write(fp + '\n')
1365
1431
class cmd_unknowns(Command):
1366
1432
"""List unknown files."""
1367
1433
@display_command
1369
from bzrlib.osutils import quotefn
1370
1435
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1436
self.outf.write(osutils.quotefn(f) + '\n')
1374
1439
class cmd_ignore(Command):
1591
1656
from bzrlib.msgeditor import edit_commit_message, \
1592
1657
make_commit_message_template
1593
1658
from tempfile import TemporaryFile
1596
1660
# TODO: Need a blackbox test for invoking the external editor; may be
1597
1661
# slightly problematic to run this cross-platform.
1620
1684
raise BzrCommandError("please specify either --message or --file")
1624
1687
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1626
1689
if message == "":
1627
raise BzrCommandError("empty commit message specified")
1690
raise BzrCommandError("empty commit message specified")
1630
1693
reporter = ReportCommitToLog()
1723
1786
def run(self, email=False):
1725
1788
b = WorkingTree.open_containing(u'.')[0].branch
1726
config = bzrlib.config.BranchConfig(b)
1789
c = config.BranchConfig(b)
1727
1790
except NotBranchError:
1728
config = bzrlib.config.GlobalConfig()
1791
c = config.GlobalConfig()
1731
print config.user_email()
1793
print c.user_email()
1733
print config.username()
1736
1798
class cmd_nick(Command):
1816
1878
# we don't want progress meters from the tests to go to the
1817
1879
# real output; and we don't want log messages cluttering up
1818
1880
# the real logs.
1819
save_ui = bzrlib.ui.ui_factory
1820
print '%10s: %s' % ('bzr', bzrlib.osutils.realpath(sys.argv[0]))
1881
save_ui = ui.ui_factory
1882
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1821
1883
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1823
bzrlib.trace.info('running tests...')
1885
info('running tests...')
1825
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1887
ui.ui_factory = ui.SilentUIFactory()
1826
1888
if testspecs_list is not None:
1827
1889
pattern = '|'.join(testspecs_list)
1843
1905
test_suite_factory=test_suite_factory,
1844
1906
lsprof_timed=lsprof_timed)
1846
bzrlib.trace.info('tests passed')
1908
info('tests passed')
1848
bzrlib.trace.info('tests failed')
1910
info('tests failed')
1849
1911
return int(not result)
1851
bzrlib.ui.ui_factory = save_ui
1913
ui.ui_factory = save_ui
1854
1916
def _get_bzr_branch():
1855
1917
"""If bzr is run from a branch, return Branch or None"""
1856
import bzrlib.errors
1857
from bzrlib.branch import Branch
1858
from bzrlib.osutils import abspath
1859
1918
from os.path import dirname
1862
branch = Branch.open(dirname(abspath(dirname(__file__))))
1921
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1864
except bzrlib.errors.BzrError:
1923
except errors.BzrError:
1868
1927
def show_version():
1869
1929
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1870
1930
# is bzrlib itself in a branch?
1871
1931
branch = _get_bzr_branch()
1937
1997
base_rev_id = common_ancestor(last1, last2, source)
1939
1999
print 'merge base is revision %s' % base_rev_id
1943
if base_revno is None:
1944
raise bzrlib.errors.UnrelatedBranches()
1946
print ' r%-6d in %s' % (base_revno, branch)
1948
other_revno = branch2.revision_id_to_revno(base_revid)
1950
print ' r%-6d in %s' % (other_revno, other)
1954
2002
class cmd_merge(Command):
1955
2003
"""Perform a three-way merge.
1957
The branch is the branch you will merge from. By default, it will
1958
merge the latest revision. If you specify a revision, that
1959
revision will be merged. If you specify two revisions, the first
1960
will be used as a BASE, and the second one as OTHER. Revision
1961
numbers are always relative to the specified branch.
2005
The branch is the branch you will merge from. By default, it will merge
2006
the latest revision. If you specify a revision, that revision will be
2007
merged. If you specify two revisions, the first will be used as a BASE,
2008
and the second one as OTHER. Revision numbers are always relative to the
1963
2011
By default, bzr will try to merge in all new work from the other
1964
2012
branch, automatically determining an appropriate base. If this
1974
2022
If there is no default branch set, the first merge will set it. After
1975
2023
that, you can omit the branch to use the default. To change the
1976
default, use --remember.
2024
default, use --remember. The value will only be saved if the remote
2025
location can be accessed.
2006
2055
if merge_type is None:
2007
2056
merge_type = Merge3Merger
2010
2058
tree = WorkingTree.open_containing(u'.')[0]
2012
if branch is not None:
2013
reader = BundleReader(file(branch, 'rb'))
2017
if e.errno not in (errno.ENOENT, errno.EISDIR):
2022
if reader is not None:
2023
conflicts = merge_bundle(reader, tree, not force, merge_type,
2024
reprocess, show_base)
2030
stored_loc = tree.branch.get_parent()
2032
if stored_loc is None:
2033
raise BzrCommandError("No merge branch known or specified.")
2035
print "Using saved branch: %s" % stored_loc
2038
if tree.branch.get_parent() is None or remember:
2039
tree.branch.set_parent(branch)
2060
if branch is not None:
2062
reader = bundle.read_bundle_from_url(branch)
2064
pass # Continue on considering this url a Branch
2066
conflicts = merge_bundle(reader, tree, not force, merge_type,
2067
reprocess, show_base)
2073
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2041
2075
if revision is None or len(revision) < 1:
2042
2076
base = [None, None]
2053
2087
if None in revision:
2054
2088
raise BzrCommandError(
2055
2089
"Merge doesn't permit that revision specifier.")
2056
b, path = Branch.open_containing(branch)
2058
base = [branch, revision[0].in_history(b).revno]
2059
other = [branch, revision[1].in_history(b).revno]
2090
other_branch, path = Branch.open_containing(branch)
2092
base = [branch, revision[0].in_history(other_branch).revno]
2093
other = [branch, revision[1].in_history(other_branch).revno]
2095
if tree.branch.get_parent() is None or remember:
2096
tree.branch.set_parent(other_branch.base)
2061
2099
interesting_files = [path]
2063
2101
interesting_files = None
2064
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2102
pb = ui.ui_factory.nested_progress_bar()
2067
2105
conflict_count = merge(other, base, check_clean=(not force),
2068
merge_type=merge_type,
2106
merge_type=merge_type,
2069
2107
reprocess=reprocess,
2070
show_base=show_base,
2108
show_base=show_base,
2071
2109
pb=pb, file_list=interesting_files)
2084
2122
"and (if you want) report this to the bzr developers\n")
2125
# TODO: move up to common parent; this isn't merge-specific anymore.
2126
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2127
"""Use tree.branch's parent if none was supplied.
2129
Report if the remembered location was used.
2131
if supplied_location is not None:
2132
return supplied_location
2133
stored_location = tree.branch.get_parent()
2134
mutter("%s", stored_location)
2135
if stored_location is None:
2136
raise BzrCommandError("No location specified or remembered")
2137
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2138
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2139
return stored_location
2088
2142
class cmd_remerge(Command):
2089
2143
"""Redo a merge.
2198
2252
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2200
2254
rev_id = revision[0].in_history(tree.branch).rev_id
2201
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2255
pb = ui.ui_factory.nested_progress_bar()
2203
2257
tree.revert(file_list,
2204
2258
tree.branch.repository.revision_tree(rev_id),
2252
2306
takes_args = ['from_branch', 'to_branch']
2253
2307
def run(self, from_branch, to_branch):
2254
2308
from bzrlib.fetch import Fetcher
2255
from bzrlib.branch import Branch
2256
2309
from_b = Branch.open(from_branch)
2257
2310
to_b = Branch.open(to_branch)
2258
2311
Fetcher(to_b, from_b)
2281
2334
show_ids=False, verbose=False):
2282
2335
from bzrlib.missing import find_unmerged, iter_log_data
2283
2336
from bzrlib.log import log_formatter
2284
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2337
local_branch = Branch.open_containing(u".")[0]
2285
2338
parent = local_branch.get_parent()
2286
2339
if other_branch is None:
2287
2340
other_branch = parent
2288
2341
if other_branch is None:
2289
2342
raise BzrCommandError("No missing location known or specified.")
2290
2343
print "Using last location: " + local_branch.get_parent()
2291
remote_branch = bzrlib.branch.Branch.open(other_branch)
2344
remote_branch = Branch.open(other_branch)
2292
2345
if remote_branch.base == local_branch.base:
2293
2346
remote_branch = local_branch
2294
2347
local_branch.lock_read()
2298
2351
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2299
2352
if (log_format == None):
2300
default = bzrlib.config.BranchConfig(local_branch).log_format()
2353
default = config.BranchConfig(local_branch).log_format()
2301
2354
log_format = get_log_format(long=long, short=short, line=line, default=default)
2302
2355
lf = log_formatter(log_format, sys.stdout,
2303
2356
show_ids=show_ids,
2363
2416
class cmd_testament(Command):
2364
2417
"""Show testament (signing-form) of a revision."""
2365
takes_options = ['revision', 'long']
2418
takes_options = ['revision', 'long',
2419
Option('strict', help='Produce a strict testament')]
2366
2420
takes_args = ['branch?']
2367
2421
@display_command
2368
def run(self, branch=u'.', revision=None, long=False):
2369
from bzrlib.testament import Testament
2422
def run(self, branch=u'.', revision=None, long=False, strict=False):
2423
from bzrlib.testament import Testament, StrictTestament
2425
testament_class = StrictTestament
2427
testament_class = Testament
2370
2428
b = WorkingTree.open_containing(branch)[0].branch
2374
2432
rev_id = b.last_revision()
2376
2434
rev_id = revision[0].in_history(b).rev_id
2377
t = Testament.from_revision(b.repository, rev_id)
2435
t = testament_class.from_revision(b.repository, rev_id)
2379
2437
sys.stdout.writelines(t.as_text_lines())
2432
2490
takes_options = ['revision']
2434
2492
def run(self, revision_id_list=None, revision=None):
2435
import bzrlib.config as config
2436
2493
import bzrlib.gpg as gpg
2437
2494
if revision_id_list is not None and revision is not None:
2438
2495
raise BzrCommandError('You can only supply one of revision_id or --revision')
2500
2557
raise BzrCommandError('Local branch is not bound')
2503
class cmd_uncommit(bzrlib.commands.Command):
2560
class cmd_uncommit(Command):
2504
2561
"""Remove the last committed revision.
2506
2563
--verbose will print out what is being removed.
2514
2571
# TODO: jam 20060108 Add an option to allow uncommit to remove
2515
# unreferenced information in 'branch-as-repostory' branches.
2572
# unreferenced information in 'branch-as-repository' branches.
2516
2573
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2517
2574
# information in shared branches as well.
2518
2575
takes_options = ['verbose', 'revision',
2524
2581
def run(self, location=None,
2525
2582
dry_run=False, verbose=False,
2526
2583
revision=None, force=False):
2527
from bzrlib.branch import Branch
2528
2584
from bzrlib.log import log_formatter
2530
2586
from bzrlib.uncommit import uncommit