17
17
"""builtin bzr commands"""
20
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
32
27
from bzrlib import (
53
from bzrlib.branch import Branch
41
from bzrlib.branch import Branch, BranchReferenceFormat
42
from bzrlib.bundle import read_bundle_from_url
54
43
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
55
44
from bzrlib.conflicts import ConflictList
45
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
52
from bzrlib.progress import DummyProgress, ProgressPhase
56
53
from bzrlib.revision import common_ancestor
57
54
from bzrlib.revisionspec import RevisionSpec
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
56
from bzrlib.transport.local import LocalTransport
58
57
from bzrlib.workingtree import WorkingTree
61
from bzrlib.commands import Command, display_command
62
from bzrlib.option import Option, RegistryOption
63
from bzrlib.progress import DummyProgress, ProgressPhase
64
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
67
60
def tree_files(file_list, default_branch=u'.'):
69
62
return internal_tree_files(file_list, default_branch)
70
except errors.FileInWrongBranch, e:
71
raise errors.BzrCommandError("%s is not in the same branch as %s" %
72
(e.path, file_list[0]))
63
except FileInWrongBranch, e:
64
raise BzrCommandError("%s is not in the same branch as %s" %
65
(e.path, file_list[0]))
75
68
# XXX: Bad function name; should possibly also be a class method of
85
78
:param file_list: Filenames to convert.
87
:param default_branch: Fallback tree path to use if file_list is empty or
80
:param default_branch: Fallback tree path to use if file_list is empty or None.
90
82
:return: workingtree, [relative_paths]
92
84
if file_list is None or len(file_list) == 0:
93
85
return WorkingTree.open_containing(default_branch)[0], file_list
94
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
86
tree = WorkingTree.open_containing(file_list[0])[0]
96
88
for filename in file_list:
98
new_list.append(tree.relpath(osutils.dereference_path(filename)))
90
new_list.append(tree.relpath(filename))
99
91
except errors.PathNotChild:
100
raise errors.FileInWrongBranch(tree.branch, filename)
92
raise FileInWrongBranch(tree.branch, filename)
101
93
return tree, new_list
104
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
105
96
def get_format_type(typestring):
106
97
"""Parse and return a format specifier."""
107
# Have to use BzrDirMetaFormat1 directly, so that
108
# RepositoryFormat.set_default_format works
98
if typestring == "weave":
99
return bzrdir.BzrDirFormat6()
109
100
if typestring == "default":
110
101
return bzrdir.BzrDirMetaFormat1()
112
return bzrdir.format_registry.make_bzrdir(typestring)
114
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
115
raise errors.BzrCommandError(msg)
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)
118
119
# TODO: Make sure no commands unconditionally use the working directory as a
432
361
"""Show inventory of the current working copy or a revision.
434
363
It is possible to limit the output to a particular entry
435
type using the --kind option. For example: --kind file.
437
It is also possible to restrict the list of files to a specific
438
set. For example: bzr inventory --show-ids this/file
364
type using the --kind option. For example; --kind file.
445
367
takes_options = ['revision', 'show-ids', 'kind']
447
takes_args = ['file*']
450
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
370
def run(self, revision=None, show_ids=False, kind=None):
451
371
if kind and kind not in ['file', 'directory', 'symlink']:
452
raise errors.BzrCommandError('invalid kind specified')
454
work_tree, file_list = tree_files(file_list)
455
work_tree.lock_read()
457
if revision is not None:
458
if len(revision) > 1:
459
raise errors.BzrCommandError(
460
'bzr inventory --revision takes exactly one revision'
462
revision_id = revision[0].in_history(work_tree.branch).rev_id
463
tree = work_tree.branch.repository.revision_tree(revision_id)
465
extra_trees = [work_tree]
471
if file_list is not None:
472
file_ids = tree.paths2ids(file_list, trees=extra_trees,
473
require_versioned=True)
474
# find_ids_across_trees may include some paths that don't
476
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
477
for file_id in file_ids if file_id in tree)
479
entries = tree.inventory.entries()
482
if tree is not work_tree:
485
for path, entry in entries:
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():
486
384
if kind and kind != entry.kind:
502
400
If the last argument is a versioned directory, all the other names
503
401
are moved into it. Otherwise, there must be exactly two arguments
504
and the file is changed to a new name.
506
If OLDNAME does not exist on the filesystem but is versioned and
507
NEWNAME does exist on the filesystem but is not versioned, mv
508
assumes that the file has been manually moved and only updates
509
its internal inventory to reflect that change.
510
The same is valid when moving many SOURCE files to a DESTINATION.
402
and the file is changed to a new name, which must not already exist.
512
404
Files cannot be moved between branches.
515
407
takes_args = ['names*']
516
takes_options = [Option("after", help="move only the bzr identifier"
517
" of the file (file has already been moved). Use this flag if"
518
" bzr is not able to detect this itself.")]
519
408
aliases = ['move', 'rename']
520
409
encoding_type = 'replace'
522
def run(self, names_list, after=False):
411
def run(self, names_list):
523
412
if names_list is None:
526
415
if len(names_list) < 2:
527
raise errors.BzrCommandError("missing file argument")
416
raise BzrCommandError("missing file argument")
528
417
tree, rel_names = tree_files(names_list)
530
419
if os.path.isdir(names_list[-1]):
531
420
# move into existing directory
532
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
421
for pair in tree.move(rel_names[:-1], rel_names[-1]):
533
422
self.outf.write("%s => %s\n" % pair)
535
424
if len(names_list) != 2:
536
raise errors.BzrCommandError('to mv multiple files the'
537
' destination must be a versioned'
539
tree.rename_one(rel_names[0], rel_names[1], after=after)
425
raise BzrCommandError('to mv multiple files the destination '
426
'must be a versioned directory')
427
tree.rename_one(rel_names[0], rel_names[1])
540
428
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
560
448
location can be accessed.
563
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
565
help='branch to pull into, '
566
'rather than the one containing the working directory',
451
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
571
452
takes_args = ['location?']
572
453
encoding_type = 'replace'
574
def run(self, location=None, remember=False, overwrite=False,
575
revision=None, verbose=False,
577
from bzrlib.tag import _merge_tags_if_possible
455
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
578
456
# FIXME: too much stuff is in the command class
581
if directory is None:
584
tree_to = WorkingTree.open_containing(directory)[0]
458
tree_to = WorkingTree.open_containing(u'.')[0]
585
459
branch_to = tree_to.branch
586
except errors.NoWorkingTree:
460
except NoWorkingTree:
588
branch_to = Branch.open_containing(directory)[0]
462
branch_to = Branch.open_containing(u'.')[0]
591
465
if location is not None:
593
mergeable = bundle.read_mergeable_from_url(
595
except errors.NotABundle:
467
reader = bundle.read_bundle_from_url(location)
596
469
pass # Continue on considering this url a Branch
598
471
stored_loc = branch_to.get_parent()
599
472
if location is None:
600
473
if stored_loc is None:
601
raise errors.BzrCommandError("No pull location known or"
474
raise BzrCommandError("No pull location known or specified.")
604
476
display_url = urlutils.unescape_for_display(stored_loc,
605
477
self.outf.encoding)
606
478
self.outf.write("Using saved location: %s\n" % display_url)
607
479
location = stored_loc
609
if mergeable is not None:
610
if revision is not None:
611
raise errors.BzrCommandError(
612
'Cannot use -r with merge directives or bundles')
613
revision_id = mergeable.install_revisions(branch_to.repository)
482
if reader is not None:
483
install_bundle(branch_to.repository, reader)
614
484
branch_from = branch_to
616
486
branch_from = Branch.open(location)
707
565
to_transport = transport.get_transport(location)
708
566
location_url = to_transport.base
710
br_to = repository_to = dir_to = None
712
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
713
except errors.NotBranchError:
714
pass # Didn't find anything
716
# If we can open a branch, use its direct repository, otherwise see
717
# if there is a repository without a branch.
719
br_to = dir_to.open_branch()
720
except errors.NotBranchError:
721
# Didn't find a branch, can we find a repository?
723
repository_to = dir_to.find_repository()
724
except errors.NoRepositoryPresent:
727
# Found a branch, so we must have found a repository
728
repository_to = br_to.repository
732
# The destination doesn't exist; create it.
733
# XXX: Refactor the create_prefix/no_create_prefix code into a
734
# common helper function
736
to_transport.mkdir('.')
737
except errors.FileExists:
738
if not use_existing_dir:
739
raise errors.BzrCommandError("Target directory %s"
740
" already exists, but does not have a valid .bzr"
741
" directory. Supply --use-existing-dir to push"
742
" there anyway." % location)
743
except errors.NoSuchFile:
744
if not create_prefix:
745
raise errors.BzrCommandError("Parent directory of %s"
747
"\nYou may supply --create-prefix to create all"
748
" leading parent directories."
751
cur_transport = to_transport
752
needed = [cur_transport]
753
# Recurse upwards until we can create a directory successfully
755
new_transport = cur_transport.clone('..')
756
if new_transport.base == cur_transport.base:
757
raise errors.BzrCommandError("Failed to create path"
761
new_transport.mkdir('.')
762
except errors.NoSuchFile:
763
needed.append(new_transport)
764
cur_transport = new_transport
768
# Now we only need to create child directories
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))]
770
cur_transport = needed.pop()
771
cur_transport.mkdir('.')
773
# Now the target directory exists, but doesn't have a .bzr
774
# directory. So we need to create it, along with any work to create
775
# all of the dependent branches, etc.
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 "
776
598
dir_to = br_from.bzrdir.clone(location_url,
777
599
revision_id=br_from.last_revision())
778
600
br_to = dir_to.open_branch()
779
# TODO: Some more useful message about what was copied
780
note('Created new branch.')
601
count = len(br_to.revision_history())
781
602
# We successfully created the target, remember it
782
603
if br_from.get_push_location() is None or remember:
783
604
br_from.set_push_location(br_to.base)
784
elif repository_to is None:
785
# we have a bzrdir but no branch or repository
786
# XXX: Figure out what to do other than complain.
787
raise errors.BzrCommandError("At %s you have a valid .bzr control"
788
" directory, but not a branch or repository. This is an"
789
" unsupported configuration. Please move the target directory"
790
" out of the way and try again."
793
# We have a repository but no branch, copy the revisions, and then
795
last_revision_id = br_from.last_revision()
796
repository_to.fetch(br_from.repository,
797
revision_id=last_revision_id)
798
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
799
note('Created new branch.')
800
if br_from.get_push_location() is None or remember:
801
br_from.set_push_location(br_to.base)
802
else: # We have a valid to branch
803
606
# We were able to connect to the remote location, so remember it
804
607
# we don't need to successfully push because of possible divergence.
805
608
if br_from.get_push_location() is None or remember:
1259
1059
existing_bzrdir = bzrdir.BzrDir.open(location)
1260
except errors.NotBranchError:
1060
except NotBranchError:
1261
1061
# really a NotBzrDir error...
1262
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1062
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1265
from bzrlib.transport.local import LocalTransport
1266
1064
if existing_bzrdir.has_branch():
1267
1065
if (isinstance(to_transport, LocalTransport)
1268
1066
and not existing_bzrdir.has_workingtree()):
1269
1067
raise errors.BranchExistsWithoutWorkingTree(location)
1270
1068
raise errors.AlreadyBranchError(location)
1272
branch = existing_bzrdir.create_branch()
1070
existing_bzrdir.create_branch()
1273
1071
existing_bzrdir.create_workingtree()
1274
if append_revisions_only:
1276
branch.set_append_revisions_only(True)
1277
except errors.UpgradeRequired:
1278
raise errors.BzrCommandError('This branch format cannot be set'
1279
' to append-revisions-only. Try --experimental-branch6')
1282
1074
class cmd_init_repository(Command):
1283
1075
"""Create a shared repository to hold branches.
1285
1077
New branches created under the repository directory will store their revisions
1286
in the repository, not in the branch directory.
1078
in the repository, not in the branch directory, if the branch format supports
1289
bzr init-repo --no-trees repo
1290
1083
bzr init repo/trunk
1291
1084
bzr checkout --lightweight repo/trunk trunk-checkout
1292
1085
cd trunk-checkout
1293
1086
(add files here)
1296
takes_args = ["location"]
1297
takes_options = [RegistryOption('format',
1298
help='Specify a format for this repository. See'
1299
' "bzr help formats" for details',
1300
registry=bzrdir.format_registry,
1301
converter=bzrdir.format_registry.make_bzrdir,
1302
value_switches=True, title='Repository format'),
1304
help='Branches in the repository will default to'
1305
' not having a working tree'),
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'
1307
1098
aliases = ["init-repo"]
1309
def run(self, location, format=None, no_trees=False):
1099
def run(self, location, format=None, trees=False):
1310
1100
if format is None:
1311
format = bzrdir.format_registry.make_bzrdir('default')
1101
format = get_format_type('default')
1313
1103
if location is None:
1415
1194
tree1, tree2 = None, None
1419
if tree2 is not None:
1420
if revision is not None:
1421
# FIXME: but there should be a clean way to diff between
1422
# non-default versions of two trees, it's not hard to do
1424
raise errors.BzrCommandError(
1425
"Sorry, diffing arbitrary revisions across branches "
1426
"is not implemented yet")
1427
return show_diff_trees(tree1, tree2, sys.stdout,
1428
specific_files=file_list,
1429
external_diff_options=diff_options,
1430
old_label=old_label, new_label=new_label)
1432
return diff_cmd_helper(tree1, file_list, diff_options,
1433
revision_specs=revision,
1434
old_label=old_label, new_label=new_label)
1197
if revision is not None:
1198
if tree2 is not None:
1199
raise BzrCommandError("Can't specify -r with two branches")
1200
if (len(revision) == 1) or (revision[1].spec is None):
1201
return diff_cmd_helper(tree1, file_list, diff_options,
1203
old_label=old_label, new_label=new_label)
1204
elif len(revision) == 2:
1205
return diff_cmd_helper(tree1, file_list, diff_options,
1206
revision[0], revision[1],
1207
old_label=old_label, new_label=new_label)
1209
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1211
if tree2 is not None:
1212
return show_diff_trees(tree1, tree2, sys.stdout,
1213
specific_files=file_list,
1214
external_diff_options=diff_options,
1215
old_label=old_label, new_label=new_label)
1217
return diff_cmd_helper(tree1, file_list, diff_options,
1218
old_label=old_label, new_label=new_label)
1437
1221
class cmd_deleted(Command):
1600
1358
dir, relpath = bzrdir.BzrDir.open_containing(location)
1601
1359
b = dir.open_branch()
1605
if revision is None:
1608
elif len(revision) == 1:
1609
rev1 = rev2 = revision[0].in_history(b).revno
1610
elif len(revision) == 2:
1611
if revision[1].get_branch() != revision[0].get_branch():
1612
# b is taken from revision[0].get_branch(), and
1613
# show_log will use its revision_history. Having
1614
# different branches will lead to weird behaviors.
1615
raise errors.BzrCommandError(
1616
"Log doesn't accept two revisions in different"
1618
if revision[0].spec is None:
1619
# missing begin-range means first revision
1622
rev1 = revision[0].in_history(b).revno
1624
if revision[1].spec is None:
1625
# missing end-range means last known revision
1628
rev2 = revision[1].in_history(b).revno
1630
raise errors.BzrCommandError(
1631
'bzr log --revision takes one or two values.')
1633
# By this point, the revision numbers are converted to the +ve
1634
# form if they were supplied in the -ve form, so we can do
1635
# this comparison in relative safety
1637
(rev2, rev1) = (rev1, rev2)
1639
if log_format is None:
1640
log_format = log.log_formatter_registry.get_default(b)
1642
lf = log_format(show_ids=show_ids, to_file=self.outf,
1643
show_timezone=timezone)
1649
direction=direction,
1650
start_revision=rev1,
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,
1657
1412
def get_log_format(long=False, short=False, line=False, default='long'):
1699
1454
Option('ignored', help='Print ignored files'),
1701
1456
Option('null', help='Null separate the files'),
1704
1458
@display_command
1705
1459
def run(self, revision=None, verbose=False,
1706
1460
non_recursive=False, from_root=False,
1707
1461
unknown=False, versioned=False, ignored=False,
1708
null=False, kind=None, show_ids=False, path=None):
1710
if kind and kind not in ('file', 'directory', 'symlink'):
1711
raise errors.BzrCommandError('invalid kind specified')
1713
1464
if verbose and null:
1714
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1465
raise BzrCommandError('Cannot set both --verbose and --null')
1715
1466
all = not (unknown or versioned or ignored)
1717
1468
selection = {'I':ignored, '?':unknown, 'V':versioned}
1724
raise errors.BzrCommandError('cannot specify both --from-root'
1728
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1470
tree, relpath = WorkingTree.open_containing(u'.')
1734
1475
if revision is not None:
1735
tree = branch.repository.revision_tree(
1736
revision[0].in_history(branch).rev_id)
1738
tree = branch.basis_tree()
1476
tree = tree.branch.repository.revision_tree(
1477
revision[0].in_history(tree.branch).rev_id)
1742
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1743
if fp.startswith(relpath):
1744
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1745
if non_recursive and '/' in fp:
1747
if not all and not selection[fc]:
1749
if kind is not None and fkind != kind:
1752
kindch = entry.kind_character()
1753
outstring = '%-8s %s%s' % (fc, fp, kindch)
1754
if show_ids and fid is not None:
1755
outstring = "%-50s %s" % (outstring, fid)
1756
self.outf.write(outstring + '\n')
1758
self.outf.write(fp + '\0')
1761
self.outf.write(fid)
1762
self.outf.write('\0')
1770
self.outf.write('%-50s %s\n' % (fp, my_id))
1772
self.outf.write(fp + '\n')
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')
1777
1496
class cmd_unknowns(Command):
1778
"""List unknown files.
1780
See also: "bzr ls --unknown".
1497
"""List unknown files."""
1785
1498
@display_command
1787
1500
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1791
1504
class cmd_ignore(Command):
1792
"""Ignore specified files or patterns.
1505
"""Ignore a command or pattern.
1794
1507
To remove patterns from the ignore list, edit the .bzrignore file.
1796
Trailing slashes on patterns are ignored.
1797
If the pattern contains a slash or is a regular expression, it is compared
1798
to the whole path from the branch root. Otherwise, it is compared to only
1799
the last component of the path. To match a file only in the root
1800
directory, prepend './'.
1802
Ignore patterns specifying absolute paths are not allowed.
1804
Ignore patterns may include globbing wildcards such as:
1805
? - Matches any single character except '/'
1806
* - Matches 0 or more characters except '/'
1807
/**/ - Matches 0 or more directories in a path
1808
[a-z] - Matches a single character from within a group of characters
1810
Ignore patterns may also be Python regular expressions.
1811
Regular expression ignore patterns are identified by a 'RE:' prefix
1812
followed by the regular expression. Regular expression ignore patterns
1813
may not include named or numbered groups.
1815
Note: ignore patterns containing shell wildcards must be quoted from
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.
1819
1519
bzr ignore ./Makefile
1820
1520
bzr ignore '*.class'
1821
bzr ignore 'lib/**/*.o'
1822
bzr ignore 'RE:lib/.*\.o'
1824
takes_args = ['name_pattern*']
1522
# TODO: Complain if the filename is absolute
1523
takes_args = ['name_pattern?']
1825
1524
takes_options = [
1826
1525
Option('old-default-rules',
1827
1526
help='Out the ignore rules bzr < 0.9 always used.')
1830
def run(self, name_pattern_list=None, old_default_rules=None):
1529
def run(self, name_pattern=None, old_default_rules=None):
1831
1530
from bzrlib.atomicfile import AtomicFile
1832
1531
if old_default_rules is not None:
1833
1532
# dump the rules and exit
1834
1533
for pattern in ignores.OLD_DEFAULTS:
1837
if not name_pattern_list:
1838
raise errors.BzrCommandError("ignore requires at least one "
1839
"NAME_PATTERN or --old-default-rules")
1840
name_pattern_list = [globbing.normalize_pattern(p)
1841
for p in name_pattern_list]
1842
for name_pattern in name_pattern_list:
1843
if (name_pattern[0] == '/' or
1844
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1845
raise errors.BzrCommandError(
1846
"NAME_PATTERN should not be an absolute path")
1536
if name_pattern is None:
1537
raise BzrCommandError("ignore requires a NAME_PATTERN")
1847
1538
tree, relpath = WorkingTree.open_containing(u'.')
1848
1539
ifn = tree.abspath('.bzrignore')
1849
1540
if os.path.exists(ifn):
1938
1624
tgz .tar.gz, .tgz
1941
takes_args = ['dest', 'branch?']
1627
takes_args = ['dest']
1942
1628
takes_options = ['revision', 'format', 'root']
1943
def run(self, dest, branch=None, revision=None, format=None, root=None):
1629
def run(self, dest, revision=None, format=None, root=None):
1944
1630
from bzrlib.export import export
1947
tree = WorkingTree.open_containing(u'.')[0]
1950
b = Branch.open(branch)
1631
tree = WorkingTree.open_containing(u'.')[0]
1952
1633
if revision is None:
1953
1634
# should be tree.last_revision FIXME
1954
1635
rev_id = b.last_revision()
1956
1637
if len(revision) != 1:
1957
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1638
raise BzrError('bzr export --revision takes exactly 1 argument')
1958
1639
rev_id = revision[0].in_history(b).rev_id
1959
1640
t = b.repository.revision_tree(rev_id)
1961
1642
export(t, dest, format, root)
1962
1643
except errors.NoSuchExportFormat, e:
1963
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1644
raise BzrCommandError('Unsupported export format: %s' % e.format)
1966
1647
class cmd_cat(Command):
1967
"""Write the contents of a file as of a given revision to standard output.
1969
If no revision is nominated, the last revision is used.
1971
Note: Take care to redirect standard output when using this command on a
1975
takes_options = ['revision', 'name-from-revision']
1648
"""Write a file's text from a previous revision."""
1650
takes_options = ['revision']
1976
1651
takes_args = ['filename']
1977
encoding_type = 'exact'
1979
1653
@display_command
1980
def run(self, filename, revision=None, name_from_revision=False):
1654
def run(self, filename, revision=None):
1981
1655
if revision is not None and len(revision) != 1:
1982
raise errors.BzrCommandError("bzr cat --revision takes exactly"
1656
raise BzrCommandError("bzr cat --revision takes exactly one number")
1987
tree, b, relpath = \
1988
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
1989
except errors.NotBranchError:
1659
tree, relpath = WorkingTree.open_containing(filename)
1661
except NotBranchError:
1665
b, relpath = Branch.open_containing(filename)
1992
1666
if revision is not None and revision[0].get_branch() is not None:
1993
1667
b = Branch.open(revision[0].get_branch())
1995
tree = b.basis_tree()
1996
1668
if revision is None:
1997
1669
revision_id = b.last_revision()
1999
1671
revision_id = revision[0].in_history(b).rev_id
2001
cur_file_id = tree.path2id(relpath)
2002
rev_tree = b.repository.revision_tree(revision_id)
2003
old_file_id = rev_tree.path2id(relpath)
2005
if name_from_revision:
2006
if old_file_id is None:
2007
raise errors.BzrCommandError("%r is not present in revision %s"
2008
% (filename, revision_id))
2010
rev_tree.print_file(old_file_id)
2011
elif cur_file_id is not None:
2012
rev_tree.print_file(cur_file_id)
2013
elif old_file_id is not None:
2014
rev_tree.print_file(old_file_id)
2016
raise errors.BzrCommandError("%r is not present in revision %s" %
2017
(filename, revision_id))
1672
b.print_file(relpath, revision_id)
2020
1675
class cmd_local_time_offset(Command):
2106
1749
if local and not tree.branch.get_bound_location():
2107
1750
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()
2109
def get_message(commit_obj):
2110
"""Callback to get commit message"""
2111
my_message = message
2112
if my_message is None and not file:
2113
template = make_commit_message_template(tree, selected_list)
2114
my_message = edit_commit_message(template)
2115
if my_message is None:
2116
raise errors.BzrCommandError("please specify a commit"
2117
" message with either --message or --file")
2118
elif my_message and file:
2119
raise errors.BzrCommandError(
2120
"please specify either --message or --file")
2122
my_message = codecs.open(file, 'rt',
2123
bzrlib.user_encoding).read()
2124
if my_message == "":
2125
raise errors.BzrCommandError("empty commit message specified")
1764
raise BzrCommandError("empty commit message specified")
2129
1767
reporter = ReportCommitToLog()
2131
1769
reporter = NullCommitReporter()
2134
tree.commit(message_callback=get_message,
2135
specific_files=selected_list,
1772
tree.commit(message, specific_files=selected_list,
2136
1773
allow_pointless=unchanged, strict=strict, local=local,
2137
1774
reporter=reporter)
2138
1775
except PointlessCommit:
2139
1776
# FIXME: This should really happen before the file is read in;
2140
1777
# perhaps prepare the commit; get the message; then actually commit
2141
raise errors.BzrCommandError("no changes to commit."
2142
" use --unchanged to commit anyhow")
1778
raise BzrCommandError("no changes to commit."
1779
" use --unchanged to commit anyhow")
2143
1780
except ConflictsInTree:
2144
raise errors.BzrCommandError('Conflicts detected in working '
2145
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1781
raise BzrCommandError("Conflicts detected in working tree. "
1782
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2147
1783
except StrictCommitFailed:
2148
raise errors.BzrCommandError("Commit refused because there are"
2149
" unknown files in the working tree.")
1784
raise BzrCommandError("Commit refused because there are unknown "
1785
"files in the working tree.")
2150
1786
except errors.BoundBranchOutOfDate, e:
2151
raise errors.BzrCommandError(str(e) + "\n"
2152
'To commit to master branch, run update and then commit.\n'
2153
'You can also pass --local to commit to continue working '
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 '
2157
1792
class cmd_check(Command):
2158
1793
"""Validate consistency of branch history.
2312
1953
return FakeNFSServer
2313
1954
msg = "No known transport type %s. Supported types are: sftp\n" %\
2315
raise errors.BzrCommandError(msg)
1956
raise BzrCommandError(msg)
2318
1959
takes_args = ['testspecs*']
2319
1960
takes_options = ['verbose',
2321
help='stop when one test fails',
2324
Option('keep-output',
1961
Option('one', help='stop when one test fails'),
1962
Option('keep-output',
2325
1963
help='keep output directories when tests fail'),
2327
1965
help='Use a different transport by default '
2328
1966
'throughout the test suite.',
2329
1967
type=get_transport_type),
2330
Option('benchmark', help='run the bzr benchmarks.'),
1968
Option('benchmark', help='run the bzr bencharks.'),
2331
1969
Option('lsprof-timed',
2332
1970
help='generate lsprof output for benchmarked'
2333
1971
' sections of code.'),
2334
1972
Option('cache-dir', type=str,
2335
1973
help='a directory to cache intermediate'
2336
1974
' benchmark steps'),
2337
Option('clean-output',
2338
help='clean temporary tests directories'
2339
' without running tests'),
2341
help='run all tests, but run specified tests first',
2344
Option('numbered-dirs',
2345
help='use numbered dirs for TestCaseInTempDir'),
2347
encoding_type = 'replace'
2349
1977
def run(self, testspecs_list=None, verbose=None, one=False,
2350
1978
keep_output=False, transport=None, benchmark=None,
2351
lsprof_timed=None, cache_dir=None, clean_output=False,
2352
first=False, numbered_dirs=None):
1979
lsprof_timed=None, cache_dir=None):
2353
1980
import bzrlib.ui
2354
1981
from bzrlib.tests import selftest
2355
1982
import bzrlib.benchmarks as benchmarks
2356
1983
from bzrlib.benchmarks import tree_creator
2359
from bzrlib.tests import clean_selftest_output
2360
clean_selftest_output()
2363
if numbered_dirs is None and sys.platform == 'win32':
2364
numbered_dirs = True
2366
1985
if cache_dir is not None:
2367
1986
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
2368
1991
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2369
1992
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2371
if testspecs_list is not None:
2372
pattern = '|'.join(testspecs_list)
2376
test_suite_factory = benchmarks.test_suite
2379
# TODO: should possibly lock the history file...
2380
benchfile = open(".perf_history", "at", buffering=1)
2382
test_suite_factory = None
1994
info('running tests...')
2387
result = selftest(verbose=verbose,
2389
stop_on_failure=one,
2390
keep_output=keep_output,
2391
transport=transport,
2392
test_suite_factory=test_suite_factory,
2393
lsprof_timed=lsprof_timed,
2394
bench_history=benchfile,
2395
matching_tests_first=first,
2396
numbered_dirs=numbered_dirs,
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)
2399
if benchfile is not None:
2402
info('tests passed')
2404
info('tests failed')
2405
return int(not result)
2029
ui.ui_factory = save_ui
2408
2032
class cmd_version(Command):
2474
2101
default, use --remember. The value will only be saved if the remote
2475
2102
location can be accessed.
2477
The results of the merge are placed into the destination working
2478
directory, where they can be reviewed (with bzr diff), tested, and then
2479
committed to record the result of the merge.
2483
To merge the latest revision from bzr.dev:
2484
bzr merge ../bzr.dev
2106
To merge the latest revision from bzr.dev
2107
bzr merge ../bzr.dev
2486
To merge changes up to and including revision 82 from bzr.dev:
2487
bzr merge -r 82 ../bzr.dev
2109
To merge changes up to and including revision 82 from bzr.dev
2110
bzr merge -r 82 ../bzr.dev
2489
2112
To merge the changes introduced by 82, without previous changes:
2490
bzr merge -r 81..82 ../bzr.dev
2113
bzr merge -r 81..82 ../bzr.dev
2492
2115
merge refuses to run if there are any uncommitted changes, unless
2493
2116
--force is given.
2118
The following merge types are available:
2495
2120
takes_args = ['branch?']
2496
2121
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2497
Option('show-base', help="Show base revision text in "
2499
Option('uncommitted', help='Apply uncommitted changes'
2500
' from a working copy, instead of branch changes'),
2501
Option('pull', help='If the destination is already'
2502
' completely merged into the source, pull from the'
2503
' source rather than merging. When this happens,'
2504
' you do not need to commit the result.'),
2506
help='Branch to merge into, '
2507
'rather than the one containing the working directory',
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()
2513
2132
def run(self, branch=None, revision=None, force=False, merge_type=None,
2514
show_base=False, reprocess=False, remember=False,
2515
uncommitted=False, pull=False,
2518
from bzrlib.tag import _merge_tags_if_possible
2519
other_revision_id = None
2133
show_base=False, reprocess=False, remember=False,
2520
2135
if merge_type is None:
2521
merge_type = _mod_merge.Merge3Merger
2136
merge_type = Merge3Merger
2523
if directory is None: directory = u'.'
2524
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2525
# inventory. Because merge is a mutating operation, it really
2526
# should be a lock_write() for the whole cmd_merge operation.
2527
# However, cmd_merge open's its own tree in _merge_helper, which
2528
# means if we lock here, the later lock_write() will always block.
2529
# Either the merge helper code should be updated to take a tree,
2530
# (What about tree.merge_from_branch?)
2531
tree = WorkingTree.open_containing(directory)[0]
2532
change_reporter = delta._ChangeReporter(
2533
unversioned_filter=tree.is_ignored)
2138
tree = WorkingTree.open_containing(u'.')[0]
2535
2140
if branch is not None:
2537
mergeable = bundle.read_mergeable_from_url(
2539
except errors.NotABundle:
2142
reader = bundle.read_bundle_from_url(branch)
2540
2144
pass # Continue on considering this url a Branch
2542
if revision is not None:
2543
raise errors.BzrCommandError(
2544
'Cannot use -r with merge directives or bundles')
2545
other_revision_id = mergeable.install_revisions(
2546
tree.branch.repository)
2547
revision = [RevisionSpec.from_string(
2548
'revid:' + other_revision_id)]
2146
conflicts = merge_bundle(reader, tree, not force, merge_type,
2147
reprocess, show_base)
2550
2153
if revision is None \
2551
2154
or len(revision) < 1 or revision[0].needs_branch():
3050
2618
if to_revid is None:
3051
2619
to_revno = b.revno()
3052
2620
if from_revno is None or to_revno is None:
3053
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2621
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3054
2622
for revno in range(from_revno, to_revno + 1):
3055
2623
b.repository.sign_revision(b.get_rev_id(revno),
3058
raise errors.BzrCommandError('Please supply either one revision, or a range.')
2626
raise BzrCommandError('Please supply either one revision, or a range.')
3061
2629
class cmd_bind(Command):
3062
"""Convert the current branch into a checkout of the supplied branch.
3064
Once converted into a checkout, commits must succeed on the master branch
3065
before they will be applied to the local branch.
3067
See "help checkouts" for more information on checkouts.
2630
"""Bind the current branch to a master branch.
2632
After binding, commits must succeed on the master branch
2633
before they are executed on the local one.
3070
takes_args = ['location?']
2636
takes_args = ['location']
3071
2637
takes_options = []
3073
2639
def run(self, location=None):
3074
2640
b, relpath = Branch.open_containing(u'.')
3075
if location is None:
3077
location = b.get_old_bound_location()
3078
except errors.UpgradeRequired:
3079
raise errors.BzrCommandError('No location supplied. '
3080
'This format does not remember old locations.')
3082
if location is None:
3083
raise errors.BzrCommandError('No location supplied and no '
3084
'previous location known')
3085
2641
b_other = Branch.open(location)
3087
2643
b.bind(b_other)
3088
except errors.DivergedBranches:
3089
raise errors.BzrCommandError('These branches have diverged.'
3090
' Try merging, and then bind again.')
2644
except DivergedBranches:
2645
raise BzrCommandError('These branches have diverged.'
2646
' Try merging, and then bind again.')
3093
2649
class cmd_unbind(Command):
3094
"""Convert the current checkout into a regular branch.
3096
After unbinding, the local branch is considered independent and subsequent
3097
commits will be local only.
3099
See "help checkouts" for more information on checkouts.
2650
"""Unbind the current branch from its master branch.
2652
After unbinding, the local branch is considered independent.
2653
All subsequent commits will be local.
3102
2656
takes_args = []
3216
class cmd_wait_until_signalled(Command):
3217
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3219
This just prints a line to signal when it is ready, then blocks on stdin.
3225
sys.stdout.write("running\n")
3227
sys.stdin.readline()
3230
class cmd_serve(Command):
3231
"""Run the bzr server."""
3233
aliases = ['server']
3237
help='serve on stdin/out for use from inetd or sshd'),
3239
help='listen for connections on nominated port of the form '
3240
'[hostname:]portnumber. Passing 0 as the port number will '
3241
'result in a dynamically allocated port. Default port is '
3245
help='serve contents of directory',
3247
Option('allow-writes',
3248
help='By default the server is a readonly server. Supplying '
3249
'--allow-writes enables write access to the contents of '
3250
'the served directory and below. '
3254
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3255
from bzrlib.smart import server, medium
3256
from bzrlib.transport import get_transport
3257
from bzrlib.transport.remote import BZR_DEFAULT_PORT
3258
if directory is None:
3259
directory = os.getcwd()
3260
url = urlutils.local_path_to_url(directory)
3261
if not allow_writes:
3262
url = 'readonly+' + url
3263
t = get_transport(url)
3265
smart_server = medium.SmartServerPipeStreamMedium(
3266
sys.stdin, sys.stdout, t)
3269
port = BZR_DEFAULT_PORT
3273
host, port = port.split(':')
3277
smart_server = server.SmartTCPServer(t, host=host, port=port)
3278
print 'listening on port: ', smart_server.port
3280
smart_server.serve()
3282
class cmd_join(Command):
3283
"""Combine a subtree into its containing tree.
3285
This command is for experimental use only. It requires the target tree
3286
to be in dirstate-with-subtree format, which cannot be converted into
3289
The TREE argument should be an independent tree, inside another tree, but
3290
not part of it. (Such trees can be produced by "bzr split", but also by
3291
running "bzr branch" with the target inside a tree.)
3293
The result is a combined tree, with the subtree no longer an independant
3294
part. This is marked as a merge of the subtree into the containing tree,
3295
and all history is preserved.
3297
If --reference is specified, the subtree retains its independence. It can
3298
be branched by itself, and can be part of multiple projects at the same
3299
time. But operations performed in the containing tree, such as commit
3300
and merge, will recurse into the subtree.
3303
takes_args = ['tree']
3304
takes_options = [Option('reference', 'join by reference')]
3307
def run(self, tree, reference=False):
3308
sub_tree = WorkingTree.open(tree)
3309
parent_dir = osutils.dirname(sub_tree.basedir)
3310
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3311
repo = containing_tree.branch.repository
3312
if not repo.supports_rich_root():
3313
raise errors.BzrCommandError(
3314
"Can't join trees because %s doesn't support rich root data.\n"
3315
"You can use bzr upgrade on the repository."
3319
containing_tree.add_reference(sub_tree)
3320
except errors.BadReferenceTarget, e:
3321
# XXX: Would be better to just raise a nicely printable
3322
# exception from the real origin. Also below. mbp 20070306
3323
raise errors.BzrCommandError("Cannot join %s. %s" %
3327
containing_tree.subsume(sub_tree)
3328
except errors.BadSubsumeSource, e:
3329
raise errors.BzrCommandError("Cannot join %s. %s" %
3333
class cmd_split(Command):
3334
"""Split a tree into two trees.
3336
This command is for experimental use only. It requires the target tree
3337
to be in dirstate-with-subtree format, which cannot be converted into
3340
The TREE argument should be a subdirectory of a working tree. That
3341
subdirectory will be converted into an independent tree, with its own
3342
branch. Commits in the top-level tree will not apply to the new subtree.
3343
If you want that behavior, do "bzr join --reference TREE".
3345
To undo this operation, do "bzr join TREE".
3348
takes_args = ['tree']
3352
def run(self, tree):
3353
containing_tree, subdir = WorkingTree.open_containing(tree)
3354
sub_id = containing_tree.path2id(subdir)
3356
raise errors.NotVersionedError(subdir)
3358
containing_tree.extract(sub_id)
3359
except errors.RootNotRich:
3360
raise errors.UpgradeRequired(containing_tree.branch.base)
3364
class cmd_merge_directive(Command):
3365
"""Generate a merge directive for auto-merge tools.
3367
A directive requests a merge to be performed, and also provides all the
3368
information necessary to do so. This means it must either include a
3369
revision bundle, or the location of a branch containing the desired
3372
A submit branch (the location to merge into) must be supplied the first
3373
time the command is issued. After it has been supplied once, it will
3374
be remembered as the default.
3376
A public branch is optional if a revision bundle is supplied, but required
3377
if --diff or --plain is specified. It will be remembered as the default
3378
after the first use.
3381
takes_args = ['submit_branch?', 'public_branch?']
3384
RegistryOption.from_kwargs('patch-type',
3385
'The type of patch to include in the directive',
3386
title='Patch type', value_switches=True, enum_switch=False,
3387
bundle='Bazaar revision bundle (default)',
3388
diff='Normal unified diff',
3389
plain='No patch, just directive'),
3390
Option('sign', help='GPG-sign the directive'), 'revision',
3391
Option('mail-to', type=str,
3392
help='Instead of printing the directive, email to this address'),
3393
Option('message', type=str, short_name='m',
3394
help='Message to use when committing this merge')
3397
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3398
sign=False, revision=None, mail_to=None, message=None):
3399
if patch_type == 'plain':
3401
branch = Branch.open('.')
3402
stored_submit_branch = branch.get_submit_branch()
3403
if submit_branch is None:
3404
submit_branch = stored_submit_branch
3406
if stored_submit_branch is None:
3407
branch.set_submit_branch(submit_branch)
3408
if submit_branch is None:
3409
submit_branch = branch.get_parent()
3410
if submit_branch is None:
3411
raise errors.BzrCommandError('No submit branch specified or known')
3413
stored_public_branch = branch.get_public_branch()
3414
if public_branch is None:
3415
public_branch = stored_public_branch
3416
elif stored_public_branch is None:
3417
branch.set_public_branch(public_branch)
3418
if patch_type != "bundle" and public_branch is None:
3419
raise errors.BzrCommandError('No public branch specified or'
3421
if revision is not None:
3422
if len(revision) != 1:
3423
raise errors.BzrCommandError('bzr merge-directive takes '
3424
'exactly one revision identifier')
3426
revision_id = revision[0].in_history(branch).rev_id
3428
revision_id = branch.last_revision()
3429
directive = merge_directive.MergeDirective.from_objects(
3430
branch.repository, revision_id, time.time(),
3431
osutils.local_time_offset(), submit_branch,
3432
public_branch=public_branch, patch_type=patch_type,
3436
self.outf.write(directive.to_signed(branch))
3438
self.outf.writelines(directive.to_lines())
3440
message = directive.to_email(mail_to, branch, sign)
3442
server = branch.get_config().get_user_option('smtp_server')
3444
server = 'localhost'
3446
s.sendmail(message['From'], message['To'], message.as_string())
3449
class cmd_tag(Command):
3450
"""Create a tag naming a revision.
3452
Tags give human-meaningful names to revisions. Commands that take a -r
3453
(--revision) option can be given -rtag:X, where X is any previously
3456
Tags are stored in the branch. Tags are copied from one branch to another
3457
along when you branch, push, pull or merge.
3459
It is an error to give a tag name that already exists unless you pass
3460
--force, in which case the tag is moved to point to the new revision.
3463
takes_args = ['tag_name']
3466
help='Delete this tag rather than placing it.',
3469
help='Branch in which to place the tag.',
3474
help='Replace existing tags',
3479
def run(self, tag_name,
3485
branch, relpath = Branch.open_containing(directory)
3489
branch.tags.delete_tag(tag_name)
3490
self.outf.write('Deleted tag %s.\n' % tag_name)
3493
if len(revision) != 1:
3494
raise errors.BzrCommandError(
3495
"Tags can only be placed on a single revision, "
3497
revision_id = revision[0].in_history(branch).rev_id
3499
revision_id = branch.last_revision()
3500
if (not force) and branch.tags.has_tag(tag_name):
3501
raise errors.TagAlreadyExists(tag_name)
3502
branch.tags.set_tag(tag_name, revision_id)
3503
self.outf.write('Created tag %s.\n' % tag_name)
3508
class cmd_tags(Command):
3511
This tag shows a table of tag names and the revisions they reference.
3516
help='Branch whose tags should be displayed',
3526
branch, relpath = Branch.open_containing(directory)
3527
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3528
self.outf.write('%-20s %s\n' % (tag_name, target))
3531
2771
# command-line interpretation helper for merge-related commands
3532
def _merge_helper(other_revision, base_revision,
3533
check_clean=True, ignore_zero=False,
3534
this_dir=None, backup_files=False,
3536
file_list=None, show_base=False, reprocess=False,
3539
change_reporter=None,
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()):
3541
2777
"""Merge changes into a tree.
3565
2801
clients might prefer to call merge.merge_inner(), which has less magic
3568
# Loading it late, so that we don't always have to import bzrlib.merge
3569
if merge_type is None:
3570
merge_type = _mod_merge.Merge3Merger
2804
from bzrlib.merge import Merger
3571
2805
if this_dir is None:
3572
2806
this_dir = u'.'
3573
2807
this_tree = WorkingTree.open_containing(this_dir)[0]
3574
if show_base and not merge_type is _mod_merge.Merge3Merger:
3575
raise errors.BzrCommandError("Show-base is not supported for this merge"
3576
" type. %s" % merge_type)
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)
3577
2811
if reprocess and not merge_type.supports_reprocess:
3578
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3579
" type %s." % merge_type)
2812
raise BzrCommandError("Conflict reduction is not supported for merge"
2813
" type %s." % merge_type)
3580
2814
if reprocess and show_base:
3581
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3582
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3583
# only want to take out a lock_tree_write() if we don't have to pull
3584
# any ancestry. But merge might fetch ancestry in the middle, in
3585
# which case we would need a lock_write().
3586
# Because we cannot upgrade locks, for now we live with the fact that
3587
# the tree will be locked multiple times during a merge. (Maybe
3588
# read-only some of the time, but it means things will get read
2815
raise BzrCommandError("Cannot do conflict reduction and show base.")
3591
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3592
pb=pb, change_reporter=change_reporter)
2817
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
3593
2818
merger.pp = ProgressPhase("Merge phase", 5, pb)
3594
2819
merger.pp.next_phase()
3595
2820
merger.check_basis(check_clean)
3596
if other_rev_id is not None:
3597
merger.set_other_revision(other_rev_id, this_tree.branch)
3599
merger.set_other(other_revision)
2821
merger.set_other(other_revision)
3600
2822
merger.pp.next_phase()
3601
2823
merger.set_base(base_revision)
3602
2824
if merger.base_rev_id == merger.other_rev_id:
3603
2825
note('Nothing to do.')
3605
if file_list is None:
3606
if pull and merger.base_rev_id == merger.this_rev_id:
3607
# FIXME: deduplicate with pull
3608
result = merger.this_tree.pull(merger.this_branch,
3609
False, merger.other_rev_id)
3610
if result.old_revid == result.new_revid:
3611
note('No revisions to pull.')
3613
note('Now on revision %d.' % result.new_revno)
3615
2827
merger.backup_files = backup_files
3616
2828
merger.merge_type = merge_type
3617
2829
merger.set_interesting_files(file_list)