1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
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"""
20
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
23
from shutil import rmtree
54
28
from bzrlib.branch import Branch
55
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
56
from bzrlib.conflicts import ConflictList
29
import bzrlib.bzrdir as bzrdir
30
from bzrlib.bundle.read_bundle import BundleReader
31
from bzrlib.bundle.apply_bundle import merge_bundle
32
from bzrlib.commands import Command, display_command
33
import bzrlib.errors as errors
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
NotVersionedError, BadBundle)
38
from bzrlib.log import show_one_log
39
from bzrlib.merge import Merge3Merger
40
from bzrlib.option import Option
42
from bzrlib.progress import DummyProgress, ProgressPhase
43
from bzrlib.revision import common_ancestor
57
44
from bzrlib.revisionspec import RevisionSpec
58
from bzrlib.smtp_connection import SMTPConnection
46
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
47
from bzrlib.transport.local import LocalTransport
49
import bzrlib.urlutils as urlutils
59
50
from bzrlib.workingtree import WorkingTree
62
from bzrlib.commands import Command, display_command
63
from bzrlib.option import ListOption, Option, RegistryOption
64
from bzrlib.progress import DummyProgress, ProgressPhase
65
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
68
53
def tree_files(file_list, default_branch=u'.'):
70
55
return internal_tree_files(file_list, default_branch)
71
except errors.FileInWrongBranch, e:
72
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
(e.path, file_list[0]))
56
except FileInWrongBranch, e:
57
raise BzrCommandError("%s is not in the same branch as %s" %
58
(e.path, file_list[0]))
76
61
# XXX: Bad function name; should possibly also be a class method of
324
267
Adding a file whose parent directory is not versioned will
325
268
implicitly add the parent, and so on up to the root. This means
326
you should never need to explicitly add a directory, they'll just
269
you should never need to explictly add a directory, they'll just
327
270
get added when you add a file in the directory.
329
272
--dry-run will show which files would be added, but not actually
332
--file-ids-from will try to use the file ids from the supplied path.
333
It looks up ids trying to find a matching parent directory with the
334
same filename, and then by pure path. This option is rarely needed
335
but can be useful when adding the same logical file into two
336
branches that will be merged later (without showing the two different
337
adds as a conflict). It is also useful when merging another project
338
into a subdirectory of this one.
340
275
takes_args = ['file*']
341
takes_options = ['no-recurse', 'dry-run', 'verbose',
342
Option('file-ids-from', type=unicode,
343
help='Lookup file ids from here')]
276
takes_options = ['no-recurse', 'dry-run', 'verbose']
344
277
encoding_type = 'replace'
345
_see_also = ['remove']
347
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
279
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
349
280
import bzrlib.add
352
if file_ids_from is not None:
354
base_tree, base_path = WorkingTree.open_containing(
356
except errors.NoWorkingTree:
357
base_branch, base_path = Branch.open_containing(
359
base_tree = base_branch.basis_tree()
361
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
362
to_file=self.outf, should_print=(not is_quiet()))
364
action = bzrlib.add.AddAction(to_file=self.outf,
365
should_print=(not is_quiet()))
368
base_tree.lock_read()
370
file_list = self._maybe_expand_globs(file_list)
372
tree = WorkingTree.open_containing(file_list[0])[0]
374
tree = WorkingTree.open_containing(u'.')[0]
375
added, ignored = tree.smart_add(file_list, not
376
no_recurse, action=action, save=not dry_run)
378
if base_tree is not None:
282
action = bzrlib.add.AddAction(to_file=self.outf,
283
should_add=(not dry_run), should_print=(not is_quiet()))
285
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
380
287
if len(ignored) > 0:
382
289
for glob in sorted(ignored.keys()):
544
407
from one into the other. Once one branch has merged, the other should
545
408
be able to pull it again.
410
If branches have diverged, you can use 'bzr merge' to pull the text changes
411
from one into the other. Once one branch has merged, the other should
412
be able to pull it again.
547
414
If you want to forget your local changes and just update your branch to
548
415
match the remote one, use pull --overwrite.
550
417
If there is no default location set, the first pull will set it. After
551
418
that, you can omit the location to use the default. To change the
552
default, use --remember. The value will only be saved if the remote
553
location can be accessed.
419
default, use --remember.
556
_see_also = ['push', 'update', 'status-flags']
557
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
559
help='branch to pull into, '
560
'rather than the one containing the working directory',
421
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
565
422
takes_args = ['location?']
566
423
encoding_type = 'replace'
568
def run(self, location=None, remember=False, overwrite=False,
569
revision=None, verbose=False,
571
from bzrlib.tag import _merge_tags_if_possible
425
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
572
426
# FIXME: too much stuff is in the command class
575
if directory is None:
578
tree_to = WorkingTree.open_containing(directory)[0]
428
tree_to = WorkingTree.open_containing(u'.')[0]
579
429
branch_to = tree_to.branch
580
except errors.NoWorkingTree:
430
except NoWorkingTree:
582
branch_to = Branch.open_containing(directory)[0]
585
if location is not None:
587
mergeable = bundle.read_mergeable_from_url(
589
except errors.NotABundle:
590
pass # Continue on considering this url a Branch
432
branch_to = Branch.open_containing(u'.')[0]
592
433
stored_loc = branch_to.get_parent()
593
434
if location is None:
594
435
if stored_loc is None:
595
raise errors.BzrCommandError("No pull location known or"
436
raise BzrCommandError("No pull location known or specified.")
598
438
display_url = urlutils.unescape_for_display(stored_loc,
599
439
self.outf.encoding)
600
440
self.outf.write("Using saved location: %s\n" % display_url)
601
441
location = stored_loc
603
if mergeable is not None:
604
if revision is not None:
605
raise errors.BzrCommandError(
606
'Cannot use -r with merge directives or bundles')
607
revision_id = mergeable.install_revisions(branch_to.repository)
608
branch_from = branch_to
443
branch_from = Branch.open(location)
445
if branch_to.get_parent() is None or remember:
446
branch_to.set_parent(branch_from.base)
450
elif len(revision) == 1:
451
rev_id = revision[0].in_history(branch_from).rev_id
610
branch_from = Branch.open(location)
612
if branch_to.get_parent() is None or remember:
613
branch_to.set_parent(branch_from.base)
615
if revision is not None:
616
if len(revision) == 1:
617
revision_id = revision[0].in_history(branch_from).rev_id
619
raise errors.BzrCommandError(
620
'bzr pull --revision takes one value.')
453
raise BzrCommandError('bzr pull --revision takes one value.')
622
455
old_rh = branch_to.revision_history()
623
456
if tree_to is not None:
624
result = tree_to.pull(branch_from, overwrite, revision_id,
625
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
457
count = tree_to.pull(branch_from, overwrite, rev_id)
627
result = branch_to.pull(branch_from, overwrite, revision_id)
459
count = branch_to.pull(branch_from, overwrite, rev_id)
460
note('%d revision(s) pulled.' % (count,))
629
result.report(self.outf)
631
from bzrlib.log import show_changed_revisions
632
463
new_rh = branch_to.revision_history()
633
show_changed_revisions(branch_to, old_rh, new_rh,
466
from bzrlib.log import show_changed_revisions
467
show_changed_revisions(branch_to, old_rh, new_rh,
637
471
class cmd_push(Command):
657
491
If there is no default push location set, the first push will set it.
658
492
After that, you can omit the location to use the default. To change the
659
default, use --remember. The value will only be saved if the remote
660
location can be accessed.
493
default, use --remember.
663
_see_also = ['pull', 'update', 'working-trees']
664
495
takes_options = ['remember', 'overwrite', 'verbose',
665
Option('create-prefix',
666
help='Create the path leading up to the branch '
667
'if it does not already exist'),
669
help='branch to push from, '
670
'rather than the one containing the working directory',
674
Option('use-existing-dir',
675
help='By default push will fail if the target'
676
' directory exists, but does not already'
677
' have a control directory. This flag will'
678
' allow push to proceed.'),
496
Option('create-prefix',
497
help='Create the path leading up to the branch '
498
'if it does not already exist')]
680
499
takes_args = ['location?']
681
500
encoding_type = 'replace'
683
502
def run(self, location=None, remember=False, overwrite=False,
684
create_prefix=False, verbose=False,
685
use_existing_dir=False,
503
create_prefix=False, verbose=False):
687
504
# FIXME: Way too big! Put this into a function called from the
689
if directory is None:
691
br_from = Branch.open_containing(directory)[0]
506
from bzrlib.transport import get_transport
508
br_from = Branch.open_containing('.')[0]
692
509
stored_loc = br_from.get_push_location()
693
510
if location is None:
694
511
if stored_loc is None:
695
raise errors.BzrCommandError("No push location known or specified.")
512
raise BzrCommandError("No push location known or specified.")
697
514
display_url = urlutils.unescape_for_display(stored_loc,
698
515
self.outf.encoding)
699
self.outf.write("Using saved location: %s\n" % display_url)
516
self.outf.write("Using saved location: %s" % display_url)
700
517
location = stored_loc
702
to_transport = transport.get_transport(location)
519
transport = get_transport(location)
520
location_url = transport.base
521
if br_from.get_push_location() is None or remember:
522
br_from.set_push_location(location_url)
704
br_to = repository_to = dir_to = None
706
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
707
except errors.NotBranchError:
708
pass # Didn't find anything
710
# If we can open a branch, use its direct repository, otherwise see
711
# if there is a repository without a branch.
713
br_to = dir_to.open_branch()
714
except errors.NotBranchError:
715
# Didn't find a branch, can we find a repository?
717
repository_to = dir_to.find_repository()
718
except errors.NoRepositoryPresent:
721
# Found a branch, so we must have found a repository
722
repository_to = br_to.repository
726
# The destination doesn't exist; create it.
727
# XXX: Refactor the create_prefix/no_create_prefix code into a
728
# common helper function
730
to_transport.mkdir('.')
731
except errors.FileExists:
732
if not use_existing_dir:
733
raise errors.BzrCommandError("Target directory %s"
734
" already exists, but does not have a valid .bzr"
735
" directory. Supply --use-existing-dir to push"
736
" there anyway." % location)
737
except errors.NoSuchFile:
738
if not create_prefix:
739
raise errors.BzrCommandError("Parent directory of %s"
741
"\nYou may supply --create-prefix to create all"
742
" leading parent directories."
745
_create_prefix(to_transport)
747
# Now the target directory exists, but doesn't have a .bzr
748
# directory. So we need to create it, along with any work to create
749
# all of the dependent branches, etc.
750
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
526
dir_to = bzrlib.bzrdir.BzrDir.open(location_url)
527
br_to = dir_to.open_branch()
528
except NotBranchError:
530
transport = transport.clone('..')
531
if not create_prefix:
533
relurl = transport.relpath(location_url)
534
mutter('creating directory %s => %s', location_url, relurl)
535
transport.mkdir(relurl)
537
raise BzrCommandError("Parent directory of %s "
538
"does not exist." % location)
540
current = transport.base
541
needed = [(transport, transport.relpath(location_url))]
544
transport, relpath = needed[-1]
545
transport.mkdir(relpath)
548
new_transport = transport.clone('..')
549
needed.append((new_transport,
550
new_transport.relpath(transport.base)))
551
if new_transport.base == transport.base:
552
raise BzrCommandError("Could not create "
554
dir_to = br_from.bzrdir.clone(location_url,
751
555
revision_id=br_from.last_revision())
752
556
br_to = dir_to.open_branch()
753
# TODO: Some more useful message about what was copied
754
note('Created new branch.')
755
# We successfully created the target, remember it
756
if br_from.get_push_location() is None or remember:
757
br_from.set_push_location(br_to.base)
758
elif repository_to is None:
759
# we have a bzrdir but no branch or repository
760
# XXX: Figure out what to do other than complain.
761
raise errors.BzrCommandError("At %s you have a valid .bzr control"
762
" directory, but not a branch or repository. This is an"
763
" unsupported configuration. Please move the target directory"
764
" out of the way and try again."
767
# We have a repository but no branch, copy the revisions, and then
769
last_revision_id = br_from.last_revision()
770
repository_to.fetch(br_from.repository,
771
revision_id=last_revision_id)
772
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
773
note('Created new branch.')
774
if br_from.get_push_location() is None or remember:
775
br_from.set_push_location(br_to.base)
776
else: # We have a valid to branch
777
# We were able to connect to the remote location, so remember it
778
# we don't need to successfully push because of possible divergence.
779
if br_from.get_push_location() is None or remember:
780
br_from.set_push_location(br_to.base)
557
count = len(br_to.revision_history())
781
559
old_rh = br_to.revision_history()
784
562
tree_to = dir_to.open_workingtree()
785
563
except errors.NotLocalUrl:
786
warning("This transport does not update the working "
787
"tree of: %s. See 'bzr help working-trees' for "
788
"more information." % br_to.base)
789
push_result = br_from.push(br_to, overwrite)
790
except errors.NoWorkingTree:
791
push_result = br_from.push(br_to, overwrite)
564
warning('This transport does not update the working '
565
'tree of: %s' % (br_to.base,))
566
count = br_to.pull(br_from, overwrite)
567
except NoWorkingTree:
568
count = br_to.pull(br_from, overwrite)
795
push_result = br_from.push(tree_to.branch, overwrite)
799
except errors.DivergedBranches:
800
raise errors.BzrCommandError('These branches have diverged.'
801
' Try using "merge" and then "push".')
802
if push_result is not None:
803
push_result.report(self.outf)
570
count = tree_to.pull(br_from, overwrite)
571
except DivergedBranches:
572
raise BzrCommandError("These branches have diverged."
573
" Try a merge then push with overwrite.")
574
note('%d revision(s) pushed.' % (count,))
805
577
new_rh = br_to.revision_history()
806
578
if old_rh != new_rh:
807
579
# Something changed
808
580
from bzrlib.log import show_changed_revisions
809
581
show_changed_revisions(br_to, old_rh, new_rh,
810
582
to_file=self.outf)
812
# we probably did a clone rather than a push, so a message was
817
585
class cmd_branch(Command):
1065
838
also new, they will also be removed.
1067
840
takes_args = ['file*']
1068
takes_options = ['verbose',
1069
Option('new', help='remove newly-added files'),
1070
RegistryOption.from_kwargs('file-deletion-strategy',
1071
'The file deletion mode to be used',
1072
title='Deletion Strategy', value_switches=True, enum_switch=False,
1073
safe='Only delete files if they can be'
1074
' safely recovered (default).',
1075
keep="Don't delete any files.",
1076
force='Delete all the specified files, even if they can not be '
1077
'recovered and even if they are non-empty directories.')]
841
takes_options = ['verbose', Option('new', help='remove newly-added files')]
1078
842
aliases = ['rm']
1079
843
encoding_type = 'replace'
1081
def run(self, file_list, verbose=False, new=False,
1082
file_deletion_strategy='safe'):
845
def run(self, file_list, verbose=False, new=False):
1083
846
tree, file_list = tree_files(file_list)
1085
if file_list is not None:
1086
file_list = [f for f in file_list if f != '']
1088
raise errors.BzrCommandError('Specify one or more files to'
1089
' remove, or use --new.')
1092
added = tree.changes_from(tree.basis_tree(),
1093
specific_files=file_list).added
1094
file_list = sorted([f[0] for f in added], reverse=True)
848
if file_list is None:
849
raise BzrCommandError('Specify one or more files to remove, or'
852
from bzrlib.delta import compare_trees
853
added = [compare_trees(tree.basis_tree(), tree,
854
specific_files=file_list).added]
855
file_list = sorted([f[0] for f in added[0]], reverse=True)
1095
856
if len(file_list) == 0:
1096
raise errors.BzrCommandError('No matching files.')
1097
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1098
keep_files=file_deletion_strategy=='keep',
1099
force=file_deletion_strategy=='force')
857
raise BzrCommandError('No matching files.')
858
tree.remove(file_list, verbose=verbose, to_file=self.outf)
1102
861
class cmd_file_id(Command):
1235
976
bzr commit -m 'imported project'
1238
_see_also = ['init-repo', 'branch', 'checkout']
1239
978
takes_args = ['location?']
1240
979
takes_options = [
1241
Option('create-prefix',
1242
help='Create the path leading up to the branch '
1243
'if it does not already exist'),
1244
RegistryOption('format',
1245
help='Specify a format for this branch. '
1246
'See "help formats".',
1247
registry=bzrdir.format_registry,
1248
converter=bzrdir.format_registry.make_bzrdir,
1249
value_switches=True,
1250
title="Branch Format",
1252
Option('append-revisions-only',
1253
help='Never change revnos or the existing log.'
1254
' Append revisions to it only.')
1256
def run(self, location=None, format=None, append_revisions_only=False,
1257
create_prefix=False):
981
help='Specify a format for this branch. Current'
982
' formats are: default, knit, metaweave and'
983
' weave. Default is knit; metaweave and'
984
' weave are deprecated',
985
type=get_format_type),
987
def run(self, location=None, format=None):
988
from bzrlib.branch import Branch
1258
989
if format is None:
1259
format = bzrdir.format_registry.make_bzrdir('default')
990
format = get_format_type('default')
1260
991
if location is None:
1263
to_transport = transport.get_transport(location)
1265
# The path has to exist to initialize a
1266
# branch inside of it.
1267
# Just using os.mkdir, since I don't
1268
# believe that we want to create a bunch of
1269
# locations if the user supplies an extended path
1271
to_transport.ensure_base()
1272
except errors.NoSuchFile:
1273
if not create_prefix:
1274
raise errors.BzrCommandError("Parent directory of %s"
1276
"\nYou may supply --create-prefix to create all"
1277
" leading parent directories."
1279
_create_prefix(to_transport)
994
# The path has to exist to initialize a
995
# branch inside of it.
996
# Just using os.mkdir, since I don't
997
# believe that we want to create a bunch of
998
# locations if the user supplies an extended path
999
if not os.path.exists(location):
1282
1002
existing_bzrdir = bzrdir.BzrDir.open(location)
1283
except errors.NotBranchError:
1003
except NotBranchError:
1284
1004
# really a NotBzrDir error...
1285
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1005
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1288
from bzrlib.transport.local import LocalTransport
1289
1007
if existing_bzrdir.has_branch():
1290
if (isinstance(to_transport, LocalTransport)
1291
and not existing_bzrdir.has_workingtree()):
1292
raise errors.BranchExistsWithoutWorkingTree(location)
1293
raise errors.AlreadyBranchError(location)
1008
if existing_bzrdir.has_workingtree():
1009
raise errors.AlreadyBranchError(location)
1011
raise errors.BranchExistsWithoutWorkingTree(location)
1295
branch = existing_bzrdir.create_branch()
1013
existing_bzrdir.create_branch()
1296
1014
existing_bzrdir.create_workingtree()
1297
if append_revisions_only:
1299
branch.set_append_revisions_only(True)
1300
except errors.UpgradeRequired:
1301
raise errors.BzrCommandError('This branch format cannot be set'
1302
' to append-revisions-only. Try --experimental-branch6')
1305
1017
class cmd_init_repository(Command):
1306
1018
"""Create a shared repository to hold branches.
1308
New branches created under the repository directory will store their
1309
revisions in the repository, not in the branch directory.
1311
If the --no-trees option is used then the branches in the repository
1312
will not have working trees by default.
1020
New branches created under the repository directory will store their revisions
1021
in the repository, not in the branch directory, if the branch format supports
1315
bzr init-repo --no-trees repo
1316
1026
bzr init repo/trunk
1317
1027
bzr checkout --lightweight repo/trunk trunk-checkout
1318
1028
cd trunk-checkout
1319
1029
(add files here)
1321
See 'bzr help repositories' for more information.
1324
_see_also = ['init', 'branch', 'checkout']
1325
takes_args = ["location"]
1326
takes_options = [RegistryOption('format',
1327
help='Specify a format for this repository. See'
1328
' "bzr help formats" for details',
1329
registry=bzrdir.format_registry,
1330
converter=bzrdir.format_registry.make_bzrdir,
1331
value_switches=True, title='Repository format'),
1333
help='Branches in the repository will default to'
1334
' not having a working tree'),
1031
takes_args = ["location"]
1032
takes_options = [Option('format',
1033
help='Specify a format for this repository.'
1034
' Current formats are: default, knit,'
1035
' metaweave and weave. Default is knit;'
1036
' metaweave and weave are deprecated',
1037
type=get_format_type),
1039
help='Allows branches in repository to have'
1336
1041
aliases = ["init-repo"]
1338
def run(self, location, format=None, no_trees=False):
1042
def run(self, location, format=None, trees=False):
1043
from bzrlib.transport import get_transport
1339
1044
if format is None:
1340
format = bzrdir.format_registry.make_bzrdir('default')
1342
if location is None:
1345
to_transport = transport.get_transport(location)
1346
to_transport.ensure_base()
1348
newdir = format.initialize_on_transport(to_transport)
1045
format = get_format_type('default')
1046
transport = get_transport(location)
1047
if not transport.has('.'):
1049
newdir = format.initialize_on_transport(transport)
1349
1050
repo = newdir.create_repository(shared=True)
1350
repo.set_make_working_trees(not no_trees)
1051
repo.set_make_working_trees(trees)
1353
1054
class cmd_diff(Command):
1354
"""Show differences in the working tree or between revisions.
1055
"""Show differences in working tree.
1356
1057
If files are listed, only the changes in those files are listed.
1357
1058
Otherwise, all changes for the tree are listed.
1407
1096
elif prefix == '1':
1408
1097
old_label = 'old/'
1409
1098
new_label = 'new/'
1100
if not ':' in prefix:
1101
raise BzrError("--diff-prefix expects two values separated by a colon")
1411
1102
old_label, new_label = prefix.split(":")
1413
raise errors.BzrCommandError(
1414
'--prefix expects two values separated by a colon'
1415
' (eg "old/:new/")')
1417
if revision and len(revision) > 2:
1418
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1419
' one or two revision specifiers')
1422
1105
tree1, file_list = internal_tree_files(file_list)
1426
except errors.FileInWrongBranch:
1109
except FileInWrongBranch:
1427
1110
if len(file_list) != 2:
1428
raise errors.BzrCommandError("Files are in different branches")
1111
raise BzrCommandError("Files are in different branches")
1430
1113
tree1, file1 = WorkingTree.open_containing(file_list[0])
1431
1114
tree2, file2 = WorkingTree.open_containing(file_list[1])
1432
1115
if file1 != "" or file2 != "":
1433
1116
# FIXME diff those two files. rbc 20051123
1434
raise errors.BzrCommandError("Files are in different branches")
1117
raise BzrCommandError("Files are in different branches")
1435
1118
file_list = None
1436
except errors.NotBranchError:
1437
if (revision is not None and len(revision) == 2
1438
and not revision[0].needs_branch()
1439
and not revision[1].needs_branch()):
1440
# If both revision specs include a branch, we can
1441
# diff them without needing a local working tree
1442
tree1, tree2 = None, None
1446
if tree2 is not None:
1447
if revision is not None:
1448
# FIXME: but there should be a clean way to diff between
1449
# non-default versions of two trees, it's not hard to do
1451
raise errors.BzrCommandError(
1452
"Sorry, diffing arbitrary revisions across branches "
1453
"is not implemented yet")
1454
return show_diff_trees(tree1, tree2, sys.stdout,
1455
specific_files=file_list,
1456
external_diff_options=diff_options,
1457
old_label=old_label, new_label=new_label)
1459
return diff_cmd_helper(tree1, file_list, diff_options,
1460
revision_specs=revision,
1461
old_label=old_label, new_label=new_label)
1119
if revision is not None:
1120
if tree2 is not None:
1121
raise BzrCommandError("Can't specify -r with two branches")
1122
if (len(revision) == 1) or (revision[1].spec is None):
1123
return diff_cmd_helper(tree1, file_list, diff_options,
1125
old_label=old_label, new_label=new_label)
1126
elif len(revision) == 2:
1127
return diff_cmd_helper(tree1, file_list, diff_options,
1128
revision[0], revision[1],
1129
old_label=old_label, new_label=new_label)
1131
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1133
if tree2 is not None:
1134
return show_diff_trees(tree1, tree2, sys.stdout,
1135
specific_files=file_list,
1136
external_diff_options=diff_options,
1137
old_label=old_label, new_label=new_label)
1139
return diff_cmd_helper(tree1, file_list, diff_options,
1140
old_label=old_label, new_label=new_label)
1464
1143
class cmd_deleted(Command):
1619
1266
# find the file id to log:
1621
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1268
dir, fp = bzrdir.BzrDir.open_containing(location)
1269
b = dir.open_branch()
1625
tree = b.basis_tree()
1626
file_id = tree.path2id(fp)
1628
raise errors.BzrCommandError(
1629
"Path does not have any revision history: %s" %
1273
inv = dir.open_workingtree().inventory
1274
except (errors.NotBranchError, errors.NotLocalUrl):
1275
# either no tree, or is remote.
1276
inv = b.basis_tree().inventory
1277
file_id = inv.path2id(fp)
1632
1279
# local dir only
1633
1280
# FIXME ? log the current subdir only RBC 20060203
1634
if revision is not None \
1635
and len(revision) > 0 and revision[0].get_branch():
1636
location = revision[0].get_branch()
1639
dir, relpath = bzrdir.BzrDir.open_containing(location)
1281
dir, relpath = bzrdir.BzrDir.open_containing('.')
1640
1282
b = dir.open_branch()
1644
if revision is None:
1647
elif len(revision) == 1:
1648
rev1 = rev2 = revision[0].in_history(b)
1649
elif len(revision) == 2:
1650
if revision[1].get_branch() != revision[0].get_branch():
1651
# b is taken from revision[0].get_branch(), and
1652
# show_log will use its revision_history. Having
1653
# different branches will lead to weird behaviors.
1654
raise errors.BzrCommandError(
1655
"Log doesn't accept two revisions in different"
1657
rev1 = revision[0].in_history(b)
1658
rev2 = revision[1].in_history(b)
1660
raise errors.BzrCommandError(
1661
'bzr log --revision takes one or two values.')
1663
if log_format is None:
1664
log_format = log.log_formatter_registry.get_default(b)
1666
lf = log_format(show_ids=show_ids, to_file=self.outf,
1667
show_timezone=timezone)
1673
direction=direction,
1674
start_revision=rev1,
1284
if revision is None:
1287
elif len(revision) == 1:
1288
rev1 = rev2 = revision[0].in_history(b).revno
1289
elif len(revision) == 2:
1290
if revision[0].spec is None:
1291
# missing begin-range means first revision
1294
rev1 = revision[0].in_history(b).revno
1296
if revision[1].spec is None:
1297
# missing end-range means last known revision
1300
rev2 = revision[1].in_history(b).revno
1302
raise BzrCommandError('bzr log --revision takes one or two values.')
1304
# By this point, the revision numbers are converted to the +ve
1305
# form if they were supplied in the -ve form, so we can do
1306
# this comparison in relative safety
1308
(rev2, rev1) = (rev1, rev2)
1310
if (log_format == None):
1311
default = bzrlib.config.BranchConfig(b).log_format()
1312
log_format = get_log_format(long=long, short=short, line=line, default=default)
1313
lf = log_formatter(log_format,
1316
show_timezone=timezone)
1322
direction=direction,
1323
start_revision=rev1,
1682
1328
def get_log_format(long=False, short=False, line=False, default='long'):
1725
1368
Option('ignored', help='Print ignored files'),
1727
1370
Option('null', help='Null separate the files'),
1730
1372
@display_command
1731
1373
def run(self, revision=None, verbose=False,
1732
1374
non_recursive=False, from_root=False,
1733
1375
unknown=False, versioned=False, ignored=False,
1734
null=False, kind=None, show_ids=False, path=None):
1736
if kind and kind not in ('file', 'directory', 'symlink'):
1737
raise errors.BzrCommandError('invalid kind specified')
1739
1378
if verbose and null:
1740
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1379
raise BzrCommandError('Cannot set both --verbose and --null')
1741
1380
all = not (unknown or versioned or ignored)
1743
1382
selection = {'I':ignored, '?':unknown, 'V':versioned}
1750
raise errors.BzrCommandError('cannot specify both --from-root'
1754
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1384
tree, relpath = WorkingTree.open_containing(u'.')
1760
1389
if revision is not None:
1761
tree = branch.repository.revision_tree(
1762
revision[0].in_history(branch).rev_id)
1764
tree = branch.basis_tree()
1390
tree = tree.branch.repository.revision_tree(
1391
revision[0].in_history(tree.branch).rev_id)
1768
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1769
if fp.startswith(relpath):
1770
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1771
if non_recursive and '/' in fp:
1773
if not all and not selection[fc]:
1775
if kind is not None and fkind != kind:
1778
kindch = entry.kind_character()
1779
outstring = '%-8s %s%s' % (fc, fp, kindch)
1780
if show_ids and fid is not None:
1781
outstring = "%-50s %s" % (outstring, fid)
1782
self.outf.write(outstring + '\n')
1784
self.outf.write(fp + '\0')
1787
self.outf.write(fid)
1788
self.outf.write('\0')
1796
self.outf.write('%-50s %s\n' % (fp, my_id))
1798
self.outf.write(fp + '\n')
1393
for fp, fc, kind, fid, entry in tree.list_files():
1394
if fp.startswith(relpath):
1395
fp = fp[len(relpath):]
1396
if non_recursive and '/' in fp:
1398
if not all and not selection[fc]:
1401
kindch = entry.kind_character()
1402
self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1405
self.outf.write('\0')
1409
self.outf.write('\n')
1803
1412
class cmd_unknowns(Command):
1804
"""List unknown files.
1413
"""List unknown files."""
1810
1414
@display_command
1416
from bzrlib.osutils import quotefn
1812
1417
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1813
self.outf.write(osutils.quotefn(f) + '\n')
1418
self.outf.write(quotefn(f))
1419
self.outf.write('\n')
1816
1422
class cmd_ignore(Command):
1817
"""Ignore specified files or patterns.
1423
"""Ignore a command or pattern.
1819
1425
To remove patterns from the ignore list, edit the .bzrignore file.
1821
Trailing slashes on patterns are ignored.
1822
If the pattern contains a slash or is a regular expression, it is compared
1823
to the whole path from the branch root. Otherwise, it is compared to only
1824
the last component of the path. To match a file only in the root
1825
directory, prepend './'.
1827
Ignore patterns specifying absolute paths are not allowed.
1829
Ignore patterns may include globbing wildcards such as:
1830
? - Matches any single character except '/'
1831
* - Matches 0 or more characters except '/'
1832
/**/ - Matches 0 or more directories in a path
1833
[a-z] - Matches a single character from within a group of characters
1835
Ignore patterns may also be Python regular expressions.
1836
Regular expression ignore patterns are identified by a 'RE:' prefix
1837
followed by the regular expression. Regular expression ignore patterns
1838
may not include named or numbered groups.
1840
Note: ignore patterns containing shell wildcards must be quoted from
1427
If the pattern contains a slash, it is compared to the whole path
1428
from the branch root. Otherwise, it is compared to only the last
1429
component of the path. To match a file only in the root directory,
1432
Ignore patterns are case-insensitive on case-insensitive systems.
1434
Note: wildcards must be quoted from the shell on Unix.
1844
1437
bzr ignore ./Makefile
1845
1438
bzr ignore '*.class'
1846
bzr ignore 'lib/**/*.o'
1847
bzr ignore 'RE:lib/.*\.o'
1850
_see_also = ['status', 'ignored']
1851
takes_args = ['name_pattern*']
1853
Option('old-default-rules',
1854
help='Out the ignore rules bzr < 0.9 always used.')
1440
# TODO: Complain if the filename is absolute
1441
takes_args = ['name_pattern']
1857
def run(self, name_pattern_list=None, old_default_rules=None):
1443
def run(self, name_pattern):
1858
1444
from bzrlib.atomicfile import AtomicFile
1859
if old_default_rules is not None:
1860
# dump the rules and exit
1861
for pattern in ignores.OLD_DEFAULTS:
1864
if not name_pattern_list:
1865
raise errors.BzrCommandError("ignore requires at least one "
1866
"NAME_PATTERN or --old-default-rules")
1867
name_pattern_list = [globbing.normalize_pattern(p)
1868
for p in name_pattern_list]
1869
for name_pattern in name_pattern_list:
1870
if (name_pattern[0] == '/' or
1871
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1872
raise errors.BzrCommandError(
1873
"NAME_PATTERN should not be an absolute path")
1874
1447
tree, relpath = WorkingTree.open_containing(u'.')
1875
1448
ifn = tree.abspath('.bzrignore')
1876
1450
if os.path.exists(ifn):
1877
1451
f = open(ifn, 'rt')
1966
1534
tgz .tar.gz, .tgz
1969
takes_args = ['dest', 'branch?']
1537
takes_args = ['dest']
1970
1538
takes_options = ['revision', 'format', 'root']
1971
def run(self, dest, branch=None, revision=None, format=None, root=None):
1539
def run(self, dest, revision=None, format=None, root=None):
1972
1541
from bzrlib.export import export
1975
tree = WorkingTree.open_containing(u'.')[0]
1978
b = Branch.open(branch)
1542
tree = WorkingTree.open_containing(u'.')[0]
1980
1544
if revision is None:
1981
1545
# should be tree.last_revision FIXME
1982
1546
rev_id = b.last_revision()
1984
1548
if len(revision) != 1:
1985
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1549
raise BzrError('bzr export --revision takes exactly 1 argument')
1986
1550
rev_id = revision[0].in_history(b).rev_id
1987
1551
t = b.repository.revision_tree(rev_id)
1989
1553
export(t, dest, format, root)
1990
1554
except errors.NoSuchExportFormat, e:
1991
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1555
raise BzrCommandError('Unsupported export format: %s' % e.format)
1994
1558
class cmd_cat(Command):
1995
"""Write the contents of a file as of a given revision to standard output.
1997
If no revision is nominated, the last revision is used.
1999
Note: Take care to redirect standard output when using this command on a
2004
takes_options = ['revision', 'name-from-revision']
1559
"""Write a file's text from a previous revision."""
1561
takes_options = ['revision']
2005
1562
takes_args = ['filename']
2006
encoding_type = 'exact'
2008
1564
@display_command
2009
def run(self, filename, revision=None, name_from_revision=False):
1565
def run(self, filename, revision=None):
2010
1566
if revision is not None and len(revision) != 1:
2011
raise errors.BzrCommandError("bzr cat --revision takes exactly"
1567
raise BzrCommandError("bzr cat --revision takes exactly one number")
2016
tree, b, relpath = \
2017
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2018
except errors.NotBranchError:
1570
tree, relpath = WorkingTree.open_containing(filename)
1572
except NotBranchError:
2021
if revision is not None and revision[0].get_branch() is not None:
2022
b = Branch.open(revision[0].get_branch())
2023
1575
if tree is None:
2024
tree = b.basis_tree()
1576
b, relpath = Branch.open_containing(filename)
2025
1577
if revision is None:
2026
1578
revision_id = b.last_revision()
2028
1580
revision_id = revision[0].in_history(b).rev_id
2030
cur_file_id = tree.path2id(relpath)
2031
rev_tree = b.repository.revision_tree(revision_id)
2032
old_file_id = rev_tree.path2id(relpath)
2034
if name_from_revision:
2035
if old_file_id is None:
2036
raise errors.BzrCommandError("%r is not present in revision %s"
2037
% (filename, revision_id))
2039
rev_tree.print_file(old_file_id)
2040
elif cur_file_id is not None:
2041
rev_tree.print_file(cur_file_id)
2042
elif old_file_id is not None:
2043
rev_tree.print_file(old_file_id)
2045
raise errors.BzrCommandError("%r is not present in revision %s" %
2046
(filename, revision_id))
1581
b.print_file(relpath, revision_id)
2049
1584
class cmd_local_time_offset(Command):
2117
1632
aliases = ['ci', 'checkin']
2119
def _get_bug_fix_properties(self, fixes, branch):
2121
# Configure the properties for bug fixing attributes.
2122
for fixed_bug in fixes:
2123
tokens = fixed_bug.split(':')
2124
if len(tokens) != 2:
2125
raise errors.BzrCommandError(
2126
"Invalid bug %s. Must be in the form of 'tag:id'. "
2127
"Commit refused." % fixed_bug)
2128
tag, bug_id = tokens
2130
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2131
except errors.UnknownBugTrackerAbbreviation:
2132
raise errors.BzrCommandError(
2133
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2134
except errors.MalformedBugIdentifier:
2135
raise errors.BzrCommandError(
2136
"Invalid bug identifier for %s. Commit refused."
2138
properties.append('%s fixed' % bug_url)
2139
return '\n'.join(properties)
2141
1634
def run(self, message=None, file=None, verbose=True, selected_list=None,
2142
unchanged=False, strict=False, local=False, fixes=None):
1635
unchanged=False, strict=False, local=False):
2143
1636
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2144
1637
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2145
1638
StrictCommitFailed)
2146
1639
from bzrlib.msgeditor import edit_commit_message, \
2147
1640
make_commit_message_template
1641
from tempfile import TemporaryFile
2149
1643
# TODO: Need a blackbox test for invoking the external editor; may be
2150
1644
# slightly problematic to run this cross-platform.
2152
1646
# TODO: do more checks that the commit will succeed before
2153
1647
# spending the user's valuable time typing a commit message.
1649
# TODO: if the commit *does* happen to fail, then save the commit
1650
# message to a temporary file where it can be recovered
2157
1651
tree, selected_list = tree_files(selected_list)
2158
1652
if selected_list == ['']:
2159
1653
# workaround - commit of root of tree should be exactly the same
2161
1655
# selected-file merge commit is not done yet
2162
1656
selected_list = []
2164
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2166
properties['bugs'] = bug_property
2168
1658
if local and not tree.branch.get_bound_location():
2169
1659
raise errors.LocalRequiresBoundBranch()
2171
def get_message(commit_obj):
2172
"""Callback to get commit message"""
2173
my_message = message
2174
if my_message is None and not file:
2175
template = make_commit_message_template(tree, selected_list)
2176
my_message = edit_commit_message(template)
2177
if my_message is None:
2178
raise errors.BzrCommandError("please specify a commit"
2179
" message with either --message or --file")
2180
elif my_message and file:
2181
raise errors.BzrCommandError(
2182
"please specify either --message or --file")
2184
my_message = codecs.open(file, 'rt',
2185
bzrlib.user_encoding).read()
2186
if my_message == "":
2187
raise errors.BzrCommandError("empty commit message specified")
1660
if message is None and not file:
1661
template = make_commit_message_template(tree, selected_list)
1662
message = edit_commit_message(template)
1664
raise BzrCommandError("please specify a commit message"
1665
" with either --message or --file")
1666
elif message and file:
1667
raise BzrCommandError("please specify either --message or --file")
1670
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1673
raise BzrCommandError("empty commit message specified")
2191
1676
reporter = ReportCommitToLog()
2193
1678
reporter = NullCommitReporter()
2196
tree.commit(message_callback=get_message,
2197
specific_files=selected_list,
1681
tree.commit(message, specific_files=selected_list,
2198
1682
allow_pointless=unchanged, strict=strict, local=local,
2199
reporter=reporter, revprops=properties)
2200
1684
except PointlessCommit:
2201
1685
# FIXME: This should really happen before the file is read in;
2202
1686
# perhaps prepare the commit; get the message; then actually commit
2203
raise errors.BzrCommandError("no changes to commit."
2204
" use --unchanged to commit anyhow")
1687
raise BzrCommandError("no changes to commit",
1688
["use --unchanged to commit anyhow"])
2205
1689
except ConflictsInTree:
2206
raise errors.BzrCommandError('Conflicts detected in working '
2207
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1690
raise BzrCommandError("Conflicts detected in working tree. "
1691
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2209
1692
except StrictCommitFailed:
2210
raise errors.BzrCommandError("Commit refused because there are"
2211
" unknown files in the working tree.")
1693
raise BzrCommandError("Commit refused because there are unknown "
1694
"files in the working tree.")
2212
1695
except errors.BoundBranchOutOfDate, e:
2213
raise errors.BzrCommandError(str(e) + "\n"
2214
'To commit to master branch, run update and then commit.\n'
2215
'You can also pass --local to commit to continue working '
1696
raise BzrCommandError(str(e)
1697
+ ' Either unbind, update, or'
1698
' pass --local to commit.')
2219
1701
class cmd_check(Command):
2244
1743
this command. When the default format has changed you may also be warned
2245
1744
during other operations to upgrade.
2248
_see_also = ['check']
2249
1746
takes_args = ['url?']
2250
1747
takes_options = [
2251
RegistryOption('format',
2252
help='Upgrade to a specific format. See "bzr help'
2253
' formats" for details',
2254
registry=bzrdir.format_registry,
2255
converter=bzrdir.format_registry.make_bzrdir,
2256
value_switches=True, title='Branch format'),
1749
help='Upgrade to a specific format. Current formats'
1750
' are: default, knit, metaweave and weave.'
1751
' Default is knit; metaweave and weave are'
1753
type=get_format_type),
2259
1757
def run(self, url='.', format=None):
2260
1758
from bzrlib.upgrade import upgrade
2261
1759
if format is None:
2262
format = bzrdir.format_registry.make_bzrdir('default')
1760
format = get_format_type('default')
2263
1761
upgrade(url, format)
2266
1764
class cmd_whoami(Command):
2267
"""Show or set bzr user id.
2271
bzr whoami 'Frank Chu <fchu@example.com>'
2273
takes_options = [ Option('email',
2274
help='display email address only'),
2276
help='set identity for the current branch instead of '
2279
takes_args = ['name?']
2280
encoding_type = 'replace'
1765
"""Show bzr user id."""
1766
takes_options = ['email']
2282
1768
@display_command
2283
def run(self, email=False, branch=False, name=None):
2285
# use branch if we're inside one; otherwise global config
2287
c = Branch.open_containing('.')[0].get_config()
2288
except errors.NotBranchError:
2289
c = config.GlobalConfig()
2291
self.outf.write(c.user_email() + '\n')
2293
self.outf.write(c.username() + '\n')
2296
# display a warning if an email address isn't included in the given name.
1769
def run(self, email=False):
2298
config.extract_email_address(name)
2299
except errors.NoEmailInUsername, e:
2300
warning('"%s" does not seem to contain an email address. '
2301
'This is allowed, but not recommended.', name)
1771
b = WorkingTree.open_containing(u'.')[0].branch
1772
config = bzrlib.config.BranchConfig(b)
1773
except NotBranchError:
1774
config = bzrlib.config.GlobalConfig()
2303
# use global config unless --branch given
2305
c = Branch.open_containing('.')[0].get_config()
1777
print config.user_email()
2307
c = config.GlobalConfig()
2308
c.set_user_option('email', name)
1779
print config.username()
2311
1782
class cmd_nick(Command):
2327
1796
@display_command
2328
1797
def printme(self, branch):
2332
1801
class cmd_selftest(Command):
2333
1802
"""Run internal test suite.
2335
If arguments are given, they are regular expressions that say which tests
2336
should run. Tests matching any expression are run, and other tests are
2339
Alternatively if --first is given, matching tests are run first and then
2340
all other tests are run. This is useful if you have been working in a
2341
particular area, but want to make sure nothing else was broken.
2343
If --exclude is given, tests that match that regular expression are
2344
excluded, regardless of whether they match --first or not.
2346
To help catch accidential dependencies between tests, the --randomize
2347
option is useful. In most cases, the argument used is the word 'now'.
2348
Note that the seed used for the random number generator is displayed
2349
when this option is used. The seed can be explicitly passed as the
2350
argument to this option if required. This enables reproduction of the
2351
actual ordering used if and when an order sensitive problem is encountered.
2353
If --list-only is given, the tests that would be run are listed. This is
2354
useful when combined with --first, --exclude and/or --randomize to
2355
understand their impact. The test harness reports "Listed nn tests in ..."
2356
instead of "Ran nn tests in ..." when list mode is enabled.
1804
This creates temporary test directories in the working directory,
1805
but not existing data is affected. These directories are deleted
1806
if the tests pass, or left behind to help in debugging if they
1807
fail and --keep-output is specified.
1809
If arguments are given, they are regular expressions that say
1810
which tests should run.
2358
1812
If the global option '--no-plugins' is given, plugins are not loaded
2359
1813
before running the selftests. This has two effects: features provided or
2360
1814
modified by plugins will not be tested, and tests provided by plugins will
2364
1818
bzr selftest ignore
2365
run only tests relating to 'ignore'
2366
1819
bzr --no-plugins selftest -v
2367
disable plugins and list tests as they're run
1821
# TODO: --list should give a list of all available tests
2369
For each test, that needs actual disk access, bzr create their own
2370
subdirectory in the temporary testing directory (testXXXX.tmp).
2371
By default the name of such subdirectory is based on the name of the test.
2372
If option '--numbered-dirs' is given, bzr will use sequent numbers
2373
of running tests to create such subdirectories. This is default behavior
2374
on Windows because of path length limitation.
2376
1823
# NB: this is used from the class without creating an instance, which is
2377
1824
# why it does not have a self parameter.
2378
1825
def get_transport_type(typestring):
2388
1835
return FakeNFSServer
2389
1836
msg = "No known transport type %s. Supported types are: sftp\n" %\
2391
raise errors.BzrCommandError(msg)
1838
raise BzrCommandError(msg)
2394
1841
takes_args = ['testspecs*']
2395
1842
takes_options = ['verbose',
2397
help='stop when one test fails',
2400
Option('keep-output',
1843
Option('one', help='stop when one test fails'),
1844
Option('keep-output',
2401
1845
help='keep output directories when tests fail'),
2403
1847
help='Use a different transport by default '
2404
1848
'throughout the test suite.',
2405
1849
type=get_transport_type),
2406
Option('benchmark', help='run the bzr benchmarks.'),
1850
Option('benchmark', help='run the bzr bencharks.'),
2407
1851
Option('lsprof-timed',
2408
1852
help='generate lsprof output for benchmarked'
2409
1853
' sections of code.'),
2410
Option('cache-dir', type=str,
2411
help='a directory to cache intermediate'
2412
' benchmark steps'),
2413
Option('clean-output',
2414
help='clean temporary tests directories'
2415
' without running tests'),
2417
help='run all tests, but run specified tests first',
2420
Option('numbered-dirs',
2421
help='use numbered dirs for TestCaseInTempDir'),
2423
help='list the tests instead of running them'),
2424
Option('randomize', type=str, argname="SEED",
2425
help='randomize the order of tests using the given'
2426
' seed or "now" for the current time'),
2427
Option('exclude', type=str, argname="PATTERN",
2429
help='exclude tests that match this regular'
2432
encoding_type = 'replace'
2434
1856
def run(self, testspecs_list=None, verbose=None, one=False,
2435
1857
keep_output=False, transport=None, benchmark=None,
2436
lsprof_timed=None, cache_dir=None, clean_output=False,
2437
first=False, numbered_dirs=None, list_only=False,
2438
randomize=None, exclude=None):
2439
1859
import bzrlib.ui
2440
1860
from bzrlib.tests import selftest
2441
1861
import bzrlib.benchmarks as benchmarks
2442
from bzrlib.benchmarks import tree_creator
2445
from bzrlib.tests import clean_selftest_output
2446
clean_selftest_output()
2449
warning("notice: selftest --keep-output "
2450
"is no longer supported; "
2451
"test output is always removed")
2453
if numbered_dirs is None and sys.platform == 'win32':
2454
numbered_dirs = True
2456
if cache_dir is not None:
2457
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2458
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1862
# we don't want progress meters from the tests to go to the
1863
# real output; and we don't want log messages cluttering up
1865
save_ui = bzrlib.ui.ui_factory
1866
print '%10s: %s' % ('bzr', bzrlib.osutils.realpath(sys.argv[0]))
2459
1867
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2461
if testspecs_list is not None:
2462
pattern = '|'.join(testspecs_list)
2466
test_suite_factory = benchmarks.test_suite
2469
# TODO: should possibly lock the history file...
2470
benchfile = open(".perf_history", "at", buffering=1)
2472
test_suite_factory = None
1869
bzrlib.trace.info('running tests...')
1871
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1872
if testspecs_list is not None:
1873
pattern = '|'.join(testspecs_list)
1877
test_suite_factory = benchmarks.test_suite
1881
test_suite_factory = None
2477
1884
result = selftest(verbose=verbose,
2478
1885
pattern=pattern,
2479
1886
stop_on_failure=one,
1887
keep_output=keep_output,
2480
1888
transport=transport,
2481
1889
test_suite_factory=test_suite_factory,
2482
lsprof_timed=lsprof_timed,
2483
bench_history=benchfile,
2484
matching_tests_first=first,
2485
numbered_dirs=numbered_dirs,
2486
list_only=list_only,
2487
random_seed=randomize,
2488
exclude_pattern=exclude
1890
lsprof_timed=lsprof_timed)
1892
bzrlib.trace.info('tests passed')
1894
bzrlib.trace.info('tests failed')
1895
return int(not result)
2491
if benchfile is not None:
2494
info('tests passed')
2496
info('tests failed')
2497
return int(not result)
1897
bzrlib.ui.ui_factory = save_ui
1900
def _get_bzr_branch():
1901
"""If bzr is run from a branch, return Branch or None"""
1902
import bzrlib.errors
1903
from bzrlib.branch import Branch
1904
from bzrlib.osutils import abspath
1905
from os.path import dirname
1908
branch = Branch.open(dirname(abspath(dirname(__file__))))
1910
except bzrlib.errors.BzrError:
1915
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1916
# is bzrlib itself in a branch?
1917
branch = _get_bzr_branch()
1919
rh = branch.revision_history()
1921
print " bzr checkout, revision %d" % (revno,)
1922
print " nick: %s" % (branch.nick,)
1924
print " revid: %s" % (rh[-1],)
1925
print "Using python interpreter:", sys.executable
1927
print "Using python standard library:", os.path.dirname(site.__file__)
1928
print "Using bzrlib:",
1929
if len(bzrlib.__path__) > 1:
1930
# print repr, which is a good enough way of making it clear it's
1931
# more than one element (eg ['/foo/bar', '/foo/bzr'])
1932
print repr(bzrlib.__path__)
1934
print bzrlib.__path__[0]
1937
print bzrlib.__copyright__
1938
print "http://bazaar-vcs.org/"
1940
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1941
print "you may use, modify and redistribute it under the terms of the GNU"
1942
print "General Public License version 2 or later."
2500
1945
class cmd_version(Command):
2501
1946
"""Show version of bzr."""
2503
1947
@display_command
2505
from bzrlib.version import show_version
2509
1951
class cmd_rocks(Command):
2510
1952
"""Statement of optimism."""
2514
1954
@display_command
2516
print "It sure does!"
1956
print "it sure does!"
2519
1959
class cmd_find_merge_base(Command):
2520
"""Find and print a base revision for merging two branches."""
1960
"""Find and print a base revision for merging two branches.
2521
1962
# TODO: Options to specify revisions on either side, as if
2522
1963
# merging only part of the history.
2523
1964
takes_args = ['branch', 'other']
2526
1967
@display_command
2527
1968
def run(self, branch, other):
2528
from bzrlib.revision import ensure_null, MultipleRevisionSources
1969
from bzrlib.revision import common_ancestor, MultipleRevisionSources
2530
1971
branch1 = Branch.open_containing(branch)[0]
2531
1972
branch2 = Branch.open_containing(other)[0]
2533
last1 = ensure_null(branch1.last_revision())
2534
last2 = ensure_null(branch2.last_revision())
2536
graph = branch1.repository.get_graph(branch2.repository)
2537
base_rev_id = graph.find_unique_lca(last1, last2)
1974
history_1 = branch1.revision_history()
1975
history_2 = branch2.revision_history()
1977
last1 = branch1.last_revision()
1978
last2 = branch2.last_revision()
1980
source = MultipleRevisionSources(branch1.repository,
1983
base_rev_id = common_ancestor(last1, last2, source)
2539
1985
print 'merge base is revision %s' % base_rev_id
1989
if base_revno is None:
1990
raise bzrlib.errors.UnrelatedBranches()
1992
print ' r%-6d in %s' % (base_revno, branch)
1994
other_revno = branch2.revision_id_to_revno(base_revid)
1996
print ' r%-6d in %s' % (other_revno, other)
2542
2000
class cmd_merge(Command):
2543
2001
"""Perform a three-way merge.
2545
The branch is the branch you will merge from. By default, it will merge
2546
the latest revision. If you specify a revision, that revision will be
2547
merged. If you specify two revisions, the first will be used as a BASE,
2548
and the second one as OTHER. Revision numbers are always relative to the
2003
The branch is the branch you will merge from. By default, it will
2004
merge the latest revision. If you specify a revision, that
2005
revision will be merged. If you specify two revisions, the first
2006
will be used as a BASE, and the second one as OTHER. Revision
2007
numbers are always relative to the specified branch.
2551
2009
By default, bzr will try to merge in all new work from the other
2552
2010
branch, automatically determining an appropriate base. If this
2562
2020
If there is no default branch set, the first merge will set it. After
2563
2021
that, you can omit the branch to use the default. To change the
2564
default, use --remember. The value will only be saved if the remote
2565
location can be accessed.
2567
The results of the merge are placed into the destination working
2568
directory, where they can be reviewed (with bzr diff), tested, and then
2569
committed to record the result of the merge.
2022
default, use --remember.
2573
To merge the latest revision from bzr.dev:
2574
bzr merge ../bzr.dev
2026
To merge the latest revision from bzr.dev
2027
bzr merge ../bzr.dev
2576
To merge changes up to and including revision 82 from bzr.dev:
2577
bzr merge -r 82 ../bzr.dev
2029
To merge changes up to and including revision 82 from bzr.dev
2030
bzr merge -r 82 ../bzr.dev
2579
2032
To merge the changes introduced by 82, without previous changes:
2580
bzr merge -r 81..82 ../bzr.dev
2033
bzr merge -r 81..82 ../bzr.dev
2582
2035
merge refuses to run if there are any uncommitted changes, unless
2583
2036
--force is given.
2038
The following merge types are available:
2586
_see_also = ['update', 'remerge', 'status-flags']
2587
2040
takes_args = ['branch?']
2588
2041
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2589
Option('show-base', help="Show base revision text in "
2591
Option('uncommitted', help='Apply uncommitted changes'
2592
' from a working copy, instead of branch changes'),
2593
Option('pull', help='If the destination is already'
2594
' completely merged into the source, pull from the'
2595
' source rather than merging. When this happens,'
2596
' you do not need to commit the result.'),
2598
help='Branch to merge into, '
2599
'rather than the one containing the working directory',
2042
Option('show-base', help="Show base revision text in "
2046
from merge import merge_type_help
2047
from inspect import getdoc
2048
return getdoc(self) + '\n' + merge_type_help()
2605
2050
def run(self, branch=None, revision=None, force=False, merge_type=None,
2606
show_base=False, reprocess=False, remember=False,
2607
uncommitted=False, pull=False,
2610
from bzrlib.tag import _merge_tags_if_possible
2611
other_revision_id = None
2051
show_base=False, reprocess=False, remember=False):
2612
2052
if merge_type is None:
2613
merge_type = _mod_merge.Merge3Merger
2615
if directory is None: directory = u'.'
2616
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2617
# inventory. Because merge is a mutating operation, it really
2618
# should be a lock_write() for the whole cmd_merge operation.
2619
# However, cmd_merge open's its own tree in _merge_helper, which
2620
# means if we lock here, the later lock_write() will always block.
2621
# Either the merge helper code should be updated to take a tree,
2622
# (What about tree.merge_from_branch?)
2623
tree = WorkingTree.open_containing(directory)[0]
2624
change_reporter = delta._ChangeReporter(
2625
unversioned_filter=tree.is_ignored)
2627
if branch is not None:
2629
mergeable = bundle.read_mergeable_from_url(
2631
except errors.NotABundle:
2632
pass # Continue on considering this url a Branch
2634
if revision is not None:
2635
raise errors.BzrCommandError(
2636
'Cannot use -r with merge directives or bundles')
2637
other_revision_id = mergeable.install_revisions(
2638
tree.branch.repository)
2639
revision = [RevisionSpec.from_string(
2640
'revid:' + other_revision_id)]
2642
if revision is None \
2643
or len(revision) < 1 or revision[0].needs_branch():
2644
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2053
merge_type = Merge3Merger
2055
tree = WorkingTree.open_containing(u'.')[0]
2058
if branch is not None:
2059
reader = BundleReader(file(branch, 'rb'))
2063
if e.errno not in (errno.ENOENT, errno.EISDIR):
2068
if reader is not None:
2069
conflicts = merge_bundle(reader, tree, not force, merge_type,
2070
reprocess, show_base)
2076
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2646
2078
if revision is None or len(revision) < 1:
2649
other = [branch, None]
2652
other = [branch, -1]
2080
other = [branch, -1]
2653
2081
other_branch, path = Branch.open_containing(branch)
2656
raise errors.BzrCommandError('Cannot use --uncommitted and'
2657
' --revision at the same time.')
2658
branch = revision[0].get_branch() or branch
2659
2083
if len(revision) == 1:
2660
2084
base = [None, None]
2661
if other_revision_id is not None:
2666
other_branch, path = Branch.open_containing(branch)
2667
revno = revision[0].in_history(other_branch).revno
2668
other = [branch, revno]
2085
other_branch, path = Branch.open_containing(branch)
2086
revno = revision[0].in_history(other_branch).revno
2087
other = [branch, revno]
2670
2089
assert len(revision) == 2
2671
2090
if None in revision:
2672
raise errors.BzrCommandError(
2673
"Merge doesn't permit empty revision specifier.")
2674
base_branch, path = Branch.open_containing(branch)
2675
branch1 = revision[1].get_branch() or branch
2676
other_branch, path1 = Branch.open_containing(branch1)
2677
if revision[0].get_branch() is not None:
2678
# then path was obtained from it, and is None.
2681
base = [branch, revision[0].in_history(base_branch).revno]
2682
other = [branch1, revision[1].in_history(other_branch).revno]
2684
if ((tree.branch.get_parent() is None or remember) and
2685
other_branch is not None):
2091
raise BzrCommandError(
2092
"Merge doesn't permit that revision specifier.")
2093
other_branch, path = Branch.open_containing(branch)
2095
base = [branch, revision[0].in_history(other_branch).revno]
2096
other = [branch, revision[1].in_history(other_branch).revno]
2098
if tree.branch.get_parent() is None or remember:
2686
2099
tree.branch.set_parent(other_branch.base)
2688
# pull tags now... it's a bit inconsistent to do it ahead of copying
2689
# the history but that's done inside the merge code
2690
if other_branch is not None:
2691
_merge_tags_if_possible(other_branch, tree.branch)
2694
2102
interesting_files = [path]
2696
2104
interesting_files = None
2697
pb = ui.ui_factory.nested_progress_bar()
2105
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2700
conflict_count = _merge_helper(
2701
other, base, other_rev_id=other_revision_id,
2702
check_clean=(not force),
2703
merge_type=merge_type,
2704
reprocess=reprocess,
2705
show_base=show_base,
2708
pb=pb, file_list=interesting_files,
2709
change_reporter=change_reporter)
2108
conflict_count = merge(other, base, check_clean=(not force),
2109
merge_type=merge_type,
2110
reprocess=reprocess,
2111
show_base=show_base,
2112
pb=pb, file_list=interesting_files)
2712
2115
if conflict_count != 0:
2716
except errors.AmbiguousBase, e:
2119
except bzrlib.errors.AmbiguousBase, e:
2717
2120
m = ("sorry, bzr can't determine the right merge base yet\n"
2718
2121
"candidates are:\n "
2719
2122
+ "\n ".join(e.bases)
2759
2161
$ bzr remerge --merge-type weave --reprocess foobar
2760
2162
Re-do the merge of "foobar", using the weave merge algorithm, with
2761
2163
additional processing to reduce the size of conflict regions.
2165
The following merge types are available:"""
2763
2166
takes_args = ['file*']
2764
2167
takes_options = ['merge-type', 'reprocess',
2765
2168
Option('show-base', help="Show base revision text in "
2172
from merge import merge_type_help
2173
from inspect import getdoc
2174
return getdoc(self) + '\n' + merge_type_help()
2768
2176
def run(self, file_list=None, merge_type=None, show_base=False,
2769
2177
reprocess=False):
2178
from bzrlib.merge import merge_inner, transform_tree
2770
2179
if merge_type is None:
2771
merge_type = _mod_merge.Merge3Merger
2180
merge_type = Merge3Merger
2772
2181
tree, file_list = tree_files(file_list)
2773
2182
tree.lock_write()
2775
parents = tree.get_parent_ids()
2776
if len(parents) != 2:
2777
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2778
" merges. Not cherrypicking or"
2184
pending_merges = tree.pending_merges()
2185
if len(pending_merges) != 1:
2186
raise BzrCommandError("Sorry, remerge only works after normal"
2187
+ " merges. Not cherrypicking or"
2780
2189
repository = tree.branch.repository
2781
graph = repository.get_graph()
2782
base_revision = graph.find_unique_lca(parents[0], parents[1])
2190
base_revision = common_ancestor(tree.branch.last_revision(),
2191
pending_merges[0], repository)
2783
2192
base_tree = repository.revision_tree(base_revision)
2784
other_tree = repository.revision_tree(parents[1])
2193
other_tree = repository.revision_tree(pending_merges[0])
2785
2194
interesting_ids = None
2787
conflicts = tree.conflicts()
2788
2195
if file_list is not None:
2789
2196
interesting_ids = set()
2790
2197
for filename in file_list:
2791
2198
file_id = tree.path2id(filename)
2792
2199
if file_id is None:
2793
raise errors.NotVersionedError(filename)
2200
raise NotVersionedError(filename)
2794
2201
interesting_ids.add(file_id)
2795
2202
if tree.kind(file_id) != "directory":
2798
2205
for name, ie in tree.inventory.iter_entries(file_id):
2799
2206
interesting_ids.add(ie.file_id)
2800
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2207
transform_tree(tree, tree.basis_tree(), interesting_ids)
2208
if file_list is None:
2209
restore_files = list(tree.iter_conflicts())
2802
# Remerge only supports resolving contents conflicts
2803
allowed_conflicts = ('text conflict', 'contents conflict')
2804
restore_files = [c.path for c in conflicts
2805
if c.typestring in allowed_conflicts]
2806
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2807
tree.set_conflicts(ConflictList(new_conflicts))
2808
if file_list is not None:
2809
2211
restore_files = file_list
2810
2212
for filename in restore_files:
2812
2214
restore(tree.abspath(filename))
2813
except errors.NotConflicted:
2215
except NotConflicted:
2815
conflicts = _mod_merge.merge_inner(
2816
tree.branch, other_tree, base_tree,
2818
interesting_ids=interesting_ids,
2819
other_rev_id=parents[1],
2820
merge_type=merge_type,
2821
show_base=show_base,
2822
reprocess=reprocess)
2217
conflicts = merge_inner(tree.branch, other_tree, base_tree,
2219
interesting_ids = interesting_ids,
2220
other_rev_id=pending_merges[0],
2221
merge_type=merge_type,
2222
show_base=show_base,
2223
reprocess=reprocess)
2825
2226
if conflicts > 0:
2937
2318
class cmd_missing(Command):
2938
2319
"""Show unmerged/unpulled revisions between two branches.
2940
OTHER_BRANCH may be local or remote.
2943
_see_also = ['merge', 'pull']
2321
OTHER_BRANCH may be local or remote."""
2944
2322
takes_args = ['other_branch?']
2945
2323
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2946
2324
Option('mine-only',
2947
2325
'Display changes in the local branch only'),
2948
Option('this' , 'same as --mine-only'),
2949
2326
Option('theirs-only',
2950
'Display changes in the remote branch only'),
2951
Option('other', 'same as --theirs-only'),
2327
'Display changes in the remote branch only'),
2956
encoding_type = 'replace'
2959
2336
def run(self, other_branch=None, reverse=False, mine_only=False,
2960
2337
theirs_only=False, log_format=None, long=False, short=False, line=False,
2961
show_ids=False, verbose=False, this=False, other=False):
2962
from bzrlib.missing import find_unmerged, iter_log_revisions
2338
show_ids=False, verbose=False):
2339
from bzrlib.missing import find_unmerged, iter_log_data
2963
2340
from bzrlib.log import log_formatter
2970
local_branch = Branch.open_containing(u".")[0]
2341
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2971
2342
parent = local_branch.get_parent()
2972
2343
if other_branch is None:
2973
2344
other_branch = parent
2974
2345
if other_branch is None:
2975
raise errors.BzrCommandError("No peer location known or specified.")
2976
display_url = urlutils.unescape_for_display(parent,
2978
print "Using last location: " + display_url
2980
remote_branch = Branch.open(other_branch)
2346
raise BzrCommandError("No missing location known or specified.")
2347
print "Using last location: " + local_branch.get_parent()
2348
remote_branch = bzrlib.branch.Branch.open(other_branch)
2981
2349
if remote_branch.base == local_branch.base:
2982
2350
remote_branch = local_branch
2983
2351
local_branch.lock_read()
3158
2513
if to_revid is None:
3159
2514
to_revno = b.revno()
3160
2515
if from_revno is None or to_revno is None:
3161
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2516
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3162
2517
for revno in range(from_revno, to_revno + 1):
3163
2518
b.repository.sign_revision(b.get_rev_id(revno),
3166
raise errors.BzrCommandError('Please supply either one revision, or a range.')
2521
raise BzrCommandError('Please supply either one revision, or a range.')
3169
2524
class cmd_bind(Command):
3170
"""Convert the current branch into a checkout of the supplied branch.
2525
"""Bind the current branch to a master branch.
3172
Once converted into a checkout, commits must succeed on the master branch
3173
before they will be applied to the local branch.
2527
After binding, commits must succeed on the master branch
2528
before they are executed on the local one.
3176
_see_also = ['checkouts', 'unbind']
3177
takes_args = ['location?']
2531
takes_args = ['location']
3178
2532
takes_options = []
3180
2534
def run(self, location=None):
3181
2535
b, relpath = Branch.open_containing(u'.')
3182
if location is None:
3184
location = b.get_old_bound_location()
3185
except errors.UpgradeRequired:
3186
raise errors.BzrCommandError('No location supplied. '
3187
'This format does not remember old locations.')
3189
if location is None:
3190
raise errors.BzrCommandError('No location supplied and no '
3191
'previous location known')
3192
2536
b_other = Branch.open(location)
3194
2538
b.bind(b_other)
3195
except errors.DivergedBranches:
3196
raise errors.BzrCommandError('These branches have diverged.'
3197
' Try merging, and then bind again.')
2539
except DivergedBranches:
2540
raise BzrCommandError('These branches have diverged.'
2541
' Try merging, and then bind again.')
3200
2544
class cmd_unbind(Command):
3201
"""Convert the current checkout into a regular branch.
2545
"""Unbind the current branch from its master branch.
3203
After unbinding, the local branch is considered independent and subsequent
3204
commits will be local only.
2547
After unbinding, the local branch is considered independent.
2548
All subsequent commits will be local.
3207
_see_also = ['checkouts', 'bind']
3208
2551
takes_args = []
3209
2552
takes_options = []
3212
2555
b, relpath = Branch.open_containing(u'.')
3213
2556
if not b.unbind():
3214
raise errors.BzrCommandError('Local branch is not bound')
3217
class cmd_uncommit(Command):
2557
raise BzrCommandError('Local branch is not bound')
2560
class cmd_uncommit(bzrlib.commands.Command):
3218
2561
"""Remove the last committed revision.
3220
2563
--verbose will print out what is being removed.
3323
class cmd_wait_until_signalled(Command):
3324
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3326
This just prints a line to signal when it is ready, then blocks on stdin.
3332
sys.stdout.write("running\n")
3334
sys.stdin.readline()
3337
class cmd_serve(Command):
3338
"""Run the bzr server."""
3340
aliases = ['server']
3344
help='serve on stdin/out for use from inetd or sshd'),
3346
help='listen for connections on nominated port of the form '
3347
'[hostname:]portnumber. Passing 0 as the port number will '
3348
'result in a dynamically allocated port. Default port is '
3352
help='serve contents of directory',
3354
Option('allow-writes',
3355
help='By default the server is a readonly server. Supplying '
3356
'--allow-writes enables write access to the contents of '
3357
'the served directory and below. '
3361
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3362
from bzrlib.smart import medium, server
3363
from bzrlib.transport import get_transport
3364
from bzrlib.transport.chroot import ChrootServer
3365
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3366
if directory is None:
3367
directory = os.getcwd()
3368
url = urlutils.local_path_to_url(directory)
3369
if not allow_writes:
3370
url = 'readonly+' + url
3371
chroot_server = ChrootServer(get_transport(url))
3372
chroot_server.setUp()
3373
t = get_transport(chroot_server.get_url())
3375
smart_server = medium.SmartServerPipeStreamMedium(
3376
sys.stdin, sys.stdout, t)
3378
host = BZR_DEFAULT_INTERFACE
3380
port = BZR_DEFAULT_PORT
3383
host, port = port.split(':')
3385
smart_server = server.SmartTCPServer(t, host=host, port=port)
3386
print 'listening on port: ', smart_server.port
3388
# for the duration of this server, no UI output is permitted.
3389
# note that this may cause problems with blackbox tests. This should
3390
# be changed with care though, as we dont want to use bandwidth sending
3391
# progress over stderr to smart server clients!
3392
old_factory = ui.ui_factory
3394
ui.ui_factory = ui.SilentUIFactory()
3395
smart_server.serve()
3397
ui.ui_factory = old_factory
3400
class cmd_join(Command):
3401
"""Combine a subtree into its containing tree.
3403
This command is for experimental use only. It requires the target tree
3404
to be in dirstate-with-subtree format, which cannot be converted into
3407
The TREE argument should be an independent tree, inside another tree, but
3408
not part of it. (Such trees can be produced by "bzr split", but also by
3409
running "bzr branch" with the target inside a tree.)
3411
The result is a combined tree, with the subtree no longer an independant
3412
part. This is marked as a merge of the subtree into the containing tree,
3413
and all history is preserved.
3415
If --reference is specified, the subtree retains its independence. It can
3416
be branched by itself, and can be part of multiple projects at the same
3417
time. But operations performed in the containing tree, such as commit
3418
and merge, will recurse into the subtree.
3421
_see_also = ['split']
3422
takes_args = ['tree']
3423
takes_options = [Option('reference', 'join by reference')]
3426
def run(self, tree, reference=False):
3427
sub_tree = WorkingTree.open(tree)
3428
parent_dir = osutils.dirname(sub_tree.basedir)
3429
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3430
repo = containing_tree.branch.repository
3431
if not repo.supports_rich_root():
3432
raise errors.BzrCommandError(
3433
"Can't join trees because %s doesn't support rich root data.\n"
3434
"You can use bzr upgrade on the repository."
3438
containing_tree.add_reference(sub_tree)
3439
except errors.BadReferenceTarget, e:
3440
# XXX: Would be better to just raise a nicely printable
3441
# exception from the real origin. Also below. mbp 20070306
3442
raise errors.BzrCommandError("Cannot join %s. %s" %
3446
containing_tree.subsume(sub_tree)
3447
except errors.BadSubsumeSource, e:
3448
raise errors.BzrCommandError("Cannot join %s. %s" %
3452
class cmd_split(Command):
3453
"""Split a tree into two trees.
3455
This command is for experimental use only. It requires the target tree
3456
to be in dirstate-with-subtree format, which cannot be converted into
3459
The TREE argument should be a subdirectory of a working tree. That
3460
subdirectory will be converted into an independent tree, with its own
3461
branch. Commits in the top-level tree will not apply to the new subtree.
3462
If you want that behavior, do "bzr join --reference TREE".
3465
_see_also = ['join']
3466
takes_args = ['tree']
3470
def run(self, tree):
3471
containing_tree, subdir = WorkingTree.open_containing(tree)
3472
sub_id = containing_tree.path2id(subdir)
3474
raise errors.NotVersionedError(subdir)
3476
containing_tree.extract(sub_id)
3477
except errors.RootNotRich:
3478
raise errors.UpgradeRequired(containing_tree.branch.base)
3482
class cmd_merge_directive(Command):
3483
"""Generate a merge directive for auto-merge tools.
3485
A directive requests a merge to be performed, and also provides all the
3486
information necessary to do so. This means it must either include a
3487
revision bundle, or the location of a branch containing the desired
3490
A submit branch (the location to merge into) must be supplied the first
3491
time the command is issued. After it has been supplied once, it will
3492
be remembered as the default.
3494
A public branch is optional if a revision bundle is supplied, but required
3495
if --diff or --plain is specified. It will be remembered as the default
3496
after the first use.
3499
takes_args = ['submit_branch?', 'public_branch?']
3502
RegistryOption.from_kwargs('patch-type',
3503
'The type of patch to include in the directive',
3504
title='Patch type', value_switches=True, enum_switch=False,
3505
bundle='Bazaar revision bundle (default)',
3506
diff='Normal unified diff',
3507
plain='No patch, just directive'),
3508
Option('sign', help='GPG-sign the directive'), 'revision',
3509
Option('mail-to', type=str,
3510
help='Instead of printing the directive, email to this address'),
3511
Option('message', type=str, short_name='m',
3512
help='Message to use when committing this merge')
3515
encoding_type = 'exact'
3517
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3518
sign=False, revision=None, mail_to=None, message=None):
3519
from bzrlib.revision import ensure_null, NULL_REVISION
3520
if patch_type == 'plain':
3522
branch = Branch.open('.')
3523
stored_submit_branch = branch.get_submit_branch()
3524
if submit_branch is None:
3525
submit_branch = stored_submit_branch
3527
if stored_submit_branch is None:
3528
branch.set_submit_branch(submit_branch)
3529
if submit_branch is None:
3530
submit_branch = branch.get_parent()
3531
if submit_branch is None:
3532
raise errors.BzrCommandError('No submit branch specified or known')
3534
stored_public_branch = branch.get_public_branch()
3535
if public_branch is None:
3536
public_branch = stored_public_branch
3537
elif stored_public_branch is None:
3538
branch.set_public_branch(public_branch)
3539
if patch_type != "bundle" and public_branch is None:
3540
raise errors.BzrCommandError('No public branch specified or'
3542
if revision is not None:
3543
if len(revision) != 1:
3544
raise errors.BzrCommandError('bzr merge-directive takes '
3545
'exactly one revision identifier')
3547
revision_id = revision[0].in_history(branch).rev_id
3549
revision_id = branch.last_revision()
3550
revision_id = ensure_null(revision_id)
3551
if revision_id == NULL_REVISION:
3552
raise errors.BzrCommandError('No revisions to bundle.')
3553
directive = merge_directive.MergeDirective.from_objects(
3554
branch.repository, revision_id, time.time(),
3555
osutils.local_time_offset(), submit_branch,
3556
public_branch=public_branch, patch_type=patch_type,
3560
self.outf.write(directive.to_signed(branch))
3562
self.outf.writelines(directive.to_lines())
3564
message = directive.to_email(mail_to, branch, sign)
3565
s = SMTPConnection(branch.get_config())
3566
s.send_email(message)
3569
class cmd_tag(Command):
3570
"""Create a tag naming a revision.
3572
Tags give human-meaningful names to revisions. Commands that take a -r
3573
(--revision) option can be given -rtag:X, where X is any previously
3576
Tags are stored in the branch. Tags are copied from one branch to another
3577
along when you branch, push, pull or merge.
3579
It is an error to give a tag name that already exists unless you pass
3580
--force, in which case the tag is moved to point to the new revision.
3583
_see_also = ['commit', 'tags']
3584
takes_args = ['tag_name']
3587
help='Delete this tag rather than placing it.',
3590
help='Branch in which to place the tag.',
3595
help='Replace existing tags',
3600
def run(self, tag_name,
3606
branch, relpath = Branch.open_containing(directory)
3610
branch.tags.delete_tag(tag_name)
3611
self.outf.write('Deleted tag %s.\n' % tag_name)
3614
if len(revision) != 1:
3615
raise errors.BzrCommandError(
3616
"Tags can only be placed on a single revision, "
3618
revision_id = revision[0].in_history(branch).rev_id
3620
revision_id = branch.last_revision()
3621
if (not force) and branch.tags.has_tag(tag_name):
3622
raise errors.TagAlreadyExists(tag_name)
3623
branch.tags.set_tag(tag_name, revision_id)
3624
self.outf.write('Created tag %s.\n' % tag_name)
3629
class cmd_tags(Command):
3632
This tag shows a table of tag names and the revisions they reference.
3638
help='Branch whose tags should be displayed',
3648
branch, relpath = Branch.open_containing(directory)
3649
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3650
self.outf.write('%-20s %s\n' % (tag_name, target))
3653
2652
# command-line interpretation helper for merge-related commands
3654
def _merge_helper(other_revision, base_revision,
3655
check_clean=True, ignore_zero=False,
3656
this_dir=None, backup_files=False,
3658
file_list=None, show_base=False, reprocess=False,
3661
change_reporter=None,
2653
def merge(other_revision, base_revision,
2654
check_clean=True, ignore_zero=False,
2655
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2656
file_list=None, show_base=False, reprocess=False,
2657
pb=DummyProgress()):
3663
2658
"""Merge changes into a tree.
3687
2682
clients might prefer to call merge.merge_inner(), which has less magic
3690
# Loading it late, so that we don't always have to import bzrlib.merge
3691
if merge_type is None:
3692
merge_type = _mod_merge.Merge3Merger
2685
from bzrlib.merge import Merger
3693
2686
if this_dir is None:
3694
2687
this_dir = u'.'
3695
2688
this_tree = WorkingTree.open_containing(this_dir)[0]
3696
if show_base and not merge_type is _mod_merge.Merge3Merger:
3697
raise errors.BzrCommandError("Show-base is not supported for this merge"
3698
" type. %s" % merge_type)
2689
if show_base and not merge_type is Merge3Merger:
2690
raise BzrCommandError("Show-base is not supported for this merge"
2691
" type. %s" % merge_type)
3699
2692
if reprocess and not merge_type.supports_reprocess:
3700
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3701
" type %s." % merge_type)
2693
raise BzrCommandError("Conflict reduction is not supported for merge"
2694
" type %s." % merge_type)
3702
2695
if reprocess and show_base:
3703
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3704
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3705
# only want to take out a lock_tree_write() if we don't have to pull
3706
# any ancestry. But merge might fetch ancestry in the middle, in
3707
# which case we would need a lock_write().
3708
# Because we cannot upgrade locks, for now we live with the fact that
3709
# the tree will be locked multiple times during a merge. (Maybe
3710
# read-only some of the time, but it means things will get read
2696
raise BzrCommandError("Cannot do conflict reduction and show base.")
3713
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3714
pb=pb, change_reporter=change_reporter)
2698
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
3715
2699
merger.pp = ProgressPhase("Merge phase", 5, pb)
3716
2700
merger.pp.next_phase()
3717
2701
merger.check_basis(check_clean)
3718
if other_rev_id is not None:
3719
merger.set_other_revision(other_rev_id, this_tree.branch)
3721
merger.set_other(other_revision)
2702
merger.set_other(other_revision)
3722
2703
merger.pp.next_phase()
3723
2704
merger.set_base(base_revision)
3724
2705
if merger.base_rev_id == merger.other_rev_id:
3725
2706
note('Nothing to do.')
3727
if file_list is None:
3728
if pull and merger.base_rev_id == merger.this_rev_id:
3729
# FIXME: deduplicate with pull
3730
result = merger.this_tree.pull(merger.this_branch,
3731
False, merger.other_rev_id)
3732
if result.old_revid == result.new_revid:
3733
note('No revisions to pull.')
3735
note('Now on revision %d.' % result.new_revno)
3737
2708
merger.backup_files = backup_files
3738
2709
merger.merge_type = merge_type
3739
2710
merger.set_interesting_files(file_list)