1053
516
location can be accessed.
1056
_see_also = ['pull', 'update', 'working-trees']
1057
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
1058
Option('create-prefix',
1059
help='Create the path leading up to the branch '
1060
'if it does not already exist.'),
1062
help='Branch to push from, '
1063
'rather than the one containing the working directory.',
1067
Option('use-existing-dir',
1068
help='By default push will fail if the target'
1069
' directory exists, but does not already'
1070
' have a control directory. This flag will'
1071
' allow push to proceed.'),
1073
help='Create a stacked branch that references the public location '
1074
'of the parent branch.'),
1075
Option('stacked-on',
1076
help='Create a stacked branch that refers to another branch '
1077
'for the commit history. Only the work not present in the '
1078
'referenced branch is included in the branch created.',
1081
help='Refuse to push if there are uncommitted changes in'
1082
' the working tree, --no-strict disables the check.'),
519
takes_options = ['remember', 'overwrite', 'verbose',
520
Option('create-prefix',
521
help='Create the path leading up to the branch '
522
'if it does not already exist')]
1084
523
takes_args = ['location?']
1085
524
encoding_type = 'replace'
1087
526
def run(self, location=None, remember=False, overwrite=False,
1088
create_prefix=False, verbose=False, revision=None,
1089
use_existing_dir=False, directory=None, stacked_on=None,
1090
stacked=False, strict=None):
1091
from bzrlib.push import _show_push_branch
1093
if directory is None:
1095
# Get the source branch
1097
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1099
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1100
if strict is None: strict = True # default value
1101
# Get the tip's revision_id
1102
revision = _get_one_revision('push', revision)
1103
if revision is not None:
1104
revision_id = revision.in_history(br_from).rev_id
1107
if strict and tree is not None and revision_id is None:
1108
if (tree.has_changes(tree.basis_tree())
1109
or len(tree.get_parent_ids()) > 1):
1110
raise errors.UncommittedChanges(
1111
tree, more='Use --no-strict to force the push.')
1112
if tree.last_revision() != tree.branch.last_revision():
1113
# The tree has lost sync with its branch, there is little
1114
# chance that the user is aware of it but he can still force
1115
# the push with --no-strict
1116
raise errors.OutOfDateTree(
1117
tree, more='Use --no-strict to force the push.')
1119
# Get the stacked_on branch, if any
1120
if stacked_on is not None:
1121
stacked_on = urlutils.normalize_url(stacked_on)
1123
parent_url = br_from.get_parent()
1125
parent = Branch.open(parent_url)
1126
stacked_on = parent.get_public_branch()
1128
# I considered excluding non-http url's here, thus forcing
1129
# 'public' branches only, but that only works for some
1130
# users, so it's best to just depend on the user spotting an
1131
# error by the feedback given to them. RBC 20080227.
1132
stacked_on = parent_url
1134
raise errors.BzrCommandError(
1135
"Could not determine branch to refer to.")
1137
# Get the destination location
527
create_prefix=False, verbose=False):
528
# FIXME: Way too big! Put this into a function called from the
531
br_from = Branch.open_containing('.')[0]
532
stored_loc = br_from.get_push_location()
1138
533
if location is None:
1139
stored_loc = br_from.get_push_location()
1140
534
if stored_loc is None:
1141
raise errors.BzrCommandError(
1142
"No push location known or specified.")
535
raise BzrCommandError("No push location known or specified.")
1144
537
display_url = urlutils.unescape_for_display(stored_loc,
1145
538
self.outf.encoding)
1146
self.outf.write("Using saved push location: %s\n" % display_url)
539
self.outf.write("Using saved location: %s\n" % display_url)
1147
540
location = stored_loc
1149
_show_push_branch(br_from, revision_id, location, self.outf,
1150
verbose=verbose, overwrite=overwrite, remember=remember,
1151
stacked_on=stacked_on, create_prefix=create_prefix,
1152
use_existing_dir=use_existing_dir)
542
to_transport = transport.get_transport(location)
543
location_url = to_transport.base
547
dir_to = bzrdir.BzrDir.open(location_url)
548
br_to = dir_to.open_branch()
549
except NotBranchError:
551
to_transport = to_transport.clone('..')
552
if not create_prefix:
554
relurl = to_transport.relpath(location_url)
555
mutter('creating directory %s => %s', location_url, relurl)
556
to_transport.mkdir(relurl)
558
raise BzrCommandError("Parent directory of %s "
559
"does not exist." % location)
561
current = to_transport.base
562
needed = [(to_transport, to_transport.relpath(location_url))]
565
to_transport, relpath = needed[-1]
566
to_transport.mkdir(relpath)
569
new_transport = to_transport.clone('..')
570
needed.append((new_transport,
571
new_transport.relpath(to_transport.base)))
572
if new_transport.base == to_transport.base:
573
raise BzrCommandError("Could not create "
575
dir_to = br_from.bzrdir.clone(location_url,
576
revision_id=br_from.last_revision())
577
br_to = dir_to.open_branch()
578
count = len(br_to.revision_history())
579
# We successfully created the target, remember it
580
if br_from.get_push_location() is None or remember:
581
br_from.set_push_location(br_to.base)
583
# We were able to connect to the remote location, so remember it
584
# we don't need to successfully push because of possible divergence.
585
if br_from.get_push_location() is None or remember:
586
br_from.set_push_location(br_to.base)
587
old_rh = br_to.revision_history()
590
tree_to = dir_to.open_workingtree()
591
except errors.NotLocalUrl:
592
warning('This transport does not update the working '
593
'tree of: %s' % (br_to.base,))
594
count = br_to.pull(br_from, overwrite)
595
except NoWorkingTree:
596
count = br_to.pull(br_from, overwrite)
598
count = tree_to.pull(br_from, overwrite)
599
except DivergedBranches:
600
raise BzrCommandError("These branches have diverged."
601
" Try a merge then push with overwrite.")
602
note('%d revision(s) pushed.' % (count,))
605
new_rh = br_to.revision_history()
608
from bzrlib.log import show_changed_revisions
609
show_changed_revisions(br_to, old_rh, new_rh,
1155
613
class cmd_branch(Command):
1156
"""Create a new branch that is a copy of an existing branch.
614
"""Create a new copy of a branch.
1158
616
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1159
617
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1160
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
1161
is derived from the FROM_LOCATION by stripping a leading scheme or drive
1162
identifier, if any. For example, "branch lp:foo-bar" will attempt to
1165
619
To retrieve the branch as of a particular revision, supply the --revision
1166
620
parameter, as in "branch foo/bar -r 5".
622
--basis is to speed up branching from remote branches. When specified, it
623
copies all the file-contents, inventory and revision data from the basis
624
branch before copying anything from the remote branch.
1169
_see_also = ['checkout']
1170
626
takes_args = ['from_location', 'to_location?']
1171
takes_options = ['revision', Option('hardlink',
1172
help='Hard-link working tree files where possible.'),
1174
help="Create a branch without a working-tree."),
1176
help='Create a stacked branch referring to the source branch. '
1177
'The new branch will depend on the availability of the source '
1178
'branch for all operations.'),
1179
Option('standalone',
1180
help='Do not use a shared repository, even if available.'),
1181
Option('use-existing-dir',
1182
help='By default branch will fail if the target'
1183
' directory exists, but does not already'
1184
' have a control directory. This flag will'
1185
' allow branch to proceed.'),
627
takes_options = ['revision', 'basis']
1187
628
aliases = ['get', 'clone']
1189
def run(self, from_location, to_location=None, revision=None,
1190
hardlink=False, stacked=False, standalone=False, no_tree=False,
1191
use_existing_dir=False):
1192
from bzrlib.tag import _merge_tags_if_possible
1194
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1196
if (accelerator_tree is not None and
1197
accelerator_tree.supports_content_filtering()):
1198
accelerator_tree = None
1199
revision = _get_one_revision('branch', revision)
630
def run(self, from_location, to_location=None, revision=None, basis=None):
633
elif len(revision) > 1:
634
raise BzrCommandError(
635
'bzr branch --revision takes exactly 1 revision value')
637
br_from = Branch.open(from_location)
639
if e.errno == errno.ENOENT:
640
raise BzrCommandError('Source location "%s" does not'
641
' exist.' % to_location)
1200
644
br_from.lock_read()
1202
if revision is not None:
1203
revision_id = revision.as_revision_id(br_from)
646
if basis is not None:
647
basis_dir = bzrdir.BzrDir.open_containing(basis)[0]
650
if len(revision) == 1 and revision[0] is not None:
651
revision_id = revision[0].in_history(br_from)[1]
1205
653
# FIXME - wt.last_revision, fallback to branch, fall back to
1206
654
# None or perhaps NULL_REVISION to mean copy nothing
1208
656
revision_id = br_from.last_revision()
1209
657
if to_location is None:
1210
to_location = urlutils.derive_to_location(from_location)
658
to_location = os.path.basename(from_location.rstrip("/\\"))
661
name = os.path.basename(to_location) + '\n'
1211
663
to_transport = transport.get_transport(to_location)
1213
665
to_transport.mkdir('.')
1214
666
except errors.FileExists:
1215
if not use_existing_dir:
1216
raise errors.BzrCommandError('Target directory "%s" '
1217
'already exists.' % to_location)
1220
bzrdir.BzrDir.open_from_transport(to_transport)
1221
except errors.NotBranchError:
1224
raise errors.AlreadyBranchError(to_location)
667
raise BzrCommandError('Target directory "%s" already'
668
' exists.' % to_location)
1225
669
except errors.NoSuchFile:
1226
raise errors.BzrCommandError('Parent of "%s" does not exist.'
670
raise BzrCommandError('Parent of "%s" does not exist.' %
1229
673
# preserve whatever source format we have.
1230
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1231
possible_transports=[to_transport],
1232
accelerator_tree=accelerator_tree,
1233
hardlink=hardlink, stacked=stacked,
1234
force_new_repo=standalone,
1235
create_tree_if_local=not no_tree,
1236
source_branch=br_from)
674
dir = br_from.bzrdir.sprout(to_transport.base,
675
revision_id, basis_dir)
1237
676
branch = dir.open_branch()
1238
677
except errors.NoSuchRevision:
1239
678
to_transport.delete_tree('.')
1240
msg = "The branch %s has no revision %s." % (from_location,
1242
raise errors.BzrCommandError(msg)
1243
_merge_tags_if_possible(br_from, branch)
1244
# If the source branch is stacked, the new branch may
1245
# be stacked whether we asked for that explicitly or not.
1246
# We therefore need a try/except here and not just 'if stacked:'
1248
note('Created new stacked branch referring to %s.' %
1249
branch.get_stacked_on_url())
1250
except (errors.NotStacked, errors.UnstackableBranchFormat,
1251
errors.UnstackableRepositoryFormat), e:
1252
note('Branched %d revision(s).' % branch.revno())
679
msg = "The branch %s has no revision %s." % (from_location, revision[0])
680
raise BzrCommandError(msg)
681
except errors.UnlistableBranch:
682
osutils.rmtree(to_location)
683
msg = "The branch %s cannot be used as a --basis" % (basis,)
684
raise BzrCommandError(msg)
686
branch.control_files.put_utf8('branch-name', name)
687
note('Branched %d revision(s).' % branch.revno())
1254
689
br_from.unlock()
1680
1033
# Just using os.mkdir, since I don't
1681
1034
# believe that we want to create a bunch of
1682
1035
# locations if the user supplies an extended path
1684
to_transport.ensure_base()
1685
except errors.NoSuchFile:
1686
if not create_prefix:
1687
raise errors.BzrCommandError("Parent directory of %s"
1689
"\nYou may supply --create-prefix to create all"
1690
" leading parent directories."
1692
to_transport.create_prefix()
1695
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1696
except errors.NotBranchError:
1036
# TODO: create-prefix
1038
to_transport.mkdir('.')
1039
except errors.FileExists:
1043
existing_bzrdir = bzrdir.BzrDir.open(location)
1044
except NotBranchError:
1697
1045
# really a NotBzrDir error...
1698
create_branch = bzrdir.BzrDir.create_branch_convenience
1699
branch = create_branch(to_transport.base, format=format,
1700
possible_transports=[to_transport])
1701
a_bzrdir = branch.bzrdir
1046
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1703
from bzrlib.transport.local import LocalTransport
1704
if a_bzrdir.has_branch():
1048
if existing_bzrdir.has_branch():
1705
1049
if (isinstance(to_transport, LocalTransport)
1706
and not a_bzrdir.has_workingtree()):
1050
and not existing_bzrdir.has_workingtree()):
1707
1051
raise errors.BranchExistsWithoutWorkingTree(location)
1708
1052
raise errors.AlreadyBranchError(location)
1709
branch = a_bzrdir.create_branch()
1710
a_bzrdir.create_workingtree()
1711
if append_revisions_only:
1713
branch.set_append_revisions_only(True)
1714
except errors.UpgradeRequired:
1715
raise errors.BzrCommandError('This branch format cannot be set'
1716
' to append-revisions-only. Try --default.')
1718
from bzrlib.info import describe_layout, describe_format
1720
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1721
except (errors.NoWorkingTree, errors.NotLocalUrl):
1723
repository = branch.repository
1724
layout = describe_layout(repository, branch, tree).lower()
1725
format = describe_format(a_bzrdir, repository, branch, tree)
1726
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1727
if repository.is_shared():
1728
#XXX: maybe this can be refactored into transport.path_or_url()
1729
url = repository.bzrdir.root_transport.external_url()
1731
url = urlutils.local_path_from_url(url)
1732
except errors.InvalidURL:
1734
self.outf.write("Using shared repository: %s\n" % url)
1054
existing_bzrdir.create_branch()
1055
existing_bzrdir.create_workingtree()
1737
1058
class cmd_init_repository(Command):
1738
1059
"""Create a shared repository to hold branches.
1740
New branches created under the repository directory will store their
1741
revisions in the repository, not in the branch directory.
1743
If the --no-trees option is used then the branches in the repository
1744
will not have working trees by default.
1747
Create a shared repositories holding just branches::
1749
bzr init-repo --no-trees repo
1752
Make a lightweight checkout elsewhere::
1754
bzr checkout --lightweight repo/trunk trunk-checkout
1061
New branches created under the repository directory will store their revisions
1062
in the repository, not in the branch directory, if the branch format supports
1068
bzr checkout --lightweight repo/trunk trunk-checkout
1759
_see_also = ['init', 'branch', 'checkout', 'repositories']
1760
takes_args = ["location"]
1761
takes_options = [RegistryOption('format',
1762
help='Specify a format for this repository. See'
1763
' "bzr help formats" for details.',
1764
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1765
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1766
value_switches=True, title='Repository format'),
1768
help='Branches in the repository will default to'
1769
' not having a working tree.'),
1072
takes_args = ["location"]
1073
takes_options = [Option('format',
1074
help='Specify a format for this repository.'
1075
' Current formats are: default, knit,'
1076
' metaweave and weave. Default is knit;'
1077
' metaweave and weave are deprecated',
1078
type=get_format_type),
1080
help='Allows branches in repository to have'
1771
1082
aliases = ["init-repo"]
1773
def run(self, location, format=None, no_trees=False):
1083
def run(self, location, format=None, trees=False):
1774
1084
if format is None:
1775
format = bzrdir.format_registry.make_bzrdir('default')
1085
format = get_format_type('default')
1777
1087
if location is None:
1780
1090
to_transport = transport.get_transport(location)
1781
to_transport.ensure_base()
1092
to_transport.mkdir('.')
1093
except errors.FileExists:
1783
1096
newdir = format.initialize_on_transport(to_transport)
1784
1097
repo = newdir.create_repository(shared=True)
1785
repo.set_make_working_trees(not no_trees)
1787
from bzrlib.info import show_bzrdir_info
1788
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1098
repo.set_make_working_trees(trees)
1791
1101
class cmd_diff(Command):
1792
"""Show differences in the working tree, between revisions or branches.
1794
If no arguments are given, all changes for the current tree are listed.
1795
If files are given, only the changes in those files are listed.
1796
Remote and multiple branches can be compared by using the --old and
1797
--new options. If not provided, the default for both is derived from
1798
the first argument, if any, or the current tree if no arguments are
1102
"""Show differences in the working tree or between revisions.
1104
If files are listed, only the changes in those files are listed.
1105
Otherwise, all changes for the tree are listed.
1801
1107
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1802
1108
produces patches suitable for "patch -p1".
1806
2 - unrepresentable changes
1811
Shows the difference in the working tree versus the last commit::
1815
Difference between the working tree and revision 1::
1819
Difference between revision 2 and revision 1::
1823
Difference between revision 2 and revision 1 for branch xxx::
1827
Show just the differences for file NEWS::
1831
Show the differences in working tree xxx for file NEWS::
1835
Show the differences from branch xxx to this working tree:
1839
Show the differences between two branches for file NEWS::
1841
bzr diff --old xxx --new yyy NEWS
1843
Same as 'bzr diff' but prefix paths with old/ and new/::
1845
bzr diff --prefix old/:new/
1112
Shows the difference in the working tree versus the last commit
1114
Difference between the working tree and revision 1
1116
Difference between revision 2 and revision 1
1117
bzr diff --diff-prefix old/:new/
1118
Same as 'bzr diff' but prefix paths with old/ and new/
1119
bzr diff bzr.mine bzr.dev
1120
Show the differences between the two working trees
1122
Show just the differences for 'foo.c'
1847
_see_also = ['status']
1124
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1125
# or a graphical diff.
1127
# TODO: Python difflib is not exactly the same as unidiff; should
1128
# either fix it up or prefer to use an external diff.
1130
# TODO: Selected-file diff is inefficient and doesn't show you
1133
# TODO: This probably handles non-Unix newlines poorly.
1848
1135
takes_args = ['file*']
1850
Option('diff-options', type=str,
1851
help='Pass these options to the external diff program.'),
1852
Option('prefix', type=str,
1854
help='Set prefixes added to old and new filenames, as '
1855
'two values separated by a colon. (eg "old/:new/").'),
1857
help='Branch/tree to compare from.',
1861
help='Branch/tree to compare to.',
1867
help='Use this command to compare files.',
1136
takes_options = ['revision', 'diff-options', 'prefix']
1871
1137
aliases = ['di', 'dif']
1872
1138
encoding_type = 'exact'
1874
1140
@display_command
1875
1141
def run(self, revision=None, file_list=None, diff_options=None,
1876
prefix=None, old=None, new=None, using=None):
1877
from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1143
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1879
1145
if (prefix is None) or (prefix == '0'):
1880
1146
# diff -p0 format
2014
1267
self.outf.write(tree.basedir + '\n')
2017
def _parse_limit(limitstring):
2019
return int(limitstring)
2021
msg = "The limit argument must be an integer."
2022
raise errors.BzrCommandError(msg)
2025
def _parse_levels(s):
2029
msg = "The levels argument must be an integer."
2030
raise errors.BzrCommandError(msg)
2033
1270
class cmd_log(Command):
2034
"""Show historical log for a branch or subset of a branch.
2036
log is bzr's default tool for exploring the history of a branch.
2037
The branch to use is taken from the first parameter. If no parameters
2038
are given, the branch containing the working directory is logged.
2039
Here are some simple examples::
2041
bzr log log the current branch
2042
bzr log foo.py log a file in its branch
2043
bzr log http://server/branch log a branch on a server
2045
The filtering, ordering and information shown for each revision can
2046
be controlled as explained below. By default, all revisions are
2047
shown sorted (topologically) so that newer revisions appear before
2048
older ones and descendants always appear before ancestors. If displayed,
2049
merged revisions are shown indented under the revision in which they
2054
The log format controls how information about each revision is
2055
displayed. The standard log formats are called ``long``, ``short``
2056
and ``line``. The default is long. See ``bzr help log-formats``
2057
for more details on log formats.
2059
The following options can be used to control what information is
2062
-l N display a maximum of N revisions
2063
-n N display N levels of revisions (0 for all, 1 for collapsed)
2064
-v display a status summary (delta) for each revision
2065
-p display a diff (patch) for each revision
2066
--show-ids display revision-ids (and file-ids), not just revnos
2068
Note that the default number of levels to display is a function of the
2069
log format. If the -n option is not used, the standard log formats show
2070
just the top level (mainline).
2072
Status summaries are shown using status flags like A, M, etc. To see
2073
the changes explained using words like ``added`` and ``modified``
2074
instead, use the -vv option.
2078
To display revisions from oldest to newest, use the --forward option.
2079
In most cases, using this option will have little impact on the total
2080
time taken to produce a log, though --forward does not incrementally
2081
display revisions like --reverse does when it can.
2083
:Revision filtering:
2085
The -r option can be used to specify what revision or range of revisions
2086
to filter against. The various forms are shown below::
2088
-rX display revision X
2089
-rX.. display revision X and later
2090
-r..Y display up to and including revision Y
2091
-rX..Y display from X to Y inclusive
2093
See ``bzr help revisionspec`` for details on how to specify X and Y.
2094
Some common examples are given below::
2096
-r-1 show just the tip
2097
-r-10.. show the last 10 mainline revisions
2098
-rsubmit:.. show what's new on this branch
2099
-rancestor:path.. show changes since the common ancestor of this
2100
branch and the one at location path
2101
-rdate:yesterday.. show changes since yesterday
2103
When logging a range of revisions using -rX..Y, log starts at
2104
revision Y and searches back in history through the primary
2105
("left-hand") parents until it finds X. When logging just the
2106
top level (using -n1), an error is reported if X is not found
2107
along the way. If multi-level logging is used (-n0), X may be
2108
a nested merge revision and the log will be truncated accordingly.
2112
If parameters are given and the first one is not a branch, the log
2113
will be filtered to show only those revisions that changed the
2114
nominated files or directories.
2116
Filenames are interpreted within their historical context. To log a
2117
deleted file, specify a revision range so that the file existed at
2118
the end or start of the range.
2120
Historical context is also important when interpreting pathnames of
2121
renamed files/directories. Consider the following example:
2123
* revision 1: add tutorial.txt
2124
* revision 2: modify tutorial.txt
2125
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2129
* ``bzr log guide.txt`` will log the file added in revision 1
2131
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2133
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2134
the original file in revision 2.
2136
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2137
was no file called guide.txt in revision 2.
2139
Renames are always followed by log. By design, there is no need to
2140
explicitly ask for this (and no way to stop logging a file back
2141
until it was last renamed).
2145
The --message option can be used for finding revisions that match a
2146
regular expression in a commit message.
2150
GUI tools and IDEs are often better at exploring history than command
2151
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2152
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2153
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2155
Web interfaces are often better at exploring history than command line
2156
tools, particularly for branches on servers. You may prefer Loggerhead
2157
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2159
You may find it useful to add the aliases below to ``bazaar.conf``::
2163
top = log -l10 --line
2166
``bzr tip`` will then show the latest revision while ``bzr top``
2167
will show the last 10 mainline revisions. To see the details of a
2168
particular revision X, ``bzr show -rX``.
2170
If you are interested in looking deeper into a particular merge X,
2171
use ``bzr log -n0 -rX``.
2173
``bzr log -v`` on a branch with lots of history is currently
2174
very slow. A fix for this issue is currently under development.
2175
With or without that fix, it is recommended that a revision range
2176
be given when using the -v option.
2178
bzr has a generic full-text matching plugin, bzr-search, that can be
2179
used to find revisions matching user names, commit messages, etc.
2180
Among other features, this plugin can find all revisions containing
2181
a list of words but not others.
2183
When exploring non-mainline history on large projects with deep
2184
history, the performance of log can be greatly improved by installing
2185
the historycache plugin. This plugin buffers historical information
2186
trading disk space for faster speed.
1271
"""Show log of a branch, file, or directory.
1273
By default show the log of the branch containing the working directory.
1275
To request a range of logs, you can use the command -r begin..end
1276
-r revision requests a specific revision, -r ..end or -r begin.. are
1282
bzr log -r -10.. http://server/branch
2188
takes_args = ['file*']
2189
_see_also = ['log-formats', 'revisionspec']
2192
help='Show from oldest to newest.'),
2194
custom_help('verbose',
2195
help='Show files changed in each revision.'),
2199
type=bzrlib.option._parse_revision_str,
2201
help='Show just the specified revision.'
2202
' See also "help revisionspec".'),
2206
help='Number of levels to display - 0 for all, 1 for flat.',
2208
type=_parse_levels),
2211
help='Show revisions whose message matches this '
2212
'regular expression.',
2216
help='Limit the output to the first N revisions.',
2221
help='Show changes made in each revision as a patch.'),
2222
Option('include-merges',
2223
help='Show merged revisions like --levels 0 does.'),
1285
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1287
takes_args = ['location?']
1288
takes_options = [Option('forward',
1289
help='show from oldest to newest'),
1292
help='show files changed in each revision'),
1293
'show-ids', 'revision',
1297
help='show revisions whose message matches this regexp',
2225
1301
encoding_type = 'replace'
2227
1303
@display_command
2228
def run(self, file_list=None, timezone='original',
1304
def run(self, location=None, timezone='original',
2230
1306
show_ids=False,
2234
1309
log_format=None,
2239
include_merges=False):
2240
from bzrlib.log import (
2242
make_log_request_dict,
2243
_get_info_for_log_files,
1314
from bzrlib.log import log_formatter, show_log
1315
assert message is None or isinstance(message, basestring), \
1316
"invalid message argument %r" % message
2245
1317
direction = (forward and 'forward') or 'reverse'
2250
raise errors.BzrCommandError(
2251
'--levels and --include-merges are mutually exclusive')
2253
if change is not None:
2255
raise errors.RangeInChangeOption()
2256
if revision is not None:
2257
raise errors.BzrCommandError(
2258
'--revision and --change are mutually exclusive')
2263
filter_by_dir = False
2265
# find the file ids to log and check for directory filtering
2266
b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2268
for relpath, file_id, kind in file_info_list:
2270
raise errors.BzrCommandError(
2271
"Path unknown at end or start of revision range: %s" %
2273
# If the relpath is the top of the tree, we log everything
2278
file_ids.append(file_id)
2279
filter_by_dir = filter_by_dir or (
2280
kind in ['directory', 'tree-reference'])
2283
# FIXME ? log the current subdir only RBC 20060203
2284
if revision is not None \
2285
and len(revision) > 0 and revision[0].get_branch():
2286
location = revision[0].get_branch()
2289
dir, relpath = bzrdir.BzrDir.open_containing(location)
2290
b = dir.open_branch()
2291
rev1, rev2 = _get_revision_range(revision, b, self.name())
2293
# Decide on the type of delta & diff filtering to use
2294
# TODO: add an --all-files option to make this configurable & consistent
2302
diff_type = 'partial'
2308
# Build the log formatter
2309
if log_format is None:
2310
log_format = log.log_formatter_registry.get_default(b)
2311
lf = log_format(show_ids=show_ids, to_file=self.outf,
2312
show_timezone=timezone,
2313
delta_format=get_verbosity_level(),
2315
show_advice=levels is None)
2317
# Choose the algorithm for doing the logging. It's annoying
2318
# having multiple code paths like this but necessary until
2319
# the underlying repository format is faster at generating
2320
# deltas or can provide everything we need from the indices.
2321
# The default algorithm - match-using-deltas - works for
2322
# multiple files and directories and is faster for small
2323
# amounts of history (200 revisions say). However, it's too
2324
# slow for logging a single file in a repository with deep
2325
# history, i.e. > 10K revisions. In the spirit of "do no
2326
# evil when adding features", we continue to use the
2327
# original algorithm - per-file-graph - for the "single
2328
# file that isn't a directory without showing a delta" case.
2329
partial_history = revision and b.repository._format.supports_chks
2330
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2331
or delta_type or partial_history)
2333
# Build the LogRequest and execute it
2334
if len(file_ids) == 0:
2336
rqst = make_log_request_dict(
2337
direction=direction, specific_fileids=file_ids,
2338
start_revision=rev1, end_revision=rev2, limit=limit,
2339
message_search=message, delta_type=delta_type,
2340
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2341
Logger(b, rqst).show(lf)
2346
def _get_revision_range(revisionspec_list, branch, command_name):
2347
"""Take the input of a revision option and turn it into a revision range.
2349
It returns RevisionInfo objects which can be used to obtain the rev_id's
2350
of the desired revisions. It does some user input validations.
2352
if revisionspec_list is None:
2355
elif len(revisionspec_list) == 1:
2356
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2357
elif len(revisionspec_list) == 2:
2358
start_spec = revisionspec_list[0]
2359
end_spec = revisionspec_list[1]
2360
if end_spec.get_branch() != start_spec.get_branch():
2361
# b is taken from revision[0].get_branch(), and
2362
# show_log will use its revision_history. Having
2363
# different branches will lead to weird behaviors.
2364
raise errors.BzrCommandError(
2365
"bzr %s doesn't accept two revisions in different"
2366
" branches." % command_name)
2367
rev1 = start_spec.in_history(branch)
2368
# Avoid loading all of history when we know a missing
2369
# end of range means the last revision ...
2370
if end_spec.spec is None:
2371
last_revno, last_revision_id = branch.last_revision_info()
2372
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2374
rev2 = end_spec.in_history(branch)
2376
raise errors.BzrCommandError(
2377
'bzr %s --revision takes one or two values.' % command_name)
2381
def _revision_range_to_revid_range(revision_range):
2384
if revision_range[0] is not None:
2385
rev_id1 = revision_range[0].rev_id
2386
if revision_range[1] is not None:
2387
rev_id2 = revision_range[1].rev_id
2388
return rev_id1, rev_id2
1322
# find the file id to log:
1324
dir, fp = bzrdir.BzrDir.open_containing(location)
1325
b = dir.open_branch()
1329
inv = dir.open_workingtree().inventory
1330
except (errors.NotBranchError, errors.NotLocalUrl):
1331
# either no tree, or is remote.
1332
inv = b.basis_tree().inventory
1333
file_id = inv.path2id(fp)
1336
# FIXME ? log the current subdir only RBC 20060203
1337
dir, relpath = bzrdir.BzrDir.open_containing('.')
1338
b = dir.open_branch()
1340
if revision is None:
1343
elif len(revision) == 1:
1344
rev1 = rev2 = revision[0].in_history(b).revno
1345
elif len(revision) == 2:
1346
if revision[0].spec is None:
1347
# missing begin-range means first revision
1350
rev1 = revision[0].in_history(b).revno
1352
if revision[1].spec is None:
1353
# missing end-range means last known revision
1356
rev2 = revision[1].in_history(b).revno
1358
raise BzrCommandError('bzr log --revision takes one or two values.')
1360
# By this point, the revision numbers are converted to the +ve
1361
# form if they were supplied in the -ve form, so we can do
1362
# this comparison in relative safety
1364
(rev2, rev1) = (rev1, rev2)
1366
if (log_format == None):
1367
default = b.get_config().log_format()
1368
log_format = get_log_format(long=long, short=short, line=line,
1370
lf = log_formatter(log_format,
1373
show_timezone=timezone)
1379
direction=direction,
1380
start_revision=rev1,
2390
1385
def get_log_format(long=False, short=False, line=False, default='long'):
2391
1386
log_format = default
3347
1924
return FakeNFSServer
3348
1925
msg = "No known transport type %s. Supported types are: sftp\n" %\
3350
raise errors.BzrCommandError(msg)
1927
raise BzrCommandError(msg)
3353
1930
takes_args = ['testspecs*']
3354
1931
takes_options = ['verbose',
3356
help='Stop when one test fails.',
1932
Option('one', help='stop when one test fails'),
1933
Option('keep-output',
1934
help='keep output directories when tests fail'),
3360
1936
help='Use a different transport by default '
3361
1937
'throughout the test suite.',
3362
1938
type=get_transport_type),
3364
help='Run the benchmarks rather than selftests.'),
1939
Option('benchmark', help='run the bzr bencharks.'),
3365
1940
Option('lsprof-timed',
3366
help='Generate lsprof output for benchmarked'
1941
help='generate lsprof output for benchmarked'
3367
1942
' sections of code.'),
3368
Option('cache-dir', type=str,
3369
help='Cache intermediate benchmark output in this '
3372
help='Run all tests, but run specified tests first.',
3376
help='List the tests instead of running them.'),
3377
RegistryOption('parallel',
3378
help="Run the test suite in parallel.",
3379
lazy_registry=('bzrlib.tests', 'parallel_registry'),
3380
value_switches=False,
3382
Option('randomize', type=str, argname="SEED",
3383
help='Randomize the order of tests using the given'
3384
' seed or "now" for the current time.'),
3385
Option('exclude', type=str, argname="PATTERN",
3387
help='Exclude tests that match this regular'
3390
help='Output test progress via subunit.'),
3391
Option('strict', help='Fail on missing dependencies or '
3393
Option('load-list', type=str, argname='TESTLISTFILE',
3394
help='Load a test id list from a text file.'),
3395
ListOption('debugflag', type=str, short_name='E',
3396
help='Turn on a selftest debug flag.'),
3397
ListOption('starting-with', type=str, argname='TESTID',
3398
param_name='starting_with', short_name='s',
3400
'Load only the tests starting with TESTID.'),
3402
encoding_type = 'replace'
3405
Command.__init__(self)
3406
self.additional_selftest_args = {}
3408
def run(self, testspecs_list=None, verbose=False, one=False,
3409
transport=None, benchmark=None,
3410
lsprof_timed=None, cache_dir=None,
3411
first=False, list_only=False,
3412
randomize=None, exclude=None, strict=False,
3413
load_list=None, debugflag=None, starting_with=None, subunit=False,
1945
def run(self, testspecs_list=None, verbose=None, one=False,
1946
keep_output=False, transport=None, benchmark=None,
3415
1949
from bzrlib.tests import selftest
3416
1950
import bzrlib.benchmarks as benchmarks
3417
from bzrlib.benchmarks import tree_creator
3419
# Make deprecation warnings visible, unless -Werror is set
3420
symbol_versioning.activate_deprecation_warnings(override=False)
3422
if cache_dir is not None:
3423
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3424
if testspecs_list is not None:
3425
pattern = '|'.join(testspecs_list)
3430
from bzrlib.tests import SubUnitBzrRunner
3432
raise errors.BzrCommandError("subunit not available. subunit "
3433
"needs to be installed to use --subunit.")
3434
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3436
self.additional_selftest_args.setdefault(
3437
'suite_decorators', []).append(parallel)
3439
test_suite_factory = benchmarks.test_suite
3440
# Unless user explicitly asks for quiet, be verbose in benchmarks
3441
verbose = not is_quiet()
3442
# TODO: should possibly lock the history file...
3443
benchfile = open(".perf_history", "at", buffering=1)
3445
test_suite_factory = None
1951
# we don't want progress meters from the tests to go to the
1952
# real output; and we don't want log messages cluttering up
1954
save_ui = ui.ui_factory
1955
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1956
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1958
info('running tests...')
3448
selftest_kwargs = {"verbose": verbose,
3450
"stop_on_failure": one,
3451
"transport": transport,
3452
"test_suite_factory": test_suite_factory,
3453
"lsprof_timed": lsprof_timed,
3454
"bench_history": benchfile,
3455
"matching_tests_first": first,
3456
"list_only": list_only,
3457
"random_seed": randomize,
3458
"exclude_pattern": exclude,
3460
"load_list": load_list,
3461
"debug_flags": debugflag,
3462
"starting_with": starting_with
3464
selftest_kwargs.update(self.additional_selftest_args)
3465
result = selftest(**selftest_kwargs)
1960
ui.ui_factory = ui.SilentUIFactory()
1961
if testspecs_list is not None:
1962
pattern = '|'.join(testspecs_list)
1966
test_suite_factory = benchmarks.test_suite
1970
test_suite_factory = None
1973
result = selftest(verbose=verbose,
1975
stop_on_failure=one,
1976
keep_output=keep_output,
1977
transport=transport,
1978
test_suite_factory=test_suite_factory,
1979
lsprof_timed=lsprof_timed)
1981
info('tests passed')
1983
info('tests failed')
1984
return int(not result)
3467
if benchfile is not None:
3469
return int(not result)
1986
ui.ui_factory = save_ui
1989
def _get_bzr_branch():
1990
"""If bzr is run from a branch, return Branch or None"""
1991
from os.path import dirname
1994
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1996
except errors.BzrError:
2002
print "Bazaar (bzr) %s" % bzrlib.__version__
2003
# is bzrlib itself in a branch?
2004
branch = _get_bzr_branch()
2006
rh = branch.revision_history()
2008
print " bzr checkout, revision %d" % (revno,)
2009
print " nick: %s" % (branch.nick,)
2011
print " revid: %s" % (rh[-1],)
2012
print "Using python interpreter:", sys.executable
2014
print "Using python standard library:", os.path.dirname(site.__file__)
2015
print "Using bzrlib:",
2016
if len(bzrlib.__path__) > 1:
2017
# print repr, which is a good enough way of making it clear it's
2018
# more than one element (eg ['/foo/bar', '/foo/bzr'])
2019
print repr(bzrlib.__path__)
2021
print bzrlib.__path__[0]
2024
print bzrlib.__copyright__
2025
print "http://bazaar-vcs.org/"
2027
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
2028
print "you may use, modify and redistribute it under the terms of the GNU"
2029
print "General Public License version 2 or later."
3472
2032
class cmd_version(Command):
3473
2033
"""Show version of bzr."""
3475
encoding_type = 'replace'
3477
Option("short", help="Print just the version number."),
3480
2035
@display_command
3481
def run(self, short=False):
3482
from bzrlib.version import show_version
3484
self.outf.write(bzrlib.version_string + '\n')
3486
show_version(to_file=self.outf)
3489
2040
class cmd_rocks(Command):
3557
2100
default, use --remember. The value will only be saved if the remote
3558
2101
location can be accessed.
3560
The results of the merge are placed into the destination working
3561
directory, where they can be reviewed (with bzr diff), tested, and then
3562
committed to record the result of the merge.
2105
To merge the latest revision from bzr.dev
2106
bzr merge ../bzr.dev
2108
To merge changes up to and including revision 82 from bzr.dev
2109
bzr merge -r 82 ../bzr.dev
2111
To merge the changes introduced by 82, without previous changes:
2112
bzr merge -r 81..82 ../bzr.dev
3564
2114
merge refuses to run if there are any uncommitted changes, unless
3565
2115
--force is given.
3567
To select only some changes to merge, use "merge -i", which will prompt
3568
you to apply each diff hunk and file change, similar to "shelve".
3571
To merge the latest revision from bzr.dev::
3573
bzr merge ../bzr.dev
3575
To merge changes up to and including revision 82 from bzr.dev::
3577
bzr merge -r 82 ../bzr.dev
3579
To merge the changes introduced by 82, without previous changes::
3581
bzr merge -r 81..82 ../bzr.dev
3583
To apply a merge directive contained in /tmp/merge:
3585
bzr merge /tmp/merge
2117
The following merge types are available:
3588
encoding_type = 'exact'
3589
_see_also = ['update', 'remerge', 'status-flags', 'send']
3590
takes_args = ['location?']
3595
help='Merge even if the destination tree has uncommitted changes.'),
3599
Option('show-base', help="Show base revision text in "
3601
Option('uncommitted', help='Apply uncommitted changes'
3602
' from a working copy, instead of branch changes.'),
3603
Option('pull', help='If the destination is already'
3604
' completely merged into the source, pull from the'
3605
' source rather than merging. When this happens,'
3606
' you do not need to commit the result.'),
3608
help='Branch to merge into, '
3609
'rather than the one containing the working directory.',
3613
Option('preview', help='Instead of merging, show a diff of the'
3615
Option('interactive', help='Select changes interactively.',
3619
def run(self, location=None, revision=None, force=False,
3620
merge_type=None, show_base=False, reprocess=None, remember=False,
3621
uncommitted=False, pull=False,
2119
takes_args = ['branch?']
2120
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2121
Option('show-base', help="Show base revision text in "
2125
from merge import merge_type_help
2126
from inspect import getdoc
2127
return getdoc(self) + '\n' + merge_type_help()
2129
def run(self, branch=None, revision=None, force=False, merge_type=None,
2130
show_base=False, reprocess=False, remember=False):
3626
2131
if merge_type is None:
3627
merge_type = _mod_merge.Merge3Merger
3629
if directory is None: directory = u'.'
3630
possible_transports = []
3632
allow_pending = True
3633
verified = 'inapplicable'
3634
tree = WorkingTree.open_containing(directory)[0]
3636
# die as quickly as possible if there are uncommitted changes
3638
basis_tree = tree.revision_tree(tree.last_revision())
3639
except errors.NoSuchRevision:
3640
basis_tree = tree.basis_tree()
3642
if tree.has_changes(basis_tree):
3643
raise errors.UncommittedChanges(tree)
3645
view_info = _get_view_info_for_change_reporter(tree)
3646
change_reporter = delta._ChangeReporter(
3647
unversioned_filter=tree.is_ignored, view_info=view_info)
3650
pb = ui.ui_factory.nested_progress_bar()
3651
cleanups.append(pb.finished)
3653
cleanups.append(tree.unlock)
3654
if location is not None:
3656
mergeable = bundle.read_mergeable_from_url(location,
3657
possible_transports=possible_transports)
3658
except errors.NotABundle:
2132
merge_type = Merge3Merger
2134
tree = WorkingTree.open_containing(u'.')[0]
2136
if branch is not None:
2138
reader = bundle.read_bundle_from_url(branch)
2140
pass # Continue on considering this url a Branch
2142
conflicts = merge_bundle(reader, tree, not force, merge_type,
2143
reprocess, show_base)
3662
raise errors.BzrCommandError('Cannot use --uncommitted'
3663
' with bundles or merge directives.')
3665
if revision is not None:
3666
raise errors.BzrCommandError(
3667
'Cannot use -r with merge directives or bundles')
3668
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3671
if merger is None and uncommitted:
3672
if revision is not None and len(revision) > 0:
3673
raise errors.BzrCommandError('Cannot use --uncommitted and'
3674
' --revision at the same time.')
3675
merger = self.get_merger_from_uncommitted(tree, location, pb,
3677
allow_pending = False
3680
merger, allow_pending = self._get_merger_from_branch(tree,
3681
location, revision, remember, possible_transports, pb)
3683
merger.merge_type = merge_type
3684
merger.reprocess = reprocess
3685
merger.show_base = show_base
3686
self.sanity_check_merger(merger)
3687
if (merger.base_rev_id == merger.other_rev_id and
3688
merger.other_rev_id is not None):
3689
note('Nothing to do.')
2149
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2151
if revision is None or len(revision) < 1:
2153
other = [branch, -1]
2154
other_branch, path = Branch.open_containing(branch)
2156
if len(revision) == 1:
2158
other_branch, path = Branch.open_containing(branch)
2159
revno = revision[0].in_history(other_branch).revno
2160
other = [branch, revno]
2162
assert len(revision) == 2
2163
if None in revision:
2164
raise BzrCommandError(
2165
"Merge doesn't permit that revision specifier.")
2166
other_branch, path = Branch.open_containing(branch)
2168
base = [branch, revision[0].in_history(other_branch).revno]
2169
other = [branch, revision[1].in_history(other_branch).revno]
2171
if tree.branch.get_parent() is None or remember:
2172
tree.branch.set_parent(other_branch.base)
2175
interesting_files = [path]
2177
interesting_files = None
2178
pb = ui.ui_factory.nested_progress_bar()
2181
conflict_count = merge(other, base, check_clean=(not force),
2182
merge_type=merge_type,
2183
reprocess=reprocess,
2184
show_base=show_base,
2185
pb=pb, file_list=interesting_files)
2188
if conflict_count != 0:
3692
if merger.interesting_files is not None:
3693
raise errors.BzrCommandError('Cannot pull individual files')
3694
if (merger.base_rev_id == tree.last_revision()):
3695
result = tree.pull(merger.other_branch, False,
3696
merger.other_rev_id)
3697
result.report(self.outf)
3699
merger.check_basis(False)
3701
return self._do_preview(merger, cleanups)
3703
return self._do_interactive(merger, cleanups)
3705
return self._do_merge(merger, change_reporter, allow_pending,
3708
for cleanup in reversed(cleanups):
3711
def _get_preview(self, merger, cleanups):
3712
tree_merger = merger.make_merger()
3713
tt = tree_merger.make_preview_transform()
3714
cleanups.append(tt.finalize)
3715
result_tree = tt.get_preview_tree()
3718
def _do_preview(self, merger, cleanups):
3719
from bzrlib.diff import show_diff_trees
3720
result_tree = self._get_preview(merger, cleanups)
3721
show_diff_trees(merger.this_tree, result_tree, self.outf,
3722
old_label='', new_label='')
3724
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3725
merger.change_reporter = change_reporter
3726
conflict_count = merger.do_merge()
3728
merger.set_pending()
3729
if verified == 'failed':
3730
warning('Preview patch does not match changes')
3731
if conflict_count != 0:
3736
def _do_interactive(self, merger, cleanups):
3737
"""Perform an interactive merge.
3739
This works by generating a preview tree of the merge, then using
3740
Shelver to selectively remove the differences between the working tree
3741
and the preview tree.
3743
from bzrlib import shelf_ui
3744
result_tree = self._get_preview(merger, cleanups)
3745
writer = bzrlib.option.diff_writer_registry.get()
3746
shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
3747
reporter=shelf_ui.ApplyReporter(),
3748
diff_writer=writer(sys.stdout))
3751
def sanity_check_merger(self, merger):
3752
if (merger.show_base and
3753
not merger.merge_type is _mod_merge.Merge3Merger):
3754
raise errors.BzrCommandError("Show-base is not supported for this"
3755
" merge type. %s" % merger.merge_type)
3756
if merger.reprocess is None:
3757
if merger.show_base:
3758
merger.reprocess = False
3760
# Use reprocess if the merger supports it
3761
merger.reprocess = merger.merge_type.supports_reprocess
3762
if merger.reprocess and not merger.merge_type.supports_reprocess:
3763
raise errors.BzrCommandError("Conflict reduction is not supported"
3764
" for merge type %s." %
3766
if merger.reprocess and merger.show_base:
3767
raise errors.BzrCommandError("Cannot do conflict reduction and"
3770
def _get_merger_from_branch(self, tree, location, revision, remember,
3771
possible_transports, pb):
3772
"""Produce a merger from a location, assuming it refers to a branch."""
3773
from bzrlib.tag import _merge_tags_if_possible
3774
# find the branch locations
3775
other_loc, user_location = self._select_branch_location(tree, location,
3777
if revision is not None and len(revision) == 2:
3778
base_loc, _unused = self._select_branch_location(tree,
3779
location, revision, 0)
3781
base_loc = other_loc
3783
other_branch, other_path = Branch.open_containing(other_loc,
3784
possible_transports)
3785
if base_loc == other_loc:
3786
base_branch = other_branch
3788
base_branch, base_path = Branch.open_containing(base_loc,
3789
possible_transports)
3790
# Find the revision ids
3791
other_revision_id = None
3792
base_revision_id = None
3793
if revision is not None:
3794
if len(revision) >= 1:
3795
other_revision_id = revision[-1].as_revision_id(other_branch)
3796
if len(revision) == 2:
3797
base_revision_id = revision[0].as_revision_id(base_branch)
3798
if other_revision_id is None:
3799
other_revision_id = _mod_revision.ensure_null(
3800
other_branch.last_revision())
3801
# Remember where we merge from
3802
if ((remember or tree.branch.get_submit_branch() is None) and
3803
user_location is not None):
3804
tree.branch.set_submit_branch(other_branch.base)
3805
_merge_tags_if_possible(other_branch, tree.branch)
3806
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
3807
other_revision_id, base_revision_id, other_branch, base_branch)
3808
if other_path != '':
3809
allow_pending = False
3810
merger.interesting_files = [other_path]
3812
allow_pending = True
3813
return merger, allow_pending
3815
def get_merger_from_uncommitted(self, tree, location, pb, cleanups):
3816
"""Get a merger for uncommitted changes.
3818
:param tree: The tree the merger should apply to.
3819
:param location: The location containing uncommitted changes.
3820
:param pb: The progress bar to use for showing progress.
3821
:param cleanups: A list of operations to perform to clean up the
3822
temporary directories, unfinalized objects, etc.
3824
location = self._select_branch_location(tree, location)[0]
3825
other_tree, other_path = WorkingTree.open_containing(location)
3826
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree, pb)
3827
if other_path != '':
3828
merger.interesting_files = [other_path]
3831
def _select_branch_location(self, tree, user_location, revision=None,
3833
"""Select a branch location, according to possible inputs.
3835
If provided, branches from ``revision`` are preferred. (Both
3836
``revision`` and ``index`` must be supplied.)
3838
Otherwise, the ``location`` parameter is used. If it is None, then the
3839
``submit`` or ``parent`` location is used, and a note is printed.
3841
:param tree: The working tree to select a branch for merging into
3842
:param location: The location entered by the user
3843
:param revision: The revision parameter to the command
3844
:param index: The index to use for the revision parameter. Negative
3845
indices are permitted.
3846
:return: (selected_location, user_location). The default location
3847
will be the user-entered location.
3849
if (revision is not None and index is not None
3850
and revision[index] is not None):
3851
branch = revision[index].get_branch()
3852
if branch is not None:
3853
return branch, branch
3854
if user_location is None:
3855
location = self._get_remembered(tree, 'Merging from')
3857
location = user_location
3858
return location, user_location
3860
def _get_remembered(self, tree, verb_string):
2192
except errors.AmbiguousBase, e:
2193
m = ("sorry, bzr can't determine the right merge base yet\n"
2194
"candidates are:\n "
2195
+ "\n ".join(e.bases)
2197
"please specify an explicit base with -r,\n"
2198
"and (if you want) report this to the bzr developers\n")
2201
# TODO: move up to common parent; this isn't merge-specific anymore.
2202
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3861
2203
"""Use tree.branch's parent if none was supplied.
3863
2205
Report if the remembered location was used.
3865
stored_location = tree.branch.get_submit_branch()
3866
stored_location_type = "submit"
3867
if stored_location is None:
3868
stored_location = tree.branch.get_parent()
3869
stored_location_type = "parent"
2207
if supplied_location is not None:
2208
return supplied_location
2209
stored_location = tree.branch.get_parent()
3870
2210
mutter("%s", stored_location)
3871
2211
if stored_location is None:
3872
raise errors.BzrCommandError("No location specified or remembered")
3873
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3874
note(u"%s remembered %s location %s", verb_string,
3875
stored_location_type, display_url)
2212
raise BzrCommandError("No location specified or remembered")
2213
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2214
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
3876
2215
return stored_location
3978
2308
class cmd_revert(Command):
3979
"""Revert files to a previous revision.
3981
Giving a list of files will revert only those files. Otherwise, all files
3982
will be reverted. If the revision is not specified with '--revision', the
3983
last committed revision is used.
3985
To remove only some changes, without reverting to a prior version, use
3986
merge instead. For example, "merge . --revision -2..-3" will remove the
3987
changes introduced by -2, without affecting the changes introduced by -1.
3988
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3990
By default, any files that have been manually changed will be backed up
3991
first. (Files changed only by merge are not backed up.) Backup files have
3992
'.~#~' appended to their name, where # is a number.
3994
When you provide files, you can use their current pathname or the pathname
3995
from the target revision. So you can use revert to "undelete" a file by
3996
name. If you name a directory, all the contents of that directory will be
3999
Any files that have been newly added since that revision will be deleted,
4000
with a backup kept if appropriate. Directories containing unknown files
4001
will not be deleted.
4003
The working tree contains a list of pending merged revisions, which will
4004
be included as parents in the next commit. Normally, revert clears that
4005
list as well as reverting the files. If any files are specified, revert
4006
leaves the pending merge list alone and reverts only the files. Use "bzr
4007
revert ." in the tree root to revert all files but keep the merge record,
4008
and "bzr revert --forget-merges" to clear the pending merge list without
4009
reverting any files.
2309
"""Reverse all changes since the last commit.
2311
Only versioned files are affected. Specify filenames to revert only
2312
those files. By default, any files that are changed will be backed up
2313
first. Backup files have a '~' appended to their name.
4012
_see_also = ['cat', 'export']
4015
Option('no-backup', "Do not save backups of reverted files."),
4016
Option('forget-merges',
4017
'Remove pending merge marker, without changing any files.'),
2315
takes_options = ['revision', 'no-backup']
4019
2316
takes_args = ['file*']
2317
aliases = ['merge-revert']
4021
def run(self, revision=None, no_backup=False, file_list=None,
4022
forget_merges=None):
2319
def run(self, revision=None, no_backup=False, file_list=None):
2320
from bzrlib.commands import parse_spec
2321
if file_list is not None:
2322
if len(file_list) == 0:
2323
raise BzrCommandError("No files specified")
4023
2327
tree, file_list = tree_files(file_list)
4027
tree.set_parent_ids(tree.get_parent_ids()[:1])
4029
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
4034
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4035
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
2328
if revision is None:
2329
# FIXME should be tree.last_revision
2330
rev_id = tree.last_revision()
2331
elif len(revision) != 1:
2332
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2334
rev_id = revision[0].in_history(tree.branch).rev_id
4036
2335
pb = ui.ui_factory.nested_progress_bar()
4038
tree.revert(file_list, rev_tree, not no_backup, pb,
4039
report_changes=True)
2337
tree.revert(file_list,
2338
tree.branch.repository.revision_tree(rev_id),
4044
2344
class cmd_assert_fail(Command):
4045
2345
"""Test reporting of assertion failures"""
4046
# intended just for use in testing
4051
raise AssertionError("always fails")
2348
assert False, "always fails"
4054
2351
class cmd_help(Command):
4055
2352
"""Show help on a command or other topic.
4058
_see_also = ['topics']
4060
Option('long', 'Show help on all commands.'),
2354
For a list of all available commands, say 'bzr help commands'."""
2355
takes_options = [Option('long', 'show help on all commands')]
4062
2356
takes_args = ['topic?']
4063
2357
aliases = ['?', '--help', '-?', '-h']
4065
2359
@display_command
4066
2360
def run(self, topic=None, long=False):
4068
2362
if topic is None and long:
4069
2363
topic = "commands"
4070
bzrlib.help.help(topic)
4073
2367
class cmd_shell_complete(Command):
4074
2368
"""Show appropriate completions for context.
4076
For a list of all available commands, say 'bzr shell-complete'.
2370
For a list of all available commands, say 'bzr shell-complete'."""
4078
2371
takes_args = ['context?']
4079
2372
aliases = ['s-c']
4082
2375
@display_command
4083
2376
def run(self, context=None):
4084
2377
import shellcomplete
4085
2378
shellcomplete.shellcomplete(context)
2381
class cmd_fetch(Command):
2382
"""Copy in history from another branch but don't merge it.
2384
This is an internal method used for pull and merge."""
2386
takes_args = ['from_branch', 'to_branch']
2387
def run(self, from_branch, to_branch):
2388
from bzrlib.fetch import Fetcher
2389
from_b = Branch.open(from_branch)
2390
to_b = Branch.open(to_branch)
2391
Fetcher(to_b, from_b)
4088
2394
class cmd_missing(Command):
4089
2395
"""Show unmerged/unpulled revisions between two branches.
4091
OTHER_BRANCH may be local or remote.
4093
To filter on a range of revisions, you can use the command -r begin..end
4094
-r revision requests a specific revision, -r ..end or -r begin.. are
4099
Determine the missing revisions between this and the branch at the
4100
remembered pull location::
4104
Determine the missing revisions between this and another branch::
4106
bzr missing http://server/branch
4108
Determine the missing revisions up to a specific revision on the other
4111
bzr missing -r ..-10
4113
Determine the missing revisions up to a specific revision on this
4116
bzr missing --my-revision ..-10
4119
_see_also = ['merge', 'pull']
2397
OTHER_BRANCH may be local or remote."""
4120
2398
takes_args = ['other_branch?']
4122
Option('reverse', 'Reverse the order of revisions.'),
4124
'Display changes in the local branch only.'),
4125
Option('this' , 'Same as --mine-only.'),
4126
Option('theirs-only',
4127
'Display changes in the remote branch only.'),
4128
Option('other', 'Same as --theirs-only.'),
4132
custom_help('revision',
4133
help='Filter on other branch revisions (inclusive). '
4134
'See "help revisionspec" for details.'),
4135
Option('my-revision',
4136
type=_parse_revision_str,
4137
help='Filter on local branch revisions (inclusive). '
4138
'See "help revisionspec" for details.'),
4139
Option('include-merges',
4140
'Show all revisions in addition to the mainline ones.'),
2399
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2401
'Display changes in the local branch only'),
2402
Option('theirs-only',
2403
'Display changes in the remote branch only'),
4142
2411
encoding_type = 'replace'
4144
2413
@display_command
4145
2414
def run(self, other_branch=None, reverse=False, mine_only=False,
4147
log_format=None, long=False, short=False, line=False,
4148
show_ids=False, verbose=False, this=False, other=False,
4149
include_merges=False, revision=None, my_revision=None):
4150
from bzrlib.missing import find_unmerged, iter_log_revisions
4159
# TODO: We should probably check that we don't have mine-only and
4160
# theirs-only set, but it gets complicated because we also have
4161
# this and other which could be used.
2415
theirs_only=False, log_format=None, long=False, short=False, line=False,
2416
show_ids=False, verbose=False):
2417
from bzrlib.missing import find_unmerged, iter_log_data
2418
from bzrlib.log import log_formatter
4168
2419
local_branch = Branch.open_containing(u".")[0]
4169
2420
parent = local_branch.get_parent()
4170
2421
if other_branch is None:
4171
2422
other_branch = parent
4172
2423
if other_branch is None:
4173
raise errors.BzrCommandError("No peer location known"
4175
display_url = urlutils.unescape_for_display(parent,
4177
message("Using saved parent location: "
4178
+ display_url + "\n")
2424
raise BzrCommandError("No peer location known or specified.")
2425
print "Using last location: " + local_branch.get_parent()
4180
2426
remote_branch = Branch.open(other_branch)
4181
2427
if remote_branch.base == local_branch.base:
4182
2428
remote_branch = local_branch
4184
local_revid_range = _revision_range_to_revid_range(
4185
_get_revision_range(my_revision, local_branch,
4188
remote_revid_range = _revision_range_to_revid_range(
4189
_get_revision_range(revision,
4190
remote_branch, self.name()))
4192
2429
local_branch.lock_read()
4194
2431
remote_branch.lock_read()
4196
local_extra, remote_extra = find_unmerged(
4197
local_branch, remote_branch, restrict,
4198
backward=not reverse,
4199
include_merges=include_merges,
4200
local_revid_range=local_revid_range,
4201
remote_revid_range=remote_revid_range)
4203
if log_format is None:
4204
registry = log.log_formatter_registry
4205
log_format = registry.get_default(local_branch)
4206
lf = log_format(to_file=self.outf,
4208
show_timezone='original')
2433
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2434
if (log_format == None):
2435
default = local_branch.get_config().log_format()
2436
log_format = get_log_format(long=long, short=short,
2437
line=line, default=default)
2438
lf = log_formatter(log_format,
2441
show_timezone='original')
2442
if reverse is False:
2443
local_extra.reverse()
2444
remote_extra.reverse()
4211
2445
if local_extra and not theirs_only:
4212
message("You have %d extra revision(s):\n" %
4214
for revision in iter_log_revisions(local_extra,
4215
local_branch.repository,
4217
lf.log_revision(revision)
2446
print "You have %d extra revision(s):" % len(local_extra)
2447
for data in iter_log_data(local_extra, local_branch.repository,
4218
2450
printed_local = True
4221
2452
printed_local = False
4223
2453
if remote_extra and not mine_only:
4224
2454
if printed_local is True:
4226
message("You are missing %d revision(s):\n" %
4228
for revision in iter_log_revisions(remote_extra,
4229
remote_branch.repository,
4231
lf.log_revision(revision)
2456
print "You are missing %d revision(s):" % len(remote_extra)
2457
for data in iter_log_data(remote_extra, remote_branch.repository,
2460
if not remote_extra and not local_extra:
2462
print "Branches are up to date."
4232
2464
status_code = 1
4234
if mine_only and not local_extra:
4235
# We checked local, and found nothing extra
4236
message('This branch is up to date.\n')
4237
elif theirs_only and not remote_extra:
4238
# We checked remote, and found nothing extra
4239
message('Other branch is up to date.\n')
4240
elif not (mine_only or theirs_only or local_extra or
4242
# We checked both branches, and neither one had extra
4244
message("Branches are up to date.\n")
4246
2466
remote_branch.unlock()
4664
2745
control.break_lock()
4665
2746
except NotImplementedError:
4669
class cmd_wait_until_signalled(Command):
4670
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4672
This just prints a line to signal when it is ready, then blocks on stdin.
4678
sys.stdout.write("running\n")
4680
sys.stdin.readline()
4683
class cmd_serve(Command):
4684
"""Run the bzr server."""
4686
aliases = ['server']
4690
help='Serve on stdin/out for use from inetd or sshd.'),
4691
RegistryOption('protocol',
4692
help="Protocol to serve.",
4693
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4694
value_switches=True),
4696
help='Listen for connections on nominated port of the form '
4697
'[hostname:]portnumber. Passing 0 as the port number will '
4698
'result in a dynamically allocated port. The default port '
4699
'depends on the protocol.',
4702
help='Serve contents of this directory.',
4704
Option('allow-writes',
4705
help='By default the server is a readonly server. Supplying '
4706
'--allow-writes enables write access to the contents of '
4707
'the served directory and below.'
4711
def get_host_and_port(self, port):
4712
"""Return the host and port to run the smart server on.
4714
If 'port' is None, None will be returned for the host and port.
4716
If 'port' has a colon in it, the string before the colon will be
4717
interpreted as the host.
4719
:param port: A string of the port to run the server on.
4720
:return: A tuple of (host, port), where 'host' is a host name or IP,
4721
and port is an integer TCP/IP port.
4724
if port is not None:
4726
host, port = port.split(':')
4730
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4732
from bzrlib.transport import get_transport, transport_server_registry
4733
if directory is None:
4734
directory = os.getcwd()
4735
if protocol is None:
4736
protocol = transport_server_registry.get()
4737
host, port = self.get_host_and_port(port)
4738
url = urlutils.local_path_to_url(directory)
4739
if not allow_writes:
4740
url = 'readonly+' + url
4741
transport = get_transport(url)
4742
protocol(transport, host, port, inet)
4745
class cmd_join(Command):
4746
"""Combine a tree into its containing tree.
4748
This command requires the target tree to be in a rich-root format.
4750
The TREE argument should be an independent tree, inside another tree, but
4751
not part of it. (Such trees can be produced by "bzr split", but also by
4752
running "bzr branch" with the target inside a tree.)
4754
The result is a combined tree, with the subtree no longer an independant
4755
part. This is marked as a merge of the subtree into the containing tree,
4756
and all history is preserved.
4759
_see_also = ['split']
4760
takes_args = ['tree']
4762
Option('reference', help='Join by reference.', hidden=True),
4765
def run(self, tree, reference=False):
4766
sub_tree = WorkingTree.open(tree)
4767
parent_dir = osutils.dirname(sub_tree.basedir)
4768
containing_tree = WorkingTree.open_containing(parent_dir)[0]
4769
repo = containing_tree.branch.repository
4770
if not repo.supports_rich_root():
4771
raise errors.BzrCommandError(
4772
"Can't join trees because %s doesn't support rich root data.\n"
4773
"You can use bzr upgrade on the repository."
4777
containing_tree.add_reference(sub_tree)
4778
except errors.BadReferenceTarget, e:
4779
# XXX: Would be better to just raise a nicely printable
4780
# exception from the real origin. Also below. mbp 20070306
4781
raise errors.BzrCommandError("Cannot join %s. %s" %
4785
containing_tree.subsume(sub_tree)
4786
except errors.BadSubsumeSource, e:
4787
raise errors.BzrCommandError("Cannot join %s. %s" %
4791
class cmd_split(Command):
4792
"""Split a subdirectory of a tree into a separate tree.
4794
This command will produce a target tree in a format that supports
4795
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
4796
converted into earlier formats like 'dirstate-tags'.
4798
The TREE argument should be a subdirectory of a working tree. That
4799
subdirectory will be converted into an independent tree, with its own
4800
branch. Commits in the top-level tree will not apply to the new subtree.
4803
_see_also = ['join']
4804
takes_args = ['tree']
4806
def run(self, tree):
4807
containing_tree, subdir = WorkingTree.open_containing(tree)
4808
sub_id = containing_tree.path2id(subdir)
4810
raise errors.NotVersionedError(subdir)
4812
containing_tree.extract(sub_id)
4813
except errors.RootNotRich:
4814
raise errors.RichRootUpgradeRequired(containing_tree.branch.base)
4817
class cmd_merge_directive(Command):
4818
"""Generate a merge directive for auto-merge tools.
4820
A directive requests a merge to be performed, and also provides all the
4821
information necessary to do so. This means it must either include a
4822
revision bundle, or the location of a branch containing the desired
4825
A submit branch (the location to merge into) must be supplied the first
4826
time the command is issued. After it has been supplied once, it will
4827
be remembered as the default.
4829
A public branch is optional if a revision bundle is supplied, but required
4830
if --diff or --plain is specified. It will be remembered as the default
4831
after the first use.
4834
takes_args = ['submit_branch?', 'public_branch?']
4838
_see_also = ['send']
4841
RegistryOption.from_kwargs('patch-type',
4842
'The type of patch to include in the directive.',
4844
value_switches=True,
4846
bundle='Bazaar revision bundle (default).',
4847
diff='Normal unified diff.',
4848
plain='No patch, just directive.'),
4849
Option('sign', help='GPG-sign the directive.'), 'revision',
4850
Option('mail-to', type=str,
4851
help='Instead of printing the directive, email to this address.'),
4852
Option('message', type=str, short_name='m',
4853
help='Message to use when committing this merge.')
4856
encoding_type = 'exact'
4858
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
4859
sign=False, revision=None, mail_to=None, message=None):
4860
from bzrlib.revision import ensure_null, NULL_REVISION
4861
include_patch, include_bundle = {
4862
'plain': (False, False),
4863
'diff': (True, False),
4864
'bundle': (True, True),
4866
branch = Branch.open('.')
4867
stored_submit_branch = branch.get_submit_branch()
4868
if submit_branch is None:
4869
submit_branch = stored_submit_branch
4871
if stored_submit_branch is None:
4872
branch.set_submit_branch(submit_branch)
4873
if submit_branch is None:
4874
submit_branch = branch.get_parent()
4875
if submit_branch is None:
4876
raise errors.BzrCommandError('No submit branch specified or known')
4878
stored_public_branch = branch.get_public_branch()
4879
if public_branch is None:
4880
public_branch = stored_public_branch
4881
elif stored_public_branch is None:
4882
branch.set_public_branch(public_branch)
4883
if not include_bundle and public_branch is None:
4884
raise errors.BzrCommandError('No public branch specified or'
4886
base_revision_id = None
4887
if revision is not None:
4888
if len(revision) > 2:
4889
raise errors.BzrCommandError('bzr merge-directive takes '
4890
'at most two one revision identifiers')
4891
revision_id = revision[-1].as_revision_id(branch)
4892
if len(revision) == 2:
4893
base_revision_id = revision[0].as_revision_id(branch)
4895
revision_id = branch.last_revision()
4896
revision_id = ensure_null(revision_id)
4897
if revision_id == NULL_REVISION:
4898
raise errors.BzrCommandError('No revisions to bundle.')
4899
directive = merge_directive.MergeDirective2.from_objects(
4900
branch.repository, revision_id, time.time(),
4901
osutils.local_time_offset(), submit_branch,
4902
public_branch=public_branch, include_patch=include_patch,
4903
include_bundle=include_bundle, message=message,
4904
base_revision_id=base_revision_id)
4907
self.outf.write(directive.to_signed(branch))
4909
self.outf.writelines(directive.to_lines())
4911
message = directive.to_email(mail_to, branch, sign)
4912
s = SMTPConnection(branch.get_config())
4913
s.send_email(message)
4916
class cmd_send(Command):
4917
"""Mail or create a merge-directive for submitting changes.
4919
A merge directive provides many things needed for requesting merges:
4921
* A machine-readable description of the merge to perform
4923
* An optional patch that is a preview of the changes requested
4925
* An optional bundle of revision data, so that the changes can be applied
4926
directly from the merge directive, without retrieving data from a
4929
If --no-bundle is specified, then public_branch is needed (and must be
4930
up-to-date), so that the receiver can perform the merge using the
4931
public_branch. The public_branch is always included if known, so that
4932
people can check it later.
4934
The submit branch defaults to the parent, but can be overridden. Both
4935
submit branch and public branch will be remembered if supplied.
4937
If a public_branch is known for the submit_branch, that public submit
4938
branch is used in the merge instructions. This means that a local mirror
4939
can be used as your actual submit branch, once you have set public_branch
4942
Mail is sent using your preferred mail program. This should be transparent
4943
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4944
If the preferred client can't be found (or used), your editor will be used.
4946
To use a specific mail program, set the mail_client configuration option.
4947
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4948
specific clients are "claws", "evolution", "kmail", "mutt", and
4949
"thunderbird"; generic options are "default", "editor", "emacsclient",
4950
"mapi", and "xdg-email". Plugins may also add supported clients.
4952
If mail is being sent, a to address is required. This can be supplied
4953
either on the commandline, by setting the submit_to configuration
4954
option in the branch itself or the child_submit_to configuration option
4955
in the submit branch.
4957
Two formats are currently supported: "4" uses revision bundle format 4 and
4958
merge directive format 2. It is significantly faster and smaller than
4959
older formats. It is compatible with Bazaar 0.19 and later. It is the
4960
default. "0.9" uses revision bundle format 0.9 and merge directive
4961
format 1. It is compatible with Bazaar 0.12 - 0.18.
4963
The merge directives created by bzr send may be applied using bzr merge or
4964
bzr pull by specifying a file containing a merge directive as the location.
4967
encoding_type = 'exact'
4969
_see_also = ['merge', 'pull']
4971
takes_args = ['submit_branch?', 'public_branch?']
4975
help='Do not include a bundle in the merge directive.'),
4976
Option('no-patch', help='Do not include a preview patch in the merge'
4979
help='Remember submit and public branch.'),
4981
help='Branch to generate the submission from, '
4982
'rather than the one containing the working directory.',
4985
Option('output', short_name='o',
4986
help='Write merge directive to this file; '
4987
'use - for stdout.',
4990
help='Refuse to send if there are uncommitted changes in'
4991
' the working tree, --no-strict disables the check.'),
4992
Option('mail-to', help='Mail the request to this address.',
4996
Option('body', help='Body for the email.', type=unicode),
4997
RegistryOption('format',
4998
help='Use the specified output format.',
4999
lazy_registry=('bzrlib.send', 'format_registry')),
5002
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5003
no_patch=False, revision=None, remember=False, output=None,
5004
format=None, mail_to=None, message=None, body=None,
5005
strict=None, **kwargs):
5006
from bzrlib.send import send
5007
return send(submit_branch, revision, public_branch, remember,
5008
format, no_bundle, no_patch, output,
5009
kwargs.get('from', '.'), mail_to, message, body,
5014
class cmd_bundle_revisions(cmd_send):
5015
"""Create a merge-directive for submitting changes.
5017
A merge directive provides many things needed for requesting merges:
5019
* A machine-readable description of the merge to perform
5021
* An optional patch that is a preview of the changes requested
5023
* An optional bundle of revision data, so that the changes can be applied
5024
directly from the merge directive, without retrieving data from a
5027
If --no-bundle is specified, then public_branch is needed (and must be
5028
up-to-date), so that the receiver can perform the merge using the
5029
public_branch. The public_branch is always included if known, so that
5030
people can check it later.
5032
The submit branch defaults to the parent, but can be overridden. Both
5033
submit branch and public branch will be remembered if supplied.
5035
If a public_branch is known for the submit_branch, that public submit
5036
branch is used in the merge instructions. This means that a local mirror
5037
can be used as your actual submit branch, once you have set public_branch
5040
Two formats are currently supported: "4" uses revision bundle format 4 and
5041
merge directive format 2. It is significantly faster and smaller than
5042
older formats. It is compatible with Bazaar 0.19 and later. It is the
5043
default. "0.9" uses revision bundle format 0.9 and merge directive
5044
format 1. It is compatible with Bazaar 0.12 - 0.18.
5049
help='Do not include a bundle in the merge directive.'),
5050
Option('no-patch', help='Do not include a preview patch in the merge'
5053
help='Remember submit and public branch.'),
5055
help='Branch to generate the submission from, '
5056
'rather than the one containing the working directory.',
5059
Option('output', short_name='o', help='Write directive to this file.',
5062
help='Refuse to bundle revisions if there are uncommitted'
5063
' changes in the working tree, --no-strict disables the check.'),
5065
RegistryOption('format',
5066
help='Use the specified output format.',
5067
lazy_registry=('bzrlib.send', 'format_registry')),
5069
aliases = ['bundle']
5071
_see_also = ['send', 'merge']
5075
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5076
no_patch=False, revision=None, remember=False, output=None,
5077
format=None, strict=None, **kwargs):
5080
from bzrlib.send import send
5081
return send(submit_branch, revision, public_branch, remember,
5082
format, no_bundle, no_patch, output,
5083
kwargs.get('from', '.'), None, None, None,
5084
self.outf, strict=strict)
5087
class cmd_tag(Command):
5088
"""Create, remove or modify a tag naming a revision.
5090
Tags give human-meaningful names to revisions. Commands that take a -r
5091
(--revision) option can be given -rtag:X, where X is any previously
5094
Tags are stored in the branch. Tags are copied from one branch to another
5095
along when you branch, push, pull or merge.
5097
It is an error to give a tag name that already exists unless you pass
5098
--force, in which case the tag is moved to point to the new revision.
5100
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5101
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5104
_see_also = ['commit', 'tags']
5105
takes_args = ['tag_name']
5108
help='Delete this tag rather than placing it.',
5111
help='Branch in which to place the tag.',
5116
help='Replace existing tags.',
5121
def run(self, tag_name,
5127
branch, relpath = Branch.open_containing(directory)
5131
branch.tags.delete_tag(tag_name)
5132
self.outf.write('Deleted tag %s.\n' % tag_name)
5135
if len(revision) != 1:
5136
raise errors.BzrCommandError(
5137
"Tags can only be placed on a single revision, "
5139
revision_id = revision[0].as_revision_id(branch)
5141
revision_id = branch.last_revision()
5142
if (not force) and branch.tags.has_tag(tag_name):
5143
raise errors.TagAlreadyExists(tag_name)
5144
branch.tags.set_tag(tag_name, revision_id)
5145
self.outf.write('Created tag %s.\n' % tag_name)
5150
class cmd_tags(Command):
5153
This command shows a table of tag names and the revisions they reference.
5159
help='Branch whose tags should be displayed.',
5163
RegistryOption.from_kwargs('sort',
5164
'Sort tags by different criteria.', title='Sorting',
5165
alpha='Sort tags lexicographically (default).',
5166
time='Sort tags chronologically.',
5179
branch, relpath = Branch.open_containing(directory)
5181
tags = branch.tags.get_tag_dict().items()
5188
graph = branch.repository.get_graph()
5189
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5190
revid1, revid2 = rev1.rev_id, rev2.rev_id
5191
# only show revisions between revid1 and revid2 (inclusive)
5192
tags = [(tag, revid) for tag, revid in tags if
5193
graph.is_between(revid, revid1, revid2)]
5196
elif sort == 'time':
5198
for tag, revid in tags:
5200
revobj = branch.repository.get_revision(revid)
5201
except errors.NoSuchRevision:
5202
timestamp = sys.maxint # place them at the end
5204
timestamp = revobj.timestamp
5205
timestamps[revid] = timestamp
5206
tags.sort(key=lambda x: timestamps[x[1]])
5208
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5209
for index, (tag, revid) in enumerate(tags):
5211
revno = branch.revision_id_to_dotted_revno(revid)
5212
if isinstance(revno, tuple):
5213
revno = '.'.join(map(str, revno))
5214
except errors.NoSuchRevision:
5215
# Bad tag data/merges can lead to tagged revisions
5216
# which are not in this branch. Fail gracefully ...
5218
tags[index] = (tag, revno)
5221
for tag, revspec in tags:
5222
self.outf.write('%-20s %s\n' % (tag, revspec))
5225
class cmd_reconfigure(Command):
5226
"""Reconfigure the type of a bzr directory.
5228
A target configuration must be specified.
5230
For checkouts, the bind-to location will be auto-detected if not specified.
5231
The order of preference is
5232
1. For a lightweight checkout, the current bound location.
5233
2. For branches that used to be checkouts, the previously-bound location.
5234
3. The push location.
5235
4. The parent location.
5236
If none of these is available, --bind-to must be specified.
5239
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5240
takes_args = ['location?']
5242
RegistryOption.from_kwargs(
5244
title='Target type',
5245
help='The type to reconfigure the directory to.',
5246
value_switches=True, enum_switch=False,
5247
branch='Reconfigure to be an unbound branch with no working tree.',
5248
tree='Reconfigure to be an unbound branch with a working tree.',
5249
checkout='Reconfigure to be a bound branch with a working tree.',
5250
lightweight_checkout='Reconfigure to be a lightweight'
5251
' checkout (with no local history).',
5252
standalone='Reconfigure to be a standalone branch '
5253
'(i.e. stop using shared repository).',
5254
use_shared='Reconfigure to use a shared repository.',
5255
with_trees='Reconfigure repository to create '
5256
'working trees on branches by default.',
5257
with_no_trees='Reconfigure repository to not create '
5258
'working trees on branches by default.'
5260
Option('bind-to', help='Branch to bind checkout to.', type=str),
5262
help='Perform reconfiguration even if local changes'
5266
def run(self, location=None, target_type=None, bind_to=None, force=False):
5267
directory = bzrdir.BzrDir.open(location)
5268
if target_type is None:
5269
raise errors.BzrCommandError('No target configuration specified')
5270
elif target_type == 'branch':
5271
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5272
elif target_type == 'tree':
5273
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5274
elif target_type == 'checkout':
5275
reconfiguration = reconfigure.Reconfigure.to_checkout(
5277
elif target_type == 'lightweight-checkout':
5278
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5280
elif target_type == 'use-shared':
5281
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5282
elif target_type == 'standalone':
5283
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5284
elif target_type == 'with-trees':
5285
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5287
elif target_type == 'with-no-trees':
5288
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5290
reconfiguration.apply(force)
5293
class cmd_switch(Command):
5294
"""Set the branch of a checkout and update.
5296
For lightweight checkouts, this changes the branch being referenced.
5297
For heavyweight checkouts, this checks that there are no local commits
5298
versus the current bound branch, then it makes the local branch a mirror
5299
of the new location and binds to it.
5301
In both cases, the working tree is updated and uncommitted changes
5302
are merged. The user can commit or revert these as they desire.
5304
Pending merges need to be committed or reverted before using switch.
5306
The path to the branch to switch to can be specified relative to the parent
5307
directory of the current branch. For example, if you are currently in a
5308
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5311
Bound branches use the nickname of its master branch unless it is set
5312
locally, in which case switching will update the the local nickname to be
5316
takes_args = ['to_location']
5317
takes_options = [Option('force',
5318
help='Switch even if local commits will be lost.'),
5319
Option('create-branch', short_name='b',
5320
help='Create the target branch from this one before'
5321
' switching to it.'),
5324
def run(self, to_location, force=False, create_branch=False):
5325
from bzrlib import switch
5327
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5329
branch = control_dir.open_branch()
5330
had_explicit_nick = branch.get_config().has_explicit_nickname()
5331
except errors.NotBranchError:
5333
had_explicit_nick = False
5336
raise errors.BzrCommandError('cannot create branch without'
5338
if '/' not in to_location and '\\' not in to_location:
5339
# This path is meant to be relative to the existing branch
5340
this_url = self._get_branch_location(control_dir)
5341
to_location = urlutils.join(this_url, '..', to_location)
5342
to_branch = branch.bzrdir.sprout(to_location,
5343
possible_transports=[branch.bzrdir.root_transport],
5344
source_branch=branch).open_branch()
5346
# from_branch = control_dir.open_branch()
5347
# except errors.NotBranchError:
5348
# raise BzrCommandError('Cannot create a branch from this'
5349
# ' location when we cannot open this branch')
5350
# from_branch.bzrdir.sprout(
5354
to_branch = Branch.open(to_location)
5355
except errors.NotBranchError:
5356
this_url = self._get_branch_location(control_dir)
5357
to_branch = Branch.open(
5358
urlutils.join(this_url, '..', to_location))
5359
switch.switch(control_dir, to_branch, force)
5360
if had_explicit_nick:
5361
branch = control_dir.open_branch() #get the new branch!
5362
branch.nick = to_branch.nick
5363
note('Switched to branch: %s',
5364
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5366
def _get_branch_location(self, control_dir):
5367
"""Return location of branch for this control dir."""
5369
this_branch = control_dir.open_branch()
5370
# This may be a heavy checkout, where we want the master branch
5371
master_location = this_branch.get_bound_location()
5372
if master_location is not None:
5373
return master_location
5374
# If not, use a local sibling
5375
return this_branch.base
5376
except errors.NotBranchError:
5377
format = control_dir.find_branch_format()
5378
if getattr(format, 'get_reference', None) is not None:
5379
return format.get_reference(control_dir)
5381
return control_dir.root_transport.base
5384
class cmd_view(Command):
5385
"""Manage filtered views.
5387
Views provide a mask over the tree so that users can focus on
5388
a subset of a tree when doing their work. After creating a view,
5389
commands that support a list of files - status, diff, commit, etc -
5390
effectively have that list of files implicitly given each time.
5391
An explicit list of files can still be given but those files
5392
must be within the current view.
5394
In most cases, a view has a short life-span: it is created to make
5395
a selected change and is deleted once that change is committed.
5396
At other times, you may wish to create one or more named views
5397
and switch between them.
5399
To disable the current view without deleting it, you can switch to
5400
the pseudo view called ``off``. This can be useful when you need
5401
to see the whole tree for an operation or two (e.g. merge) but
5402
want to switch back to your view after that.
5405
To define the current view::
5407
bzr view file1 dir1 ...
5409
To list the current view::
5413
To delete the current view::
5417
To disable the current view without deleting it::
5419
bzr view --switch off
5421
To define a named view and switch to it::
5423
bzr view --name view-name file1 dir1 ...
5425
To list a named view::
5427
bzr view --name view-name
5429
To delete a named view::
5431
bzr view --name view-name --delete
5433
To switch to a named view::
5435
bzr view --switch view-name
5437
To list all views defined::
5441
To delete all views::
5443
bzr view --delete --all
5447
takes_args = ['file*']
5450
help='Apply list or delete action to all views.',
5453
help='Delete the view.',
5456
help='Name of the view to define, list or delete.',
5460
help='Name of the view to switch to.',
5465
def run(self, file_list,
5471
tree, file_list = tree_files(file_list, apply_view=False)
5472
current_view, view_dict = tree.views.get_view_info()
5477
raise errors.BzrCommandError(
5478
"Both --delete and a file list specified")
5480
raise errors.BzrCommandError(
5481
"Both --delete and --switch specified")
5483
tree.views.set_view_info(None, {})
5484
self.outf.write("Deleted all views.\n")
5486
raise errors.BzrCommandError("No current view to delete")
5488
tree.views.delete_view(name)
5489
self.outf.write("Deleted '%s' view.\n" % name)
5492
raise errors.BzrCommandError(
5493
"Both --switch and a file list specified")
5495
raise errors.BzrCommandError(
5496
"Both --switch and --all specified")
5497
elif switch == 'off':
5498
if current_view is None:
5499
raise errors.BzrCommandError("No current view to disable")
5500
tree.views.set_view_info(None, view_dict)
5501
self.outf.write("Disabled '%s' view.\n" % (current_view))
5503
tree.views.set_view_info(switch, view_dict)
5504
view_str = views.view_display_str(tree.views.lookup_view())
5505
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5508
self.outf.write('Views defined:\n')
5509
for view in sorted(view_dict):
5510
if view == current_view:
5514
view_str = views.view_display_str(view_dict[view])
5515
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5517
self.outf.write('No views defined.\n')
5520
# No name given and no current view set
5523
raise errors.BzrCommandError(
5524
"Cannot change the 'off' pseudo view")
5525
tree.views.set_view(name, sorted(file_list))
5526
view_str = views.view_display_str(tree.views.lookup_view())
5527
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5531
# No name given and no current view set
5532
self.outf.write('No current view.\n')
5534
view_str = views.view_display_str(tree.views.lookup_view(name))
5535
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5538
class cmd_hooks(Command):
5544
for hook_key in sorted(hooks.known_hooks.keys()):
5545
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5546
self.outf.write("%s:\n" % type(some_hooks).__name__)
5547
for hook_name, hook_point in sorted(some_hooks.items()):
5548
self.outf.write(" %s:\n" % (hook_name,))
5549
found_hooks = list(hook_point)
5551
for hook in found_hooks:
5552
self.outf.write(" %s\n" %
5553
(some_hooks.get_hook_name(hook),))
5555
self.outf.write(" <no hooks installed>\n")
5558
class cmd_shelve(Command):
5559
"""Temporarily set aside some changes from the current tree.
5561
Shelve allows you to temporarily put changes you've made "on the shelf",
5562
ie. out of the way, until a later time when you can bring them back from
5563
the shelf with the 'unshelve' command. The changes are stored alongside
5564
your working tree, and so they aren't propagated along with your branch nor
5565
will they survive its deletion.
5567
If shelve --list is specified, previously-shelved changes are listed.
5569
Shelve is intended to help separate several sets of changes that have
5570
been inappropriately mingled. If you just want to get rid of all changes
5571
and you don't need to restore them later, use revert. If you want to
5572
shelve all text changes at once, use shelve --all.
5574
If filenames are specified, only the changes to those files will be
5575
shelved. Other files will be left untouched.
5577
If a revision is specified, changes since that revision will be shelved.
5579
You can put multiple items on the shelf, and by default, 'unshelve' will
5580
restore the most recently shelved changes.
5583
takes_args = ['file*']
5587
Option('all', help='Shelve all changes.'),
5589
RegistryOption('writer', 'Method to use for writing diffs.',
5590
bzrlib.option.diff_writer_registry,
5591
value_switches=True, enum_switch=False),
5593
Option('list', help='List shelved changes.'),
5595
help='Destroy removed changes instead of shelving them.'),
5597
_see_also = ['unshelve']
5599
def run(self, revision=None, all=False, file_list=None, message=None,
5600
writer=None, list=False, destroy=False):
5602
return self.run_for_list()
5603
from bzrlib.shelf_ui import Shelver
5605
writer = bzrlib.option.diff_writer_registry.get()
5607
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5608
message, destroy=destroy).run()
5609
except errors.UserAbort:
2751
# command-line interpretation helper for merge-related commands
2752
def merge(other_revision, base_revision,
2753
check_clean=True, ignore_zero=False,
2754
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2755
file_list=None, show_base=False, reprocess=False,
2756
pb=DummyProgress()):
2757
"""Merge changes into a tree.
2760
list(path, revno) Base for three-way merge.
2761
If [None, None] then a base will be automatically determined.
2763
list(path, revno) Other revision for three-way merge.
2765
Directory to merge changes into; '.' by default.
2767
If true, this_dir must have no uncommitted changes before the
2769
ignore_zero - If true, suppress the "zero conflicts" message when
2770
there are no conflicts; should be set when doing something we expect
2771
to complete perfectly.
2772
file_list - If supplied, merge only changes to selected files.
2774
All available ancestors of other_revision and base_revision are
2775
automatically pulled into the branch.
2777
The revno may be -1 to indicate the last revision on the branch, which is
2780
This function is intended for use from the command line; programmatic
2781
clients might prefer to call merge.merge_inner(), which has less magic
2784
from bzrlib.merge import Merger
2785
if this_dir is None:
2787
this_tree = WorkingTree.open_containing(this_dir)[0]
2788
if show_base and not merge_type is Merge3Merger:
2789
raise BzrCommandError("Show-base is not supported for this merge"
2790
" type. %s" % merge_type)
2791
if reprocess and not merge_type.supports_reprocess:
2792
raise BzrCommandError("Conflict reduction is not supported for merge"
2793
" type %s." % merge_type)
2794
if reprocess and show_base:
2795
raise BzrCommandError("Cannot do conflict reduction and show base.")
2797
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2798
merger.pp = ProgressPhase("Merge phase", 5, pb)
2799
merger.pp.next_phase()
2800
merger.check_basis(check_clean)
2801
merger.set_other(other_revision)
2802
merger.pp.next_phase()
2803
merger.set_base(base_revision)
2804
if merger.base_rev_id == merger.other_rev_id:
2805
note('Nothing to do.')
5612
def run_for_list(self):
5613
tree = WorkingTree.open_containing('.')[0]
5616
manager = tree.get_shelf_manager()
5617
shelves = manager.active_shelves()
5618
if len(shelves) == 0:
5619
note('No shelved changes.')
5621
for shelf_id in reversed(shelves):
5622
message = manager.get_metadata(shelf_id).get('message')
5624
message = '<no message>'
5625
self.outf.write('%3d: %s\n' % (shelf_id, message))
5631
class cmd_unshelve(Command):
5632
"""Restore shelved changes.
5634
By default, the most recently shelved changes are restored. However if you
5635
specify a shelf by id those changes will be restored instead. This works
5636
best when the changes don't depend on each other.
5639
takes_args = ['shelf_id?']
5641
RegistryOption.from_kwargs(
5642
'action', help="The action to perform.",
5643
enum_switch=False, value_switches=True,
5644
apply="Apply changes and remove from the shelf.",
5645
dry_run="Show changes, but do not apply or remove them.",
5646
delete_only="Delete changes without applying them."
5649
_see_also = ['shelve']
5651
def run(self, shelf_id=None, action='apply'):
5652
from bzrlib.shelf_ui import Unshelver
5653
Unshelver.from_args(shelf_id, action).run()
5656
class cmd_clean_tree(Command):
5657
"""Remove unwanted files from working tree.
5659
By default, only unknown files, not ignored files, are deleted. Versioned
5660
files are never deleted.
5662
Another class is 'detritus', which includes files emitted by bzr during
5663
normal operations and selftests. (The value of these files decreases with
5666
If no options are specified, unknown files are deleted. Otherwise, option
5667
flags are respected, and may be combined.
5669
To check what clean-tree will do, use --dry-run.
5671
takes_options = [Option('ignored', help='Delete all ignored files.'),
5672
Option('detritus', help='Delete conflict files, merge'
5673
' backups, and failed selftest dirs.'),
5675
help='Delete files unknown to bzr (default).'),
5676
Option('dry-run', help='Show files to delete instead of'
5678
Option('force', help='Do not prompt before deleting.')]
5679
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5681
from bzrlib.clean_tree import clean_tree
5682
if not (unknown or ignored or detritus):
5686
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5687
dry_run=dry_run, no_prompt=force)
5690
class cmd_reference(Command):
5691
"""list, view and set branch locations for nested trees.
5693
If no arguments are provided, lists the branch locations for nested trees.
5694
If one argument is provided, display the branch location for that tree.
5695
If two arguments are provided, set the branch location for that tree.
5700
takes_args = ['path?', 'location?']
5702
def run(self, path=None, location=None):
5704
if path is not None:
5706
tree, branch, relpath =(
5707
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5708
if path is not None:
5711
tree = branch.basis_tree()
5713
info = branch._get_all_reference_info().iteritems()
5714
self._display_reference_info(tree, branch, info)
5716
file_id = tree.path2id(path)
5718
raise errors.NotVersionedError(path)
5719
if location is None:
5720
info = [(file_id, branch.get_reference_info(file_id))]
5721
self._display_reference_info(tree, branch, info)
5723
branch.set_reference_info(file_id, path, location)
5725
def _display_reference_info(self, tree, branch, info):
5727
for file_id, (path, location) in info:
5729
path = tree.id2path(file_id)
5730
except errors.NoSuchId:
5732
ref_list.append((path, location))
5733
for path, location in sorted(ref_list):
5734
self.outf.write('%s %s\n' % (path, location))
2807
merger.backup_files = backup_files
2808
merger.merge_type = merge_type
2809
merger.set_interesting_files(file_list)
2810
merger.show_base = show_base
2811
merger.reprocess = reprocess
2812
conflicts = merger.do_merge()
2813
if file_list is None:
2814
merger.set_pending()
5737
2820
# these get imported and then picked up by the scan for cmd_*
5738
2821
# TODO: Some more consistent way to split command definitions across files;
5739
# we do need to load at least some information about them to know of
2822
# we do need to load at least some information about them to know of
5740
2823
# aliases. ideally we would avoid loading the implementation until the
5741
2824
# details were needed.
5742
from bzrlib.cmd_version_info import cmd_version_info
5743
2825
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5744
from bzrlib.bundle.commands import (
5747
from bzrlib.foreign import cmd_dpush
2826
from bzrlib.bundle.commands import cmd_bundle_revisions
5748
2827
from bzrlib.sign_my_commits import cmd_sign_my_commits
5749
from bzrlib.weave_commands import cmd_versionedfile_list, \
2828
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
5750
2829
cmd_weave_plan_merge, cmd_weave_merge_text