17
17
"""builtin bzr commands"""
20
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
27
32
from bzrlib import (
41
from bzrlib.branch import Branch, BranchReferenceFormat
42
from bzrlib.bundle import read_bundle_from_url
54
from bzrlib.branch import Branch
43
55
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
56
from bzrlib.conflicts import ConflictList
57
from bzrlib.revision import common_ancestor
58
from bzrlib.revisionspec import RevisionSpec
59
from bzrlib.workingtree import WorkingTree
45
62
from bzrlib.commands import Command, display_command
46
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
47
NotBranchError, DivergedBranches, NotConflicted,
48
NoSuchFile, NoWorkingTree, FileInWrongBranch,
49
NotVersionedError, NotABundle)
50
from bzrlib.merge import Merge3Merger
51
from bzrlib.option import Option
63
from bzrlib.option import ListOption, Option, RegistryOption
52
64
from bzrlib.progress import DummyProgress, ProgressPhase
53
from bzrlib.revision import common_ancestor
54
from bzrlib.revisionspec import RevisionSpec
55
65
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
56
from bzrlib.transport.local import LocalTransport
57
from bzrlib.workingtree import WorkingTree
60
68
def tree_files(file_list, default_branch=u'.'):
62
70
return internal_tree_files(file_list, default_branch)
63
except FileInWrongBranch, e:
64
raise BzrCommandError("%s is not in the same branch as %s" %
65
(e.path, file_list[0]))
71
except errors.FileInWrongBranch, e:
72
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
(e.path, file_list[0]))
68
76
# XXX: Bad function name; should possibly also be a class method of
78
86
:param file_list: Filenames to convert.
80
:param default_branch: Fallback tree path to use if file_list is empty or None.
88
:param default_branch: Fallback tree path to use if file_list is empty or
82
91
:return: workingtree, [relative_paths]
84
93
if file_list is None or len(file_list) == 0:
85
94
return WorkingTree.open_containing(default_branch)[0], file_list
86
tree = WorkingTree.open_containing(file_list[0])[0]
95
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
88
97
for filename in file_list:
90
new_list.append(tree.relpath(filename))
99
new_list.append(tree.relpath(osutils.dereference_path(filename)))
91
100
except errors.PathNotChild:
92
raise FileInWrongBranch(tree.branch, filename)
101
raise errors.FileInWrongBranch(tree.branch, filename)
93
102
return tree, new_list
105
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
96
106
def get_format_type(typestring):
97
107
"""Parse and return a format specifier."""
98
if typestring == "weave":
99
return bzrdir.BzrDirFormat6()
108
# Have to use BzrDirMetaFormat1 directly, so that
109
# RepositoryFormat.set_default_format works
100
110
if typestring == "default":
101
111
return bzrdir.BzrDirMetaFormat1()
102
if typestring == "metaweave":
103
format = bzrdir.BzrDirMetaFormat1()
104
format.repository_format = repository.RepositoryFormat7()
106
if typestring == "knit":
107
format = bzrdir.BzrDirMetaFormat1()
108
format.repository_format = repository.RepositoryFormatKnit1()
110
if typestring == "experimental-knit2":
111
format = bzrdir.BzrDirMetaFormat1()
112
format.repository_format = repository.RepositoryFormatKnit2()
114
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
115
"metaweave and weave" % typestring
116
raise BzrCommandError(msg)
113
return bzrdir.format_registry.make_bzrdir(typestring)
115
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
116
raise errors.BzrCommandError(msg)
119
119
# TODO: Make sure no commands unconditionally use the working directory as a
361
437
"""Show inventory of the current working copy or a revision.
363
439
It is possible to limit the output to a particular entry
364
type using the --kind option. For example; --kind file.
440
type using the --kind option. For example: --kind file.
442
It is also possible to restrict the list of files to a specific
443
set. For example: bzr inventory --show-ids this/file
367
448
takes_options = ['revision', 'show-ids', 'kind']
449
takes_args = ['file*']
370
def run(self, revision=None, show_ids=False, kind=None):
452
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
371
453
if kind and kind not in ['file', 'directory', 'symlink']:
372
raise BzrCommandError('invalid kind specified')
373
tree = WorkingTree.open_containing(u'.')[0]
375
inv = tree.read_working_inventory()
377
if len(revision) > 1:
378
raise BzrCommandError('bzr inventory --revision takes'
379
' exactly one revision identifier')
380
inv = tree.branch.repository.get_revision_inventory(
381
revision[0].in_history(tree.branch).rev_id)
383
for path, entry in inv.entries():
454
raise errors.BzrCommandError('invalid kind specified')
456
work_tree, file_list = tree_files(file_list)
457
work_tree.lock_read()
459
if revision is not None:
460
if len(revision) > 1:
461
raise errors.BzrCommandError(
462
'bzr inventory --revision takes exactly one revision'
464
revision_id = revision[0].in_history(work_tree.branch).rev_id
465
tree = work_tree.branch.repository.revision_tree(revision_id)
467
extra_trees = [work_tree]
473
if file_list is not None:
474
file_ids = tree.paths2ids(file_list, trees=extra_trees,
475
require_versioned=True)
476
# find_ids_across_trees may include some paths that don't
478
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
479
for file_id in file_ids if file_id in tree)
481
entries = tree.inventory.entries()
484
if tree is not work_tree:
487
for path, entry in entries:
384
488
if kind and kind != entry.kind:
448
562
location can be accessed.
451
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
565
_see_also = ['push', 'update']
566
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
568
help='branch to pull into, '
569
'rather than the one containing the working directory',
452
574
takes_args = ['location?']
453
575
encoding_type = 'replace'
455
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
577
def run(self, location=None, remember=False, overwrite=False,
578
revision=None, verbose=False,
580
from bzrlib.tag import _merge_tags_if_possible
456
581
# FIXME: too much stuff is in the command class
584
if directory is None:
458
tree_to = WorkingTree.open_containing(u'.')[0]
587
tree_to = WorkingTree.open_containing(directory)[0]
459
588
branch_to = tree_to.branch
460
except NoWorkingTree:
589
except errors.NoWorkingTree:
462
branch_to = Branch.open_containing(u'.')[0]
591
branch_to = Branch.open_containing(directory)[0]
465
594
if location is not None:
467
reader = bundle.read_bundle_from_url(location)
596
mergeable = bundle.read_mergeable_from_url(
598
except errors.NotABundle:
469
599
pass # Continue on considering this url a Branch
471
601
stored_loc = branch_to.get_parent()
472
602
if location is None:
473
603
if stored_loc is None:
474
raise BzrCommandError("No pull location known or specified.")
604
raise errors.BzrCommandError("No pull location known or"
476
607
display_url = urlutils.unescape_for_display(stored_loc,
477
608
self.outf.encoding)
478
609
self.outf.write("Using saved location: %s\n" % display_url)
479
610
location = stored_loc
482
if reader is not None:
483
install_bundle(branch_to.repository, reader)
612
if mergeable is not None:
613
if revision is not None:
614
raise errors.BzrCommandError(
615
'Cannot use -r with merge directives or bundles')
616
revision_id = mergeable.install_revisions(branch_to.repository)
484
617
branch_from = branch_to
486
619
branch_from = Branch.open(location)
563
709
location = stored_loc
565
711
to_transport = transport.get_transport(location)
566
location_url = to_transport.base
713
br_to = repository_to = dir_to = None
715
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
716
except errors.NotBranchError:
717
pass # Didn't find anything
719
# If we can open a branch, use its direct repository, otherwise see
720
# if there is a repository without a branch.
722
br_to = dir_to.open_branch()
723
except errors.NotBranchError:
724
# Didn't find a branch, can we find a repository?
726
repository_to = dir_to.find_repository()
727
except errors.NoRepositoryPresent:
730
# Found a branch, so we must have found a repository
731
repository_to = br_to.repository
570
dir_to = bzrdir.BzrDir.open(location_url)
571
br_to = dir_to.open_branch()
572
except NotBranchError:
574
to_transport = to_transport.clone('..')
575
if not create_prefix:
577
relurl = to_transport.relpath(location_url)
578
mutter('creating directory %s => %s', location_url, relurl)
579
to_transport.mkdir(relurl)
581
raise BzrCommandError("Parent directory of %s "
582
"does not exist." % location)
584
current = to_transport.base
585
needed = [(to_transport, to_transport.relpath(location_url))]
735
# The destination doesn't exist; create it.
736
# XXX: Refactor the create_prefix/no_create_prefix code into a
737
# common helper function
739
to_transport.mkdir('.')
740
except errors.FileExists:
741
if not use_existing_dir:
742
raise errors.BzrCommandError("Target directory %s"
743
" already exists, but does not have a valid .bzr"
744
" directory. Supply --use-existing-dir to push"
745
" there anyway." % location)
746
except errors.NoSuchFile:
747
if not create_prefix:
748
raise errors.BzrCommandError("Parent directory of %s"
750
"\nYou may supply --create-prefix to create all"
751
" leading parent directories."
754
cur_transport = to_transport
755
needed = [cur_transport]
756
# Recurse upwards until we can create a directory successfully
758
new_transport = cur_transport.clone('..')
759
if new_transport.base == cur_transport.base:
760
raise errors.BzrCommandError("Failed to create path"
764
new_transport.mkdir('.')
765
except errors.NoSuchFile:
766
needed.append(new_transport)
767
cur_transport = new_transport
771
# Now we only need to create child directories
588
to_transport, relpath = needed[-1]
589
to_transport.mkdir(relpath)
592
new_transport = to_transport.clone('..')
593
needed.append((new_transport,
594
new_transport.relpath(to_transport.base)))
595
if new_transport.base == to_transport.base:
596
raise BzrCommandError("Could not create "
598
dir_to = br_from.bzrdir.clone(location_url,
773
cur_transport = needed.pop()
774
cur_transport.ensure_base()
776
# Now the target directory exists, but doesn't have a .bzr
777
# directory. So we need to create it, along with any work to create
778
# all of the dependent branches, etc.
779
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
599
780
revision_id=br_from.last_revision())
600
781
br_to = dir_to.open_branch()
601
count = len(br_to.revision_history())
782
# TODO: Some more useful message about what was copied
783
note('Created new branch.')
602
784
# We successfully created the target, remember it
603
785
if br_from.get_push_location() is None or remember:
604
786
br_from.set_push_location(br_to.base)
787
elif repository_to is None:
788
# we have a bzrdir but no branch or repository
789
# XXX: Figure out what to do other than complain.
790
raise errors.BzrCommandError("At %s you have a valid .bzr control"
791
" directory, but not a branch or repository. This is an"
792
" unsupported configuration. Please move the target directory"
793
" out of the way and try again."
796
# We have a repository but no branch, copy the revisions, and then
798
last_revision_id = br_from.last_revision()
799
repository_to.fetch(br_from.repository,
800
revision_id=last_revision_id)
801
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
802
note('Created new branch.')
803
if br_from.get_push_location() is None or remember:
804
br_from.set_push_location(br_to.base)
805
else: # We have a valid to branch
606
806
# We were able to connect to the remote location, so remember it
607
807
# we don't need to successfully push because of possible divergence.
608
808
if br_from.get_push_location() is None or remember:
881
1085
also new, they will also be removed.
883
1087
takes_args = ['file*']
884
takes_options = ['verbose', Option('new', help='remove newly-added files')]
1088
takes_options = ['verbose',
1089
Option('new', help='remove newly-added files'),
1090
RegistryOption.from_kwargs('file-deletion-strategy',
1091
'The file deletion mode to be used',
1092
title='Deletion Strategy', value_switches=True, enum_switch=False,
1093
safe='Only delete files if they can be'
1094
' safely recovered (default).',
1095
keep="Don't delete any files.",
1096
force='Delete all the specified files, even if they can not be '
1097
'recovered and even if they are non-empty directories.')]
885
1098
aliases = ['rm']
886
1099
encoding_type = 'replace'
888
def run(self, file_list, verbose=False, new=False):
1101
def run(self, file_list, verbose=False, new=False,
1102
file_deletion_strategy='safe'):
889
1103
tree, file_list = tree_files(file_list)
891
if file_list is None:
892
raise BzrCommandError('Specify one or more files to remove, or'
1105
if file_list is not None:
1106
file_list = [f for f in file_list if f != '']
1108
raise errors.BzrCommandError('Specify one or more files to'
1109
' remove, or use --new.')
895
1112
added = tree.changes_from(tree.basis_tree(),
896
1113
specific_files=file_list).added
897
1114
file_list = sorted([f[0] for f in added], reverse=True)
898
1115
if len(file_list) == 0:
899
raise BzrCommandError('No matching files.')
900
tree.remove(file_list, verbose=verbose, to_file=self.outf)
1116
raise errors.BzrCommandError('No matching files.')
1117
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1118
keep_files=file_deletion_strategy=='keep',
1119
force=file_deletion_strategy=='force')
903
1122
class cmd_file_id(Command):
1050
1284
# believe that we want to create a bunch of
1051
1285
# locations if the user supplies an extended path
1052
1286
# TODO: create-prefix
1054
to_transport.mkdir('.')
1055
except errors.FileExists:
1287
to_transport.ensure_base()
1059
1290
existing_bzrdir = bzrdir.BzrDir.open(location)
1060
except NotBranchError:
1291
except errors.NotBranchError:
1061
1292
# really a NotBzrDir error...
1062
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1293
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1296
from bzrlib.transport.local import LocalTransport
1064
1297
if existing_bzrdir.has_branch():
1065
1298
if (isinstance(to_transport, LocalTransport)
1066
1299
and not existing_bzrdir.has_workingtree()):
1067
1300
raise errors.BranchExistsWithoutWorkingTree(location)
1068
1301
raise errors.AlreadyBranchError(location)
1070
existing_bzrdir.create_branch()
1303
branch = existing_bzrdir.create_branch()
1071
1304
existing_bzrdir.create_workingtree()
1305
if append_revisions_only:
1307
branch.set_append_revisions_only(True)
1308
except errors.UpgradeRequired:
1309
raise errors.BzrCommandError('This branch format cannot be set'
1310
' to append-revisions-only. Try --experimental-branch6')
1074
1313
class cmd_init_repository(Command):
1075
1314
"""Create a shared repository to hold branches.
1077
New branches created under the repository directory will store their revisions
1078
in the repository, not in the branch directory, if the branch format supports
1316
New branches created under the repository directory will store their
1317
revisions in the repository, not in the branch directory.
1319
If the --no-trees option is used then the branches in the repository
1320
will not have working trees by default.
1323
bzr init-repo --no-trees repo
1083
1324
bzr init repo/trunk
1084
1325
bzr checkout --lightweight repo/trunk trunk-checkout
1085
1326
cd trunk-checkout
1086
1327
(add files here)
1329
See 'bzr help repositories' for more information.
1088
takes_args = ["location"]
1089
takes_options = [Option('format',
1090
help='Specify a format for this repository.'
1091
' Current formats are: default, knit,'
1092
' metaweave and weave. Default is knit;'
1093
' metaweave and weave are deprecated',
1094
type=get_format_type),
1096
help='Allows branches in repository to have'
1332
_see_also = ['init', 'branch', 'checkout']
1333
takes_args = ["location"]
1334
takes_options = [RegistryOption('format',
1335
help='Specify a format for this repository. See'
1336
' "bzr help formats" for details',
1337
registry=bzrdir.format_registry,
1338
converter=bzrdir.format_registry.make_bzrdir,
1339
value_switches=True, title='Repository format'),
1341
help='Branches in the repository will default to'
1342
' not having a working tree'),
1098
1344
aliases = ["init-repo"]
1099
def run(self, location, format=None, trees=False):
1346
def run(self, location, format=None, no_trees=False):
1100
1347
if format is None:
1101
format = get_format_type('default')
1348
format = bzrdir.format_registry.make_bzrdir('default')
1103
1350
if location is None:
1106
1353
to_transport = transport.get_transport(location)
1108
to_transport.mkdir('.')
1109
except errors.FileExists:
1354
to_transport.ensure_base()
1112
1356
newdir = format.initialize_on_transport(to_transport)
1113
1357
repo = newdir.create_repository(shared=True)
1114
repo.set_make_working_trees(trees)
1358
repo.set_make_working_trees(not no_trees)
1117
1361
class cmd_diff(Command):
1358
1647
dir, relpath = bzrdir.BzrDir.open_containing(location)
1359
1648
b = dir.open_branch()
1361
if revision is None:
1364
elif len(revision) == 1:
1365
rev1 = rev2 = revision[0].in_history(b).revno
1366
elif len(revision) == 2:
1367
if revision[1].get_branch() != revision[0].get_branch():
1368
# b is taken from revision[0].get_branch(), and
1369
# show_log will use its revision_history. Having
1370
# different branches will lead to weird behaviors.
1371
raise BzrCommandError(
1372
"Log doesn't accept two revisions in different branches.")
1373
if revision[0].spec is None:
1374
# missing begin-range means first revision
1377
rev1 = revision[0].in_history(b).revno
1379
if revision[1].spec is None:
1380
# missing end-range means last known revision
1383
rev2 = revision[1].in_history(b).revno
1385
raise BzrCommandError('bzr log --revision takes one or two values.')
1387
# By this point, the revision numbers are converted to the +ve
1388
# form if they were supplied in the -ve form, so we can do
1389
# this comparison in relative safety
1391
(rev2, rev1) = (rev1, rev2)
1393
if (log_format is None):
1394
default = b.get_config().log_format()
1395
log_format = get_log_format(long=long, short=short, line=line,
1397
lf = log_formatter(log_format,
1400
show_timezone=timezone)
1406
direction=direction,
1407
start_revision=rev1,
1652
if revision is None:
1655
elif len(revision) == 1:
1656
rev1 = rev2 = revision[0].in_history(b).revno
1657
elif len(revision) == 2:
1658
if revision[1].get_branch() != revision[0].get_branch():
1659
# b is taken from revision[0].get_branch(), and
1660
# show_log will use its revision_history. Having
1661
# different branches will lead to weird behaviors.
1662
raise errors.BzrCommandError(
1663
"Log doesn't accept two revisions in different"
1665
if revision[0].spec is None:
1666
# missing begin-range means first revision
1669
rev1 = revision[0].in_history(b).revno
1671
if revision[1].spec is None:
1672
# missing end-range means last known revision
1675
rev2 = revision[1].in_history(b).revno
1677
raise errors.BzrCommandError(
1678
'bzr log --revision takes one or two values.')
1680
# By this point, the revision numbers are converted to the +ve
1681
# form if they were supplied in the -ve form, so we can do
1682
# this comparison in relative safety
1684
(rev2, rev1) = (rev1, rev2)
1686
if log_format is None:
1687
log_format = log.log_formatter_registry.get_default(b)
1689
lf = log_format(show_ids=show_ids, to_file=self.outf,
1690
show_timezone=timezone)
1696
direction=direction,
1697
start_revision=rev1,
1412
1705
def get_log_format(long=False, short=False, line=False, default='long'):
1454
1748
Option('ignored', help='Print ignored files'),
1456
1750
Option('null', help='Null separate the files'),
1458
1753
@display_command
1459
1754
def run(self, revision=None, verbose=False,
1460
1755
non_recursive=False, from_root=False,
1461
1756
unknown=False, versioned=False, ignored=False,
1757
null=False, kind=None, show_ids=False, path=None):
1759
if kind and kind not in ('file', 'directory', 'symlink'):
1760
raise errors.BzrCommandError('invalid kind specified')
1464
1762
if verbose and null:
1465
raise BzrCommandError('Cannot set both --verbose and --null')
1763
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1466
1764
all = not (unknown or versioned or ignored)
1468
1766
selection = {'I':ignored, '?':unknown, 'V':versioned}
1470
tree, relpath = WorkingTree.open_containing(u'.')
1773
raise errors.BzrCommandError('cannot specify both --from-root'
1777
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1475
1783
if revision is not None:
1476
tree = tree.branch.repository.revision_tree(
1477
revision[0].in_history(tree.branch).rev_id)
1784
tree = branch.repository.revision_tree(
1785
revision[0].in_history(branch).rev_id)
1787
tree = branch.basis_tree()
1479
for fp, fc, kind, fid, entry in tree.list_files():
1480
if fp.startswith(relpath):
1481
fp = fp[len(relpath):]
1482
if non_recursive and '/' in fp:
1484
if not all and not selection[fc]:
1487
kindch = entry.kind_character()
1488
self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1490
self.outf.write(fp + '\0')
1493
self.outf.write(fp + '\n')
1791
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1792
if fp.startswith(relpath):
1793
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1794
if non_recursive and '/' in fp:
1796
if not all and not selection[fc]:
1798
if kind is not None and fkind != kind:
1801
kindch = entry.kind_character()
1802
outstring = '%-8s %s%s' % (fc, fp, kindch)
1803
if show_ids and fid is not None:
1804
outstring = "%-50s %s" % (outstring, fid)
1805
self.outf.write(outstring + '\n')
1807
self.outf.write(fp + '\0')
1810
self.outf.write(fid)
1811
self.outf.write('\0')
1819
self.outf.write('%-50s %s\n' % (fp, my_id))
1821
self.outf.write(fp + '\n')
1496
1826
class cmd_unknowns(Command):
1497
"""List unknown files."""
1827
"""List unknown files.
1498
1833
@display_command
1500
1835
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1504
1839
class cmd_ignore(Command):
1505
"""Ignore a command or pattern.
1840
"""Ignore specified files or patterns.
1507
1842
To remove patterns from the ignore list, edit the .bzrignore file.
1509
If the pattern contains a slash, it is compared to the whole path
1510
from the branch root. Otherwise, it is compared to only the last
1511
component of the path. To match a file only in the root directory,
1514
Ignore patterns are case-insensitive on case-insensitive systems.
1516
Note: wildcards must be quoted from the shell on Unix.
1844
Trailing slashes on patterns are ignored.
1845
If the pattern contains a slash or is a regular expression, it is compared
1846
to the whole path from the branch root. Otherwise, it is compared to only
1847
the last component of the path. To match a file only in the root
1848
directory, prepend './'.
1850
Ignore patterns specifying absolute paths are not allowed.
1852
Ignore patterns may include globbing wildcards such as:
1853
? - Matches any single character except '/'
1854
* - Matches 0 or more characters except '/'
1855
/**/ - Matches 0 or more directories in a path
1856
[a-z] - Matches a single character from within a group of characters
1858
Ignore patterns may also be Python regular expressions.
1859
Regular expression ignore patterns are identified by a 'RE:' prefix
1860
followed by the regular expression. Regular expression ignore patterns
1861
may not include named or numbered groups.
1863
Note: ignore patterns containing shell wildcards must be quoted from
1519
1867
bzr ignore ./Makefile
1520
1868
bzr ignore '*.class'
1869
bzr ignore 'lib/**/*.o'
1870
bzr ignore 'RE:lib/.*\.o'
1522
# TODO: Complain if the filename is absolute
1523
takes_args = ['name_pattern?']
1873
_see_also = ['status', 'ignored']
1874
takes_args = ['name_pattern*']
1524
1875
takes_options = [
1525
1876
Option('old-default-rules',
1526
1877
help='Out the ignore rules bzr < 0.9 always used.')
1529
def run(self, name_pattern=None, old_default_rules=None):
1880
def run(self, name_pattern_list=None, old_default_rules=None):
1530
1881
from bzrlib.atomicfile import AtomicFile
1531
1882
if old_default_rules is not None:
1532
1883
# dump the rules and exit
1533
1884
for pattern in ignores.OLD_DEFAULTS:
1536
if name_pattern is None:
1537
raise BzrCommandError("ignore requires a NAME_PATTERN")
1887
if not name_pattern_list:
1888
raise errors.BzrCommandError("ignore requires at least one "
1889
"NAME_PATTERN or --old-default-rules")
1890
name_pattern_list = [globbing.normalize_pattern(p)
1891
for p in name_pattern_list]
1892
for name_pattern in name_pattern_list:
1893
if (name_pattern[0] == '/' or
1894
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1895
raise errors.BzrCommandError(
1896
"NAME_PATTERN should not be an absolute path")
1538
1897
tree, relpath = WorkingTree.open_containing(u'.')
1539
1898
ifn = tree.abspath('.bzrignore')
1540
1899
if os.path.exists(ifn):
1624
1989
tgz .tar.gz, .tgz
1627
takes_args = ['dest']
1992
takes_args = ['dest', 'branch?']
1628
1993
takes_options = ['revision', 'format', 'root']
1629
def run(self, dest, revision=None, format=None, root=None):
1994
def run(self, dest, branch=None, revision=None, format=None, root=None):
1630
1995
from bzrlib.export import export
1631
tree = WorkingTree.open_containing(u'.')[0]
1998
tree = WorkingTree.open_containing(u'.')[0]
2001
b = Branch.open(branch)
1633
2003
if revision is None:
1634
2004
# should be tree.last_revision FIXME
1635
2005
rev_id = b.last_revision()
1637
2007
if len(revision) != 1:
1638
raise BzrError('bzr export --revision takes exactly 1 argument')
2008
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1639
2009
rev_id = revision[0].in_history(b).rev_id
1640
2010
t = b.repository.revision_tree(rev_id)
1642
2012
export(t, dest, format, root)
1643
2013
except errors.NoSuchExportFormat, e:
1644
raise BzrCommandError('Unsupported export format: %s' % e.format)
2014
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1647
2017
class cmd_cat(Command):
1648
"""Write a file's text from a previous revision."""
1650
takes_options = ['revision']
2018
"""Write the contents of a file as of a given revision to standard output.
2020
If no revision is nominated, the last revision is used.
2022
Note: Take care to redirect standard output when using this command on a
2027
takes_options = ['revision', 'name-from-revision']
1651
2028
takes_args = ['filename']
2029
encoding_type = 'exact'
1653
2031
@display_command
1654
def run(self, filename, revision=None):
2032
def run(self, filename, revision=None, name_from_revision=False):
1655
2033
if revision is not None and len(revision) != 1:
1656
raise BzrCommandError("bzr cat --revision takes exactly one number")
2034
raise errors.BzrCommandError("bzr cat --revision takes exactly"
1659
tree, relpath = WorkingTree.open_containing(filename)
1661
except NotBranchError:
2039
tree, b, relpath = \
2040
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2041
except errors.NotBranchError:
1665
b, relpath = Branch.open_containing(filename)
1666
2044
if revision is not None and revision[0].get_branch() is not None:
1667
2045
b = Branch.open(revision[0].get_branch())
2047
tree = b.basis_tree()
1668
2048
if revision is None:
1669
2049
revision_id = b.last_revision()
1671
2051
revision_id = revision[0].in_history(b).rev_id
1672
b.print_file(relpath, revision_id)
2053
cur_file_id = tree.path2id(relpath)
2054
rev_tree = b.repository.revision_tree(revision_id)
2055
old_file_id = rev_tree.path2id(relpath)
2057
if name_from_revision:
2058
if old_file_id is None:
2059
raise errors.BzrCommandError("%r is not present in revision %s"
2060
% (filename, revision_id))
2062
rev_tree.print_file(old_file_id)
2063
elif cur_file_id is not None:
2064
rev_tree.print_file(cur_file_id)
2065
elif old_file_id is not None:
2066
rev_tree.print_file(old_file_id)
2068
raise errors.BzrCommandError("%r is not present in revision %s" %
2069
(filename, revision_id))
1675
2072
class cmd_local_time_offset(Command):
1723
2140
aliases = ['ci', 'checkin']
2142
def _get_bug_fix_properties(self, fixes, branch):
2144
# Configure the properties for bug fixing attributes.
2145
for fixed_bug in fixes:
2146
tokens = fixed_bug.split(':')
2147
if len(tokens) != 2:
2148
raise errors.BzrCommandError(
2149
"Invalid bug %s. Must be in the form of 'tag:id'. "
2150
"Commit refused." % fixed_bug)
2151
tag, bug_id = tokens
2153
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2154
except errors.UnknownBugTrackerAbbreviation:
2155
raise errors.BzrCommandError(
2156
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2157
except errors.MalformedBugIdentifier:
2158
raise errors.BzrCommandError(
2159
"Invalid bug identifier for %s. Commit refused."
2161
properties.append('%s fixed' % bug_url)
2162
return '\n'.join(properties)
1725
2164
def run(self, message=None, file=None, verbose=True, selected_list=None,
1726
unchanged=False, strict=False, local=False):
2165
unchanged=False, strict=False, local=False, fixes=None):
1727
2166
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
1728
2167
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1729
2168
StrictCommitFailed)
1730
2169
from bzrlib.msgeditor import edit_commit_message, \
1731
2170
make_commit_message_template
1732
from tempfile import TemporaryFile
1734
2172
# TODO: Need a blackbox test for invoking the external editor; may be
1735
2173
# slightly problematic to run this cross-platform.
1737
2175
# TODO: do more checks that the commit will succeed before
1738
2176
# spending the user's valuable time typing a commit message.
1740
# TODO: if the commit *does* happen to fail, then save the commit
1741
# message to a temporary file where it can be recovered
1742
2180
tree, selected_list = tree_files(selected_list)
1743
2181
if selected_list == ['']:
1744
2182
# workaround - commit of root of tree should be exactly the same
1746
2184
# selected-file merge commit is not done yet
1747
2185
selected_list = []
2187
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2189
properties['bugs'] = bug_property
1749
2191
if local and not tree.branch.get_bound_location():
1750
2192
raise errors.LocalRequiresBoundBranch()
1751
if message is None and not file:
1752
template = make_commit_message_template(tree, selected_list)
1753
message = edit_commit_message(template)
1755
raise BzrCommandError("please specify a commit message"
1756
" with either --message or --file")
1757
elif message and file:
1758
raise BzrCommandError("please specify either --message or --file")
1761
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1764
raise BzrCommandError("empty commit message specified")
2194
def get_message(commit_obj):
2195
"""Callback to get commit message"""
2196
my_message = message
2197
if my_message is None and not file:
2198
template = make_commit_message_template(tree, selected_list)
2199
my_message = edit_commit_message(template)
2200
if my_message is None:
2201
raise errors.BzrCommandError("please specify a commit"
2202
" message with either --message or --file")
2203
elif my_message and file:
2204
raise errors.BzrCommandError(
2205
"please specify either --message or --file")
2207
my_message = codecs.open(file, 'rt',
2208
bzrlib.user_encoding).read()
2209
if my_message == "":
2210
raise errors.BzrCommandError("empty commit message specified")
1767
2214
reporter = ReportCommitToLog()
1769
2216
reporter = NullCommitReporter()
1772
tree.commit(message, specific_files=selected_list,
2219
tree.commit(message_callback=get_message,
2220
specific_files=selected_list,
1773
2221
allow_pointless=unchanged, strict=strict, local=local,
2222
reporter=reporter, revprops=properties)
1775
2223
except PointlessCommit:
1776
2224
# FIXME: This should really happen before the file is read in;
1777
2225
# perhaps prepare the commit; get the message; then actually commit
1778
raise BzrCommandError("no changes to commit."
1779
" use --unchanged to commit anyhow")
2226
raise errors.BzrCommandError("no changes to commit."
2227
" use --unchanged to commit anyhow")
1780
2228
except ConflictsInTree:
1781
raise BzrCommandError("Conflicts detected in working tree. "
1782
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2229
raise errors.BzrCommandError('Conflicts detected in working '
2230
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1783
2232
except StrictCommitFailed:
1784
raise BzrCommandError("Commit refused because there are unknown "
1785
"files in the working tree.")
2233
raise errors.BzrCommandError("Commit refused because there are"
2234
" unknown files in the working tree.")
1786
2235
except errors.BoundBranchOutOfDate, e:
1787
raise BzrCommandError(str(e) + "\n"
1788
'To commit to master branch, run update and then commit.\n'
1789
'You can also pass --local to commit to continue working '
2236
raise errors.BzrCommandError(str(e) + "\n"
2237
'To commit to master branch, run update and then commit.\n'
2238
'You can also pass --local to commit to continue working '
1792
2242
class cmd_check(Command):
1793
2243
"""Validate consistency of branch history.
1914
2350
@display_command
1915
2351
def printme(self, branch):
1919
2355
class cmd_selftest(Command):
1920
2356
"""Run internal test suite.
1922
This creates temporary test directories in the working directory,
1923
but not existing data is affected. These directories are deleted
1924
if the tests pass, or left behind to help in debugging if they
1925
fail and --keep-output is specified.
2358
This creates temporary test directories in the working directory, but no
2359
existing data is affected. These directories are deleted if the tests
2360
pass, or left behind to help in debugging if they fail and --keep-output
1927
If arguments are given, they are regular expressions that say
1928
which tests should run.
2363
If arguments are given, they are regular expressions that say which tests
2364
should run. Tests matching any expression are run, and other tests are
2367
Alternatively if --first is given, matching tests are run first and then
2368
all other tests are run. This is useful if you have been working in a
2369
particular area, but want to make sure nothing else was broken.
2371
If --exclude is given, tests that match that regular expression are
2372
excluded, regardless of whether they match --first or not.
2374
To help catch accidential dependencies between tests, the --randomize
2375
option is useful. In most cases, the argument used is the word 'now'.
2376
Note that the seed used for the random number generator is displayed
2377
when this option is used. The seed can be explicitly passed as the
2378
argument to this option if required. This enables reproduction of the
2379
actual ordering used if and when an order sensitive problem is encountered.
2381
If --list-only is given, the tests that would be run are listed. This is
2382
useful when combined with --first, --exclude and/or --randomize to
2383
understand their impact. The test harness reports "Listed nn tests in ..."
2384
instead of "Ran nn tests in ..." when list mode is enabled.
1930
2386
If the global option '--no-plugins' is given, plugins are not loaded
1931
2387
before running the selftests. This has two effects: features provided or
1932
2388
modified by plugins will not be tested, and tests provided by plugins will
1936
2392
bzr selftest ignore
2393
run only tests relating to 'ignore'
1937
2394
bzr --no-plugins selftest -v
2395
disable plugins and list tests as they're run
2397
For each test, that needs actual disk access, bzr create their own
2398
subdirectory in the temporary testing directory (testXXXX.tmp).
2399
By default the name of such subdirectory is based on the name of the test.
2400
If option '--numbered-dirs' is given, bzr will use sequent numbers
2401
of running tests to create such subdirectories. This is default behavior
2402
on Windows because of path length limitation.
1939
# TODO: --list should give a list of all available tests
1941
2404
# NB: this is used from the class without creating an instance, which is
1942
2405
# why it does not have a self parameter.
1943
2406
def get_transport_type(typestring):
1953
2416
return FakeNFSServer
1954
2417
msg = "No known transport type %s. Supported types are: sftp\n" %\
1956
raise BzrCommandError(msg)
2419
raise errors.BzrCommandError(msg)
1959
2422
takes_args = ['testspecs*']
1960
2423
takes_options = ['verbose',
1961
Option('one', help='stop when one test fails'),
1962
Option('keep-output',
2425
help='stop when one test fails',
2428
Option('keep-output',
1963
2429
help='keep output directories when tests fail'),
1965
2431
help='Use a different transport by default '
1966
2432
'throughout the test suite.',
1967
2433
type=get_transport_type),
1968
Option('benchmark', help='run the bzr bencharks.'),
2434
Option('benchmark', help='run the bzr benchmarks.'),
1969
2435
Option('lsprof-timed',
1970
2436
help='generate lsprof output for benchmarked'
1971
2437
' sections of code.'),
1972
2438
Option('cache-dir', type=str,
1973
2439
help='a directory to cache intermediate'
1974
2440
' benchmark steps'),
2441
Option('clean-output',
2442
help='clean temporary tests directories'
2443
' without running tests'),
2445
help='run all tests, but run specified tests first',
2448
Option('numbered-dirs',
2449
help='use numbered dirs for TestCaseInTempDir'),
2451
help='list the tests instead of running them'),
2452
Option('randomize', type=str, argname="SEED",
2453
help='randomize the order of tests using the given'
2454
' seed or "now" for the current time'),
2455
Option('exclude', type=str, argname="PATTERN",
2457
help='exclude tests that match this regular'
2460
encoding_type = 'replace'
1977
2462
def run(self, testspecs_list=None, verbose=None, one=False,
1978
2463
keep_output=False, transport=None, benchmark=None,
1979
lsprof_timed=None, cache_dir=None):
2464
lsprof_timed=None, cache_dir=None, clean_output=False,
2465
first=False, numbered_dirs=None, list_only=False,
2466
randomize=None, exclude=None):
1980
2467
import bzrlib.ui
1981
2468
from bzrlib.tests import selftest
1982
2469
import bzrlib.benchmarks as benchmarks
1983
2470
from bzrlib.benchmarks import tree_creator
2473
from bzrlib.tests import clean_selftest_output
2474
clean_selftest_output()
2477
if numbered_dirs is None and sys.platform == 'win32':
2478
numbered_dirs = True
1985
2480
if cache_dir is not None:
1986
2481
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1987
# we don't want progress meters from the tests to go to the
1988
# real output; and we don't want log messages cluttering up
1990
save_ui = ui.ui_factory
1991
2482
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1992
2483
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1994
info('running tests...')
2485
if testspecs_list is not None:
2486
pattern = '|'.join(testspecs_list)
2490
test_suite_factory = benchmarks.test_suite
2493
# TODO: should possibly lock the history file...
2494
benchfile = open(".perf_history", "at", buffering=1)
2496
test_suite_factory = None
1996
ui.ui_factory = ui.SilentUIFactory()
1997
if testspecs_list is not None:
1998
pattern = '|'.join(testspecs_list)
2002
test_suite_factory = benchmarks.test_suite
2005
benchfile = open(".perf_history", "at")
2007
test_suite_factory = None
2012
result = selftest(verbose=verbose,
2014
stop_on_failure=one,
2015
keep_output=keep_output,
2016
transport=transport,
2017
test_suite_factory=test_suite_factory,
2018
lsprof_timed=lsprof_timed,
2019
bench_history=benchfile)
2021
if benchfile is not None:
2024
info('tests passed')
2026
info('tests failed')
2027
return int(not result)
2501
result = selftest(verbose=verbose,
2503
stop_on_failure=one,
2504
keep_output=keep_output,
2505
transport=transport,
2506
test_suite_factory=test_suite_factory,
2507
lsprof_timed=lsprof_timed,
2508
bench_history=benchfile,
2509
matching_tests_first=first,
2510
numbered_dirs=numbered_dirs,
2511
list_only=list_only,
2512
random_seed=randomize,
2513
exclude_pattern=exclude
2029
ui.ui_factory = save_ui
2516
if benchfile is not None:
2519
info('tests passed')
2521
info('tests failed')
2522
return int(not result)
2032
2525
class cmd_version(Command):
2101
2591
default, use --remember. The value will only be saved if the remote
2102
2592
location can be accessed.
2594
The results of the merge are placed into the destination working
2595
directory, where they can be reviewed (with bzr diff), tested, and then
2596
committed to record the result of the merge.
2106
To merge the latest revision from bzr.dev
2107
bzr merge ../bzr.dev
2600
To merge the latest revision from bzr.dev:
2601
bzr merge ../bzr.dev
2109
To merge changes up to and including revision 82 from bzr.dev
2110
bzr merge -r 82 ../bzr.dev
2603
To merge changes up to and including revision 82 from bzr.dev:
2604
bzr merge -r 82 ../bzr.dev
2112
2606
To merge the changes introduced by 82, without previous changes:
2113
bzr merge -r 81..82 ../bzr.dev
2607
bzr merge -r 81..82 ../bzr.dev
2115
2609
merge refuses to run if there are any uncommitted changes, unless
2116
2610
--force is given.
2118
The following merge types are available:
2613
_see_also = ['update', 'remerge']
2120
2614
takes_args = ['branch?']
2121
2615
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2122
Option('show-base', help="Show base revision text in "
2124
Option('uncommitted', help='Apply uncommitted changes'
2125
' from a working copy, instead of branch changes')]
2128
from merge import merge_type_help
2129
from inspect import getdoc
2130
return getdoc(self) + '\n' + merge_type_help()
2616
Option('show-base', help="Show base revision text in "
2618
Option('uncommitted', help='Apply uncommitted changes'
2619
' from a working copy, instead of branch changes'),
2620
Option('pull', help='If the destination is already'
2621
' completely merged into the source, pull from the'
2622
' source rather than merging. When this happens,'
2623
' you do not need to commit the result.'),
2625
help='Branch to merge into, '
2626
'rather than the one containing the working directory',
2132
2632
def run(self, branch=None, revision=None, force=False, merge_type=None,
2133
show_base=False, reprocess=False, remember=False,
2633
show_base=False, reprocess=False, remember=False,
2634
uncommitted=False, pull=False,
2637
from bzrlib.tag import _merge_tags_if_possible
2638
other_revision_id = None
2135
2639
if merge_type is None:
2136
merge_type = Merge3Merger
2640
merge_type = _mod_merge.Merge3Merger
2138
tree = WorkingTree.open_containing(u'.')[0]
2642
if directory is None: directory = u'.'
2643
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2644
# inventory. Because merge is a mutating operation, it really
2645
# should be a lock_write() for the whole cmd_merge operation.
2646
# However, cmd_merge open's its own tree in _merge_helper, which
2647
# means if we lock here, the later lock_write() will always block.
2648
# Either the merge helper code should be updated to take a tree,
2649
# (What about tree.merge_from_branch?)
2650
tree = WorkingTree.open_containing(directory)[0]
2651
change_reporter = delta._ChangeReporter(
2652
unversioned_filter=tree.is_ignored)
2140
2654
if branch is not None:
2142
reader = bundle.read_bundle_from_url(branch)
2656
mergeable = bundle.read_mergeable_from_url(
2658
except errors.NotABundle:
2144
2659
pass # Continue on considering this url a Branch
2146
conflicts = merge_bundle(reader, tree, not force, merge_type,
2147
reprocess, show_base)
2661
if revision is not None:
2662
raise errors.BzrCommandError(
2663
'Cannot use -r with merge directives or bundles')
2664
other_revision_id = mergeable.install_revisions(
2665
tree.branch.repository)
2666
revision = [RevisionSpec.from_string(
2667
'revid:' + other_revision_id)]
2153
2669
if revision is None \
2154
2670
or len(revision) < 1 or revision[0].needs_branch():
2618
3175
if to_revid is None:
2619
3176
to_revno = b.revno()
2620
3177
if from_revno is None or to_revno is None:
2621
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3178
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2622
3179
for revno in range(from_revno, to_revno + 1):
2623
3180
b.repository.sign_revision(b.get_rev_id(revno),
2626
raise BzrCommandError('Please supply either one revision, or a range.')
3183
raise errors.BzrCommandError('Please supply either one revision, or a range.')
2629
3186
class cmd_bind(Command):
2630
"""Bind the current branch to a master branch.
3187
"""Convert the current branch into a checkout of the supplied branch.
2632
After binding, commits must succeed on the master branch
2633
before they are executed on the local one.
3189
Once converted into a checkout, commits must succeed on the master branch
3190
before they will be applied to the local branch.
2636
takes_args = ['location']
3193
_see_also = ['checkouts', 'unbind']
3194
takes_args = ['location?']
2637
3195
takes_options = []
2639
3197
def run(self, location=None):
2640
3198
b, relpath = Branch.open_containing(u'.')
3199
if location is None:
3201
location = b.get_old_bound_location()
3202
except errors.UpgradeRequired:
3203
raise errors.BzrCommandError('No location supplied. '
3204
'This format does not remember old locations.')
3206
if location is None:
3207
raise errors.BzrCommandError('No location supplied and no '
3208
'previous location known')
2641
3209
b_other = Branch.open(location)
2643
3211
b.bind(b_other)
2644
except DivergedBranches:
2645
raise BzrCommandError('These branches have diverged.'
2646
' Try merging, and then bind again.')
3212
except errors.DivergedBranches:
3213
raise errors.BzrCommandError('These branches have diverged.'
3214
' Try merging, and then bind again.')
2649
3217
class cmd_unbind(Command):
2650
"""Unbind the current branch from its master branch.
3218
"""Convert the current checkout into a regular branch.
2652
After unbinding, the local branch is considered independent.
2653
All subsequent commits will be local.
3220
After unbinding, the local branch is considered independent and subsequent
3221
commits will be local only.
3224
_see_also = ['checkouts', 'bind']
2656
3225
takes_args = []
2657
3226
takes_options = []
2660
3229
b, relpath = Branch.open_containing(u'.')
2661
3230
if not b.unbind():
2662
raise BzrCommandError('Local branch is not bound')
3231
raise errors.BzrCommandError('Local branch is not bound')
2665
3234
class cmd_uncommit(Command):
3340
class cmd_wait_until_signalled(Command):
3341
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3343
This just prints a line to signal when it is ready, then blocks on stdin.
3349
sys.stdout.write("running\n")
3351
sys.stdin.readline()
3354
class cmd_serve(Command):
3355
"""Run the bzr server."""
3357
aliases = ['server']
3361
help='serve on stdin/out for use from inetd or sshd'),
3363
help='listen for connections on nominated port of the form '
3364
'[hostname:]portnumber. Passing 0 as the port number will '
3365
'result in a dynamically allocated port. Default port is '
3369
help='serve contents of directory',
3371
Option('allow-writes',
3372
help='By default the server is a readonly server. Supplying '
3373
'--allow-writes enables write access to the contents of '
3374
'the served directory and below. '
3378
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3379
from bzrlib.smart import medium, server
3380
from bzrlib.transport import get_transport
3381
from bzrlib.transport.chroot import ChrootServer
3382
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3383
if directory is None:
3384
directory = os.getcwd()
3385
url = urlutils.local_path_to_url(directory)
3386
if not allow_writes:
3387
url = 'readonly+' + url
3388
chroot_server = ChrootServer(get_transport(url))
3389
chroot_server.setUp()
3390
t = get_transport(chroot_server.get_url())
3392
smart_server = medium.SmartServerPipeStreamMedium(
3393
sys.stdin, sys.stdout, t)
3395
host = BZR_DEFAULT_INTERFACE
3397
port = BZR_DEFAULT_PORT
3400
host, port = port.split(':')
3402
smart_server = server.SmartTCPServer(t, host=host, port=port)
3403
print 'listening on port: ', smart_server.port
3405
# for the duration of this server, no UI output is permitted.
3406
# note that this may cause problems with blackbox tests. This should
3407
# be changed with care though, as we dont want to use bandwidth sending
3408
# progress over stderr to smart server clients!
3409
old_factory = ui.ui_factory
3411
ui.ui_factory = ui.SilentUIFactory()
3412
smart_server.serve()
3414
ui.ui_factory = old_factory
3417
class cmd_join(Command):
3418
"""Combine a subtree into its containing tree.
3420
This command is for experimental use only. It requires the target tree
3421
to be in dirstate-with-subtree format, which cannot be converted into
3424
The TREE argument should be an independent tree, inside another tree, but
3425
not part of it. (Such trees can be produced by "bzr split", but also by
3426
running "bzr branch" with the target inside a tree.)
3428
The result is a combined tree, with the subtree no longer an independant
3429
part. This is marked as a merge of the subtree into the containing tree,
3430
and all history is preserved.
3432
If --reference is specified, the subtree retains its independence. It can
3433
be branched by itself, and can be part of multiple projects at the same
3434
time. But operations performed in the containing tree, such as commit
3435
and merge, will recurse into the subtree.
3438
_see_also = ['split']
3439
takes_args = ['tree']
3440
takes_options = [Option('reference', 'join by reference')]
3443
def run(self, tree, reference=False):
3444
sub_tree = WorkingTree.open(tree)
3445
parent_dir = osutils.dirname(sub_tree.basedir)
3446
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3447
repo = containing_tree.branch.repository
3448
if not repo.supports_rich_root():
3449
raise errors.BzrCommandError(
3450
"Can't join trees because %s doesn't support rich root data.\n"
3451
"You can use bzr upgrade on the repository."
3455
containing_tree.add_reference(sub_tree)
3456
except errors.BadReferenceTarget, e:
3457
# XXX: Would be better to just raise a nicely printable
3458
# exception from the real origin. Also below. mbp 20070306
3459
raise errors.BzrCommandError("Cannot join %s. %s" %
3463
containing_tree.subsume(sub_tree)
3464
except errors.BadSubsumeSource, e:
3465
raise errors.BzrCommandError("Cannot join %s. %s" %
3469
class cmd_split(Command):
3470
"""Split a tree into two trees.
3472
This command is for experimental use only. It requires the target tree
3473
to be in dirstate-with-subtree format, which cannot be converted into
3476
The TREE argument should be a subdirectory of a working tree. That
3477
subdirectory will be converted into an independent tree, with its own
3478
branch. Commits in the top-level tree will not apply to the new subtree.
3479
If you want that behavior, do "bzr join --reference TREE".
3482
_see_also = ['join']
3483
takes_args = ['tree']
3487
def run(self, tree):
3488
containing_tree, subdir = WorkingTree.open_containing(tree)
3489
sub_id = containing_tree.path2id(subdir)
3491
raise errors.NotVersionedError(subdir)
3493
containing_tree.extract(sub_id)
3494
except errors.RootNotRich:
3495
raise errors.UpgradeRequired(containing_tree.branch.base)
3499
class cmd_merge_directive(Command):
3500
"""Generate a merge directive for auto-merge tools.
3502
A directive requests a merge to be performed, and also provides all the
3503
information necessary to do so. This means it must either include a
3504
revision bundle, or the location of a branch containing the desired
3507
A submit branch (the location to merge into) must be supplied the first
3508
time the command is issued. After it has been supplied once, it will
3509
be remembered as the default.
3511
A public branch is optional if a revision bundle is supplied, but required
3512
if --diff or --plain is specified. It will be remembered as the default
3513
after the first use.
3516
takes_args = ['submit_branch?', 'public_branch?']
3519
RegistryOption.from_kwargs('patch-type',
3520
'The type of patch to include in the directive',
3521
title='Patch type', value_switches=True, enum_switch=False,
3522
bundle='Bazaar revision bundle (default)',
3523
diff='Normal unified diff',
3524
plain='No patch, just directive'),
3525
Option('sign', help='GPG-sign the directive'), 'revision',
3526
Option('mail-to', type=str,
3527
help='Instead of printing the directive, email to this address'),
3528
Option('message', type=str, short_name='m',
3529
help='Message to use when committing this merge')
3532
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3533
sign=False, revision=None, mail_to=None, message=None):
3534
if patch_type == 'plain':
3536
branch = Branch.open('.')
3537
stored_submit_branch = branch.get_submit_branch()
3538
if submit_branch is None:
3539
submit_branch = stored_submit_branch
3541
if stored_submit_branch is None:
3542
branch.set_submit_branch(submit_branch)
3543
if submit_branch is None:
3544
submit_branch = branch.get_parent()
3545
if submit_branch is None:
3546
raise errors.BzrCommandError('No submit branch specified or known')
3548
stored_public_branch = branch.get_public_branch()
3549
if public_branch is None:
3550
public_branch = stored_public_branch
3551
elif stored_public_branch is None:
3552
branch.set_public_branch(public_branch)
3553
if patch_type != "bundle" and public_branch is None:
3554
raise errors.BzrCommandError('No public branch specified or'
3556
if revision is not None:
3557
if len(revision) != 1:
3558
raise errors.BzrCommandError('bzr merge-directive takes '
3559
'exactly one revision identifier')
3561
revision_id = revision[0].in_history(branch).rev_id
3563
revision_id = branch.last_revision()
3564
directive = merge_directive.MergeDirective.from_objects(
3565
branch.repository, revision_id, time.time(),
3566
osutils.local_time_offset(), submit_branch,
3567
public_branch=public_branch, patch_type=patch_type,
3571
self.outf.write(directive.to_signed(branch))
3573
self.outf.writelines(directive.to_lines())
3575
message = directive.to_email(mail_to, branch, sign)
3577
server = branch.get_config().get_user_option('smtp_server')
3579
server = 'localhost'
3581
s.sendmail(message['From'], message['To'], message.as_string())
3584
class cmd_tag(Command):
3585
"""Create a tag naming a revision.
3587
Tags give human-meaningful names to revisions. Commands that take a -r
3588
(--revision) option can be given -rtag:X, where X is any previously
3591
Tags are stored in the branch. Tags are copied from one branch to another
3592
along when you branch, push, pull or merge.
3594
It is an error to give a tag name that already exists unless you pass
3595
--force, in which case the tag is moved to point to the new revision.
3598
_see_also = ['commit', 'tags']
3599
takes_args = ['tag_name']
3602
help='Delete this tag rather than placing it.',
3605
help='Branch in which to place the tag.',
3610
help='Replace existing tags',
3615
def run(self, tag_name,
3621
branch, relpath = Branch.open_containing(directory)
3625
branch.tags.delete_tag(tag_name)
3626
self.outf.write('Deleted tag %s.\n' % tag_name)
3629
if len(revision) != 1:
3630
raise errors.BzrCommandError(
3631
"Tags can only be placed on a single revision, "
3633
revision_id = revision[0].in_history(branch).rev_id
3635
revision_id = branch.last_revision()
3636
if (not force) and branch.tags.has_tag(tag_name):
3637
raise errors.TagAlreadyExists(tag_name)
3638
branch.tags.set_tag(tag_name, revision_id)
3639
self.outf.write('Created tag %s.\n' % tag_name)
3644
class cmd_tags(Command):
3647
This tag shows a table of tag names and the revisions they reference.
3653
help='Branch whose tags should be displayed',
3663
branch, relpath = Branch.open_containing(directory)
3664
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3665
self.outf.write('%-20s %s\n' % (tag_name, target))
2771
3668
# command-line interpretation helper for merge-related commands
2772
def merge(other_revision, base_revision,
2773
check_clean=True, ignore_zero=False,
2774
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2775
file_list=None, show_base=False, reprocess=False,
2776
pb=DummyProgress()):
3669
def _merge_helper(other_revision, base_revision,
3670
check_clean=True, ignore_zero=False,
3671
this_dir=None, backup_files=False,
3673
file_list=None, show_base=False, reprocess=False,
3676
change_reporter=None,
2777
3678
"""Merge changes into a tree.
2801
3702
clients might prefer to call merge.merge_inner(), which has less magic
2804
from bzrlib.merge import Merger
3705
# Loading it late, so that we don't always have to import bzrlib.merge
3706
if merge_type is None:
3707
merge_type = _mod_merge.Merge3Merger
2805
3708
if this_dir is None:
2806
3709
this_dir = u'.'
2807
3710
this_tree = WorkingTree.open_containing(this_dir)[0]
2808
if show_base and not merge_type is Merge3Merger:
2809
raise BzrCommandError("Show-base is not supported for this merge"
2810
" type. %s" % merge_type)
3711
if show_base and not merge_type is _mod_merge.Merge3Merger:
3712
raise errors.BzrCommandError("Show-base is not supported for this merge"
3713
" type. %s" % merge_type)
2811
3714
if reprocess and not merge_type.supports_reprocess:
2812
raise BzrCommandError("Conflict reduction is not supported for merge"
2813
" type %s." % merge_type)
3715
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3716
" type %s." % merge_type)
2814
3717
if reprocess and show_base:
2815
raise BzrCommandError("Cannot do conflict reduction and show base.")
3718
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3719
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3720
# only want to take out a lock_tree_write() if we don't have to pull
3721
# any ancestry. But merge might fetch ancestry in the middle, in
3722
# which case we would need a lock_write().
3723
# Because we cannot upgrade locks, for now we live with the fact that
3724
# the tree will be locked multiple times during a merge. (Maybe
3725
# read-only some of the time, but it means things will get read
2817
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
3728
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3729
pb=pb, change_reporter=change_reporter)
2818
3730
merger.pp = ProgressPhase("Merge phase", 5, pb)
2819
3731
merger.pp.next_phase()
2820
3732
merger.check_basis(check_clean)
2821
merger.set_other(other_revision)
3733
if other_rev_id is not None:
3734
merger.set_other_revision(other_rev_id, this_tree.branch)
3736
merger.set_other(other_revision)
2822
3737
merger.pp.next_phase()
2823
3738
merger.set_base(base_revision)
2824
3739
if merger.base_rev_id == merger.other_rev_id:
2825
3740
note('Nothing to do.')
3742
if file_list is None:
3743
if pull and merger.base_rev_id == merger.this_rev_id:
3744
# FIXME: deduplicate with pull
3745
result = merger.this_tree.pull(merger.this_branch,
3746
False, merger.other_rev_id)
3747
if result.old_revid == result.new_revid:
3748
note('No revisions to pull.')
3750
note('Now on revision %d.' % result.new_revno)
2827
3752
merger.backup_files = backup_files
2828
3753
merger.merge_type = merge_type
2829
3754
merger.set_interesting_files(file_list)