696
1073
' directory exists, but does not already'
697
1074
' have a control directory. This flag will'
698
1075
' allow push to proceed.'),
1077
help='Create a stacked branch that references the public location '
1078
'of the parent branch.'),
1079
Option('stacked-on',
1080
help='Create a stacked branch that refers to another branch '
1081
'for the commit history. Only the work not present in the '
1082
'referenced branch is included in the branch created.',
1085
help='Refuse to push if there are uncommitted changes in'
1086
' the working tree, --no-strict disables the check.'),
700
1088
takes_args = ['location?']
701
1089
encoding_type = 'replace'
703
1091
def run(self, location=None, remember=False, overwrite=False,
704
create_prefix=False, verbose=False,
705
use_existing_dir=False,
707
# FIXME: Way too big! Put this into a function called from the
1092
create_prefix=False, verbose=False, revision=None,
1093
use_existing_dir=False, directory=None, stacked_on=None,
1094
stacked=False, strict=None):
1095
from bzrlib.push import _show_push_branch
709
1097
if directory is None:
711
br_from = Branch.open_containing(directory)[0]
712
stored_loc = br_from.get_push_location()
1099
# Get the source branch
1101
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1103
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1104
if strict is None: strict = True # default value
1105
# Get the tip's revision_id
1106
revision = _get_one_revision('push', revision)
1107
if revision is not None:
1108
revision_id = revision.in_history(br_from).rev_id
1111
if strict and tree is not None and revision_id is None:
1112
if (tree.has_changes(tree.basis_tree())
1113
or len(tree.get_parent_ids()) > 1):
1114
raise errors.UncommittedChanges(
1115
tree, more='Use --no-strict to force the push.')
1116
if tree.last_revision() != tree.branch.last_revision():
1117
# The tree has lost sync with its branch, there is little
1118
# chance that the user is aware of it but he can still force
1119
# the push with --no-strict
1120
raise errors.OutOfDateTree(
1121
tree, more='Use --no-strict to force the push.')
1123
# Get the stacked_on branch, if any
1124
if stacked_on is not None:
1125
stacked_on = urlutils.normalize_url(stacked_on)
1127
parent_url = br_from.get_parent()
1129
parent = Branch.open(parent_url)
1130
stacked_on = parent.get_public_branch()
1132
# I considered excluding non-http url's here, thus forcing
1133
# 'public' branches only, but that only works for some
1134
# users, so it's best to just depend on the user spotting an
1135
# error by the feedback given to them. RBC 20080227.
1136
stacked_on = parent_url
1138
raise errors.BzrCommandError(
1139
"Could not determine branch to refer to.")
1141
# Get the destination location
713
1142
if location is None:
1143
stored_loc = br_from.get_push_location()
714
1144
if stored_loc is None:
715
raise errors.BzrCommandError("No push location known or specified.")
1145
raise errors.BzrCommandError(
1146
"No push location known or specified.")
717
1148
display_url = urlutils.unescape_for_display(stored_loc,
718
1149
self.outf.encoding)
719
self.outf.write("Using saved location: %s\n" % display_url)
1150
self.outf.write("Using saved push location: %s\n" % display_url)
720
1151
location = stored_loc
722
to_transport = transport.get_transport(location)
724
br_to = repository_to = dir_to = None
726
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
727
except errors.NotBranchError:
728
pass # Didn't find anything
730
# If we can open a branch, use its direct repository, otherwise see
731
# if there is a repository without a branch.
733
br_to = dir_to.open_branch()
734
except errors.NotBranchError:
735
# Didn't find a branch, can we find a repository?
737
repository_to = dir_to.find_repository()
738
except errors.NoRepositoryPresent:
741
# Found a branch, so we must have found a repository
742
repository_to = br_to.repository
747
# The destination doesn't exist; create it.
748
# XXX: Refactor the create_prefix/no_create_prefix code into a
749
# common helper function
751
to_transport.mkdir('.')
752
except errors.FileExists:
753
if not use_existing_dir:
754
raise errors.BzrCommandError("Target directory %s"
755
" already exists, but does not have a valid .bzr"
756
" directory. Supply --use-existing-dir to push"
757
" there anyway." % location)
758
except errors.NoSuchFile:
759
if not create_prefix:
760
raise errors.BzrCommandError("Parent directory of %s"
762
"\nYou may supply --create-prefix to create all"
763
" leading parent directories."
765
_create_prefix(to_transport)
767
# Now the target directory exists, but doesn't have a .bzr
768
# directory. So we need to create it, along with any work to create
769
# all of the dependent branches, etc.
770
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
771
revision_id=br_from.last_revision())
772
br_to = dir_to.open_branch()
773
# TODO: Some more useful message about what was copied
774
note('Created new branch.')
775
# We successfully created the target, remember it
776
if br_from.get_push_location() is None or remember:
777
br_from.set_push_location(br_to.base)
778
elif repository_to is None:
779
# we have a bzrdir but no branch or repository
780
# XXX: Figure out what to do other than complain.
781
raise errors.BzrCommandError("At %s you have a valid .bzr control"
782
" directory, but not a branch or repository. This is an"
783
" unsupported configuration. Please move the target directory"
784
" out of the way and try again."
787
# We have a repository but no branch, copy the revisions, and then
789
last_revision_id = br_from.last_revision()
790
repository_to.fetch(br_from.repository,
791
revision_id=last_revision_id)
792
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
793
note('Created new branch.')
794
if br_from.get_push_location() is None or remember:
795
br_from.set_push_location(br_to.base)
796
else: # We have a valid to branch
797
# We were able to connect to the remote location, so remember it
798
# we don't need to successfully push because of possible divergence.
799
if br_from.get_push_location() is None or remember:
800
br_from.set_push_location(br_to.base)
802
old_rh = br_to.revision_history()
805
tree_to = dir_to.open_workingtree()
806
except errors.NotLocalUrl:
807
warning("This transport does not update the working "
808
"tree of: %s. See 'bzr help working-trees' for "
809
"more information." % br_to.base)
810
push_result = br_from.push(br_to, overwrite)
811
except errors.NoWorkingTree:
812
push_result = br_from.push(br_to, overwrite)
816
push_result = br_from.push(tree_to.branch, overwrite)
820
except errors.DivergedBranches:
821
raise errors.BzrCommandError('These branches have diverged.'
822
' Try using "merge" and then "push".')
823
if push_result is not None:
824
push_result.report(self.outf)
826
new_rh = br_to.revision_history()
829
from bzrlib.log import show_changed_revisions
830
show_changed_revisions(br_to, old_rh, new_rh,
833
# we probably did a clone rather than a push, so a message was
1153
_show_push_branch(br_from, revision_id, location, self.outf,
1154
verbose=verbose, overwrite=overwrite, remember=remember,
1155
stacked_on=stacked_on, create_prefix=create_prefix,
1156
use_existing_dir=use_existing_dir)
838
1159
class cmd_branch(Command):
839
"""Create a new copy of a branch.
1160
"""Create a new branch that is a copy of an existing branch.
841
1162
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
842
1163
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1604
2035
raise errors.BzrCommandError(msg)
2038
def _parse_levels(s):
2042
msg = "The levels argument must be an integer."
2043
raise errors.BzrCommandError(msg)
1607
2046
class cmd_log(Command):
1608
"""Show log of a branch, file, or directory.
1610
By default show the log of the branch containing the working directory.
1612
To request a range of logs, you can use the command -r begin..end
1613
-r revision requests a specific revision, -r ..end or -r begin.. are
1617
Log the current branch::
1625
Log the last 10 revisions of a branch::
1627
bzr log -r -10.. http://server/branch
2047
"""Show historical log for a branch or subset of a branch.
2049
log is bzr's default tool for exploring the history of a branch.
2050
The branch to use is taken from the first parameter. If no parameters
2051
are given, the branch containing the working directory is logged.
2052
Here are some simple examples::
2054
bzr log log the current branch
2055
bzr log foo.py log a file in its branch
2056
bzr log http://server/branch log a branch on a server
2058
The filtering, ordering and information shown for each revision can
2059
be controlled as explained below. By default, all revisions are
2060
shown sorted (topologically) so that newer revisions appear before
2061
older ones and descendants always appear before ancestors. If displayed,
2062
merged revisions are shown indented under the revision in which they
2067
The log format controls how information about each revision is
2068
displayed. The standard log formats are called ``long``, ``short``
2069
and ``line``. The default is long. See ``bzr help log-formats``
2070
for more details on log formats.
2072
The following options can be used to control what information is
2075
-l N display a maximum of N revisions
2076
-n N display N levels of revisions (0 for all, 1 for collapsed)
2077
-v display a status summary (delta) for each revision
2078
-p display a diff (patch) for each revision
2079
--show-ids display revision-ids (and file-ids), not just revnos
2081
Note that the default number of levels to display is a function of the
2082
log format. If the -n option is not used, the standard log formats show
2083
just the top level (mainline).
2085
Status summaries are shown using status flags like A, M, etc. To see
2086
the changes explained using words like ``added`` and ``modified``
2087
instead, use the -vv option.
2091
To display revisions from oldest to newest, use the --forward option.
2092
In most cases, using this option will have little impact on the total
2093
time taken to produce a log, though --forward does not incrementally
2094
display revisions like --reverse does when it can.
2096
:Revision filtering:
2098
The -r option can be used to specify what revision or range of revisions
2099
to filter against. The various forms are shown below::
2101
-rX display revision X
2102
-rX.. display revision X and later
2103
-r..Y display up to and including revision Y
2104
-rX..Y display from X to Y inclusive
2106
See ``bzr help revisionspec`` for details on how to specify X and Y.
2107
Some common examples are given below::
2109
-r-1 show just the tip
2110
-r-10.. show the last 10 mainline revisions
2111
-rsubmit:.. show what's new on this branch
2112
-rancestor:path.. show changes since the common ancestor of this
2113
branch and the one at location path
2114
-rdate:yesterday.. show changes since yesterday
2116
When logging a range of revisions using -rX..Y, log starts at
2117
revision Y and searches back in history through the primary
2118
("left-hand") parents until it finds X. When logging just the
2119
top level (using -n1), an error is reported if X is not found
2120
along the way. If multi-level logging is used (-n0), X may be
2121
a nested merge revision and the log will be truncated accordingly.
2125
If parameters are given and the first one is not a branch, the log
2126
will be filtered to show only those revisions that changed the
2127
nominated files or directories.
2129
Filenames are interpreted within their historical context. To log a
2130
deleted file, specify a revision range so that the file existed at
2131
the end or start of the range.
2133
Historical context is also important when interpreting pathnames of
2134
renamed files/directories. Consider the following example:
2136
* revision 1: add tutorial.txt
2137
* revision 2: modify tutorial.txt
2138
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2142
* ``bzr log guide.txt`` will log the file added in revision 1
2144
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2146
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2147
the original file in revision 2.
2149
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2150
was no file called guide.txt in revision 2.
2152
Renames are always followed by log. By design, there is no need to
2153
explicitly ask for this (and no way to stop logging a file back
2154
until it was last renamed).
2158
The --message option can be used for finding revisions that match a
2159
regular expression in a commit message.
2163
GUI tools and IDEs are often better at exploring history than command
2164
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2165
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2166
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2168
Web interfaces are often better at exploring history than command line
2169
tools, particularly for branches on servers. You may prefer Loggerhead
2170
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2172
You may find it useful to add the aliases below to ``bazaar.conf``::
2176
top = log -l10 --line
2179
``bzr tip`` will then show the latest revision while ``bzr top``
2180
will show the last 10 mainline revisions. To see the details of a
2181
particular revision X, ``bzr show -rX``.
2183
If you are interested in looking deeper into a particular merge X,
2184
use ``bzr log -n0 -rX``.
2186
``bzr log -v`` on a branch with lots of history is currently
2187
very slow. A fix for this issue is currently under development.
2188
With or without that fix, it is recommended that a revision range
2189
be given when using the -v option.
2191
bzr has a generic full-text matching plugin, bzr-search, that can be
2192
used to find revisions matching user names, commit messages, etc.
2193
Among other features, this plugin can find all revisions containing
2194
a list of words but not others.
2196
When exploring non-mainline history on large projects with deep
2197
history, the performance of log can be greatly improved by installing
2198
the historycache plugin. This plugin buffers historical information
2199
trading disk space for faster speed.
1630
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1632
takes_args = ['location?']
2201
takes_args = ['file*']
2202
_see_also = ['log-formats', 'revisionspec']
1633
2203
takes_options = [
1634
2204
Option('forward',
1635
2205
help='Show from oldest to newest.'),
1638
help='Display timezone as local, original, or utc.'),
1639
2207
custom_help('verbose',
1640
2208
help='Show files changed in each revision.'),
2212
type=bzrlib.option._parse_revision_str,
2214
help='Show just the specified revision.'
2215
' See also "help revisionspec".'),
2219
help='Number of levels to display - 0 for all, 1 for flat.',
2221
type=_parse_levels),
1644
2222
Option('message',
1645
2223
short_name='m',
1646
2224
help='Show revisions whose message matches this '
1647
2225
'regular expression.',
1649
2227
Option('limit',
1650
2229
help='Limit the output to the first N revisions.',
1652
2231
type=_parse_limit),
2234
help='Show changes made in each revision as a patch.'),
2235
Option('include-merges',
2236
help='Show merged revisions like --levels 0 does.'),
1654
2238
encoding_type = 'replace'
1656
2240
@display_command
1657
def run(self, location=None, timezone='original',
2241
def run(self, file_list=None, timezone='original',
1659
2243
show_ids=False,
1662
2247
log_format=None,
1665
from bzrlib.log import show_log
1666
assert message is None or isinstance(message, basestring), \
1667
"invalid message argument %r" % message
2252
include_merges=False):
2253
from bzrlib.log import (
2255
make_log_request_dict,
2256
_get_info_for_log_files,
1668
2258
direction = (forward and 'forward') or 'reverse'
1673
# find the file id to log:
1675
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1679
tree = b.basis_tree()
1680
file_id = tree.path2id(fp)
1682
raise errors.BzrCommandError(
1683
"Path does not have any revision history: %s" %
1687
# FIXME ? log the current subdir only RBC 20060203
1688
if revision is not None \
1689
and len(revision) > 0 and revision[0].get_branch():
1690
location = revision[0].get_branch()
1693
dir, relpath = bzrdir.BzrDir.open_containing(location)
1694
b = dir.open_branch()
2263
raise errors.BzrCommandError(
2264
'--levels and --include-merges are mutually exclusive')
2266
if change is not None:
2268
raise errors.RangeInChangeOption()
2269
if revision is not None:
2270
raise errors.BzrCommandError(
2271
'--revision and --change are mutually exclusive')
2276
filter_by_dir = False
1698
if revision is None:
1701
elif len(revision) == 1:
1702
rev1 = rev2 = revision[0].in_history(b)
1703
elif len(revision) == 2:
1704
if revision[1].get_branch() != revision[0].get_branch():
1705
# b is taken from revision[0].get_branch(), and
1706
# show_log will use its revision_history. Having
1707
# different branches will lead to weird behaviors.
1708
raise errors.BzrCommandError(
1709
"Log doesn't accept two revisions in different"
1711
rev1 = revision[0].in_history(b)
1712
rev2 = revision[1].in_history(b)
1714
raise errors.BzrCommandError(
1715
'bzr log --revision takes one or two values.')
2280
# find the file ids to log and check for directory filtering
2281
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2282
revision, file_list)
2283
for relpath, file_id, kind in file_info_list:
2285
raise errors.BzrCommandError(
2286
"Path unknown at end or start of revision range: %s" %
2288
# If the relpath is the top of the tree, we log everything
2293
file_ids.append(file_id)
2294
filter_by_dir = filter_by_dir or (
2295
kind in ['directory', 'tree-reference'])
2298
# FIXME ? log the current subdir only RBC 20060203
2299
if revision is not None \
2300
and len(revision) > 0 and revision[0].get_branch():
2301
location = revision[0].get_branch()
2304
dir, relpath = bzrdir.BzrDir.open_containing(location)
2305
b = dir.open_branch()
2307
rev1, rev2 = _get_revision_range(revision, b, self.name())
2309
# Decide on the type of delta & diff filtering to use
2310
# TODO: add an --all-files option to make this configurable & consistent
2318
diff_type = 'partial'
2322
# Build the log formatter
1717
2323
if log_format is None:
1718
2324
log_format = log.log_formatter_registry.get_default(b)
1720
2325
lf = log_format(show_ids=show_ids, to_file=self.outf,
1721
show_timezone=timezone)
1727
direction=direction,
1728
start_revision=rev1,
2326
show_timezone=timezone,
2327
delta_format=get_verbosity_level(),
2329
show_advice=levels is None)
2331
# Choose the algorithm for doing the logging. It's annoying
2332
# having multiple code paths like this but necessary until
2333
# the underlying repository format is faster at generating
2334
# deltas or can provide everything we need from the indices.
2335
# The default algorithm - match-using-deltas - works for
2336
# multiple files and directories and is faster for small
2337
# amounts of history (200 revisions say). However, it's too
2338
# slow for logging a single file in a repository with deep
2339
# history, i.e. > 10K revisions. In the spirit of "do no
2340
# evil when adding features", we continue to use the
2341
# original algorithm - per-file-graph - for the "single
2342
# file that isn't a directory without showing a delta" case.
2343
partial_history = revision and b.repository._format.supports_chks
2344
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2345
or delta_type or partial_history)
2347
# Build the LogRequest and execute it
2348
if len(file_ids) == 0:
2350
rqst = make_log_request_dict(
2351
direction=direction, specific_fileids=file_ids,
2352
start_revision=rev1, end_revision=rev2, limit=limit,
2353
message_search=message, delta_type=delta_type,
2354
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2355
Logger(b, rqst).show(lf)
2361
def _get_revision_range(revisionspec_list, branch, command_name):
2362
"""Take the input of a revision option and turn it into a revision range.
2364
It returns RevisionInfo objects which can be used to obtain the rev_id's
2365
of the desired revisions. It does some user input validations.
2367
if revisionspec_list is None:
2370
elif len(revisionspec_list) == 1:
2371
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2372
elif len(revisionspec_list) == 2:
2373
start_spec = revisionspec_list[0]
2374
end_spec = revisionspec_list[1]
2375
if end_spec.get_branch() != start_spec.get_branch():
2376
# b is taken from revision[0].get_branch(), and
2377
# show_log will use its revision_history. Having
2378
# different branches will lead to weird behaviors.
2379
raise errors.BzrCommandError(
2380
"bzr %s doesn't accept two revisions in different"
2381
" branches." % command_name)
2382
rev1 = start_spec.in_history(branch)
2383
# Avoid loading all of history when we know a missing
2384
# end of range means the last revision ...
2385
if end_spec.spec is None:
2386
last_revno, last_revision_id = branch.last_revision_info()
2387
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2389
rev2 = end_spec.in_history(branch)
2391
raise errors.BzrCommandError(
2392
'bzr %s --revision takes one or two values.' % command_name)
2396
def _revision_range_to_revid_range(revision_range):
2399
if revision_range[0] is not None:
2400
rev_id1 = revision_range[0].rev_id
2401
if revision_range[1] is not None:
2402
rev_id2 = revision_range[1].rev_id
2403
return rev_id1, rev_id2
1736
2405
def get_log_format(long=False, short=False, line=False, default='long'):
1737
2406
log_format = default
3902
5006
'rather than the one containing the working directory.',
3903
5007
short_name='f',
3905
Option('output', short_name='o', help='Write directive to this file.',
5009
Option('output', short_name='o',
5010
help='Write merge directive to this file; '
5011
'use - for stdout.',
5014
help='Refuse to send if there are uncommitted changes in'
5015
' the working tree, --no-strict disables the check.'),
3907
5016
Option('mail-to', help='Mail the request to this address.',
3911
RegistryOption.from_kwargs('format',
3912
'Use the specified output format.',
3913
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
3914
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5020
Option('body', help='Body for the email.', type=unicode),
5021
RegistryOption('format',
5022
help='Use the specified output format.',
5023
lazy_registry=('bzrlib.send', 'format_registry')),
3917
5026
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3918
5027
no_patch=False, revision=None, remember=False, output=None,
3919
format='4', mail_to=None, message=None, **kwargs):
3920
return self._run(submit_branch, revision, public_branch, remember,
3921
format, no_bundle, no_patch, output,
3922
kwargs.get('from', '.'), mail_to, message)
3924
def _run(self, submit_branch, revision, public_branch, remember, format,
3925
no_bundle, no_patch, output, from_, mail_to, message):
3926
from bzrlib.revision import NULL_REVISION
3928
outfile = StringIO()
3932
outfile = open(output, 'wb')
3934
branch = Branch.open_containing(from_)[0]
3936
config = branch.get_config()
3938
mail_to = config.get_user_option('submit_to')
3940
raise errors.BzrCommandError('No mail-to address'
3942
mail_client = config.get_mail_client()
3943
if remember and submit_branch is None:
3944
raise errors.BzrCommandError(
3945
'--remember requires a branch to be specified.')
3946
stored_submit_branch = branch.get_submit_branch()
3947
remembered_submit_branch = False
3948
if submit_branch is None:
3949
submit_branch = stored_submit_branch
3950
remembered_submit_branch = True
3952
if stored_submit_branch is None or remember:
3953
branch.set_submit_branch(submit_branch)
3954
if submit_branch is None:
3955
submit_branch = branch.get_parent()
3956
remembered_submit_branch = True
3957
if submit_branch is None:
3958
raise errors.BzrCommandError('No submit branch known or'
3960
if remembered_submit_branch:
3961
note('Using saved location: %s', submit_branch)
3963
stored_public_branch = branch.get_public_branch()
3964
if public_branch is None:
3965
public_branch = stored_public_branch
3966
elif stored_public_branch is None or remember:
3967
branch.set_public_branch(public_branch)
3968
if no_bundle and public_branch is None:
3969
raise errors.BzrCommandError('No public branch specified or'
3971
base_revision_id = None
3973
if revision is not None:
3974
if len(revision) > 2:
3975
raise errors.BzrCommandError('bzr send takes '
3976
'at most two one revision identifiers')
3977
revision_id = revision[-1].in_history(branch).rev_id
3978
if len(revision) == 2:
3979
base_revision_id = revision[0].in_history(branch).rev_id
3980
if revision_id is None:
3981
revision_id = branch.last_revision()
3982
if revision_id == NULL_REVISION:
3983
raise errors.BzrCommandError('No revisions to submit.')
3985
directive = merge_directive.MergeDirective2.from_objects(
3986
branch.repository, revision_id, time.time(),
3987
osutils.local_time_offset(), submit_branch,
3988
public_branch=public_branch, include_patch=not no_patch,
3989
include_bundle=not no_bundle, message=message,
3990
base_revision_id=base_revision_id)
3991
elif format == '0.9':
3994
patch_type = 'bundle'
3996
raise errors.BzrCommandError('Format 0.9 does not'
3997
' permit bundle with no patch')
4003
directive = merge_directive.MergeDirective.from_objects(
4004
branch.repository, revision_id, time.time(),
4005
osutils.local_time_offset(), submit_branch,
4006
public_branch=public_branch, patch_type=patch_type,
4009
outfile.writelines(directive.to_lines())
4011
subject = '[MERGE] '
4012
if message is not None:
4015
revision = branch.repository.get_revision(revision_id)
4016
subject += revision.get_summary()
4017
mail_client.compose_merge_request(mail_to, subject,
5028
format=None, mail_to=None, message=None, body=None,
5029
strict=None, **kwargs):
5030
from bzrlib.send import send
5031
return send(submit_branch, revision, public_branch, remember,
5032
format, no_bundle, no_patch, output,
5033
kwargs.get('from', '.'), mail_to, message, body,
4024
5038
class cmd_bundle_revisions(cmd_send):
4026
"""Create a merge-directive for submiting changes.
5039
"""Create a merge-directive for submitting changes.
4028
5041
A merge directive provides many things needed for requesting merges:
4189
5260
If none of these is available, --bind-to must be specified.
5263
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4192
5264
takes_args = ['location?']
4193
takes_options = [RegistryOption.from_kwargs('target_type',
4194
title='Target type',
4195
help='The type to reconfigure the directory to.',
4196
value_switches=True, enum_switch=False,
4197
branch='Reconfigure to a branch.',
4198
tree='Reconfigure to a tree.',
4199
checkout='Reconfigure to a checkout.'),
4200
Option('bind-to', help='Branch to bind checkout to.',
4203
help='Perform reconfiguration even if local changes'
5266
RegistryOption.from_kwargs(
5268
title='Target type',
5269
help='The type to reconfigure the directory to.',
5270
value_switches=True, enum_switch=False,
5271
branch='Reconfigure to be an unbound branch with no working tree.',
5272
tree='Reconfigure to be an unbound branch with a working tree.',
5273
checkout='Reconfigure to be a bound branch with a working tree.',
5274
lightweight_checkout='Reconfigure to be a lightweight'
5275
' checkout (with no local history).',
5276
standalone='Reconfigure to be a standalone branch '
5277
'(i.e. stop using shared repository).',
5278
use_shared='Reconfigure to use a shared repository.',
5279
with_trees='Reconfigure repository to create '
5280
'working trees on branches by default.',
5281
with_no_trees='Reconfigure repository to not create '
5282
'working trees on branches by default.'
5284
Option('bind-to', help='Branch to bind checkout to.', type=str),
5286
help='Perform reconfiguration even if local changes'
5288
Option('stacked-on',
5289
help='Reconfigure a branch to be stacked on another branch.',
5293
help='Reconfigure a branch to be unstacked. This '
5294
'may require copying substantial data into it.',
4207
def run(self, location=None, target_type=None, bind_to=None, force=False):
5298
def run(self, location=None, target_type=None, bind_to=None, force=False,
4208
5301
directory = bzrdir.BzrDir.open(location)
5302
if stacked_on and unstacked:
5303
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5304
elif stacked_on is not None:
5305
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5307
reconfigure.ReconfigureUnstacked().apply(directory)
5308
# At the moment you can use --stacked-on and a different
5309
# reconfiguration shape at the same time; there seems no good reason
4209
5311
if target_type is None:
4210
raise errors.BzrCommandError('No target configuration specified')
5312
if stacked_on or unstacked:
5315
raise errors.BzrCommandError('No target configuration '
4211
5317
elif target_type == 'branch':
4212
5318
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4213
5319
elif target_type == 'tree':
4214
5320
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4215
5321
elif target_type == 'checkout':
4216
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
5322
reconfiguration = reconfigure.Reconfigure.to_checkout(
5324
elif target_type == 'lightweight-checkout':
5325
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5327
elif target_type == 'use-shared':
5328
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5329
elif target_type == 'standalone':
5330
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5331
elif target_type == 'with-trees':
5332
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5334
elif target_type == 'with-no-trees':
5335
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
4218
5337
reconfiguration.apply(force)
4221
def _create_prefix(cur_transport):
4222
needed = [cur_transport]
4223
# Recurse upwards until we can create a directory successfully
4225
new_transport = cur_transport.clone('..')
4226
if new_transport.base == cur_transport.base:
4227
raise errors.BzrCommandError(
4228
"Failed to create path prefix for %s."
4229
% cur_transport.base)
4231
new_transport.mkdir('.')
4232
except errors.NoSuchFile:
4233
needed.append(new_transport)
4234
cur_transport = new_transport
4237
# Now we only need to create child directories
4239
cur_transport = needed.pop()
4240
cur_transport.ensure_base()
4243
def _get_mergeable_helper(location):
4244
"""Get a merge directive or bundle if 'location' points to one.
4246
Try try to identify a bundle and returns its mergeable form. If it's not,
4247
we return the tried transport anyway so that it can reused to access the
4250
:param location: can point to a bundle or a branch.
4252
:return: mergeable, transport
4255
url = urlutils.normalize_url(location)
4256
url, filename = urlutils.split(url, exclude_trailing_slash=False)
4257
location_transport = transport.get_transport(url)
4260
# There may be redirections but we ignore the intermediate
4261
# and final transports used
4262
read = bundle.read_mergeable_from_transport
4263
mergeable, t = read(location_transport, filename)
4264
except errors.NotABundle:
4265
# Continue on considering this url a Branch but adjust the
4266
# location_transport
4267
location_transport = location_transport.clone(filename)
4268
return mergeable, location_transport
5340
class cmd_switch(Command):
5341
"""Set the branch of a checkout and update.
5343
For lightweight checkouts, this changes the branch being referenced.
5344
For heavyweight checkouts, this checks that there are no local commits
5345
versus the current bound branch, then it makes the local branch a mirror
5346
of the new location and binds to it.
5348
In both cases, the working tree is updated and uncommitted changes
5349
are merged. The user can commit or revert these as they desire.
5351
Pending merges need to be committed or reverted before using switch.
5353
The path to the branch to switch to can be specified relative to the parent
5354
directory of the current branch. For example, if you are currently in a
5355
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5358
Bound branches use the nickname of its master branch unless it is set
5359
locally, in which case switching will update the the local nickname to be
5363
takes_args = ['to_location']
5364
takes_options = [Option('force',
5365
help='Switch even if local commits will be lost.'),
5366
Option('create-branch', short_name='b',
5367
help='Create the target branch from this one before'
5368
' switching to it.'),
5371
def run(self, to_location, force=False, create_branch=False):
5372
from bzrlib import switch
5374
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5376
branch = control_dir.open_branch()
5377
had_explicit_nick = branch.get_config().has_explicit_nickname()
5378
except errors.NotBranchError:
5380
had_explicit_nick = False
5383
raise errors.BzrCommandError('cannot create branch without'
5385
if '/' not in to_location and '\\' not in to_location:
5386
# This path is meant to be relative to the existing branch
5387
this_url = self._get_branch_location(control_dir)
5388
to_location = urlutils.join(this_url, '..', to_location)
5389
to_branch = branch.bzrdir.sprout(to_location,
5390
possible_transports=[branch.bzrdir.root_transport],
5391
source_branch=branch).open_branch()
5393
# from_branch = control_dir.open_branch()
5394
# except errors.NotBranchError:
5395
# raise BzrCommandError('Cannot create a branch from this'
5396
# ' location when we cannot open this branch')
5397
# from_branch.bzrdir.sprout(
5401
to_branch = Branch.open(to_location)
5402
except errors.NotBranchError:
5403
this_url = self._get_branch_location(control_dir)
5404
to_branch = Branch.open(
5405
urlutils.join(this_url, '..', to_location))
5406
switch.switch(control_dir, to_branch, force)
5407
if had_explicit_nick:
5408
branch = control_dir.open_branch() #get the new branch!
5409
branch.nick = to_branch.nick
5410
note('Switched to branch: %s',
5411
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5413
def _get_branch_location(self, control_dir):
5414
"""Return location of branch for this control dir."""
5416
this_branch = control_dir.open_branch()
5417
# This may be a heavy checkout, where we want the master branch
5418
master_location = this_branch.get_bound_location()
5419
if master_location is not None:
5420
return master_location
5421
# If not, use a local sibling
5422
return this_branch.base
5423
except errors.NotBranchError:
5424
format = control_dir.find_branch_format()
5425
if getattr(format, 'get_reference', None) is not None:
5426
return format.get_reference(control_dir)
5428
return control_dir.root_transport.base
5431
class cmd_view(Command):
5432
"""Manage filtered views.
5434
Views provide a mask over the tree so that users can focus on
5435
a subset of a tree when doing their work. After creating a view,
5436
commands that support a list of files - status, diff, commit, etc -
5437
effectively have that list of files implicitly given each time.
5438
An explicit list of files can still be given but those files
5439
must be within the current view.
5441
In most cases, a view has a short life-span: it is created to make
5442
a selected change and is deleted once that change is committed.
5443
At other times, you may wish to create one or more named views
5444
and switch between them.
5446
To disable the current view without deleting it, you can switch to
5447
the pseudo view called ``off``. This can be useful when you need
5448
to see the whole tree for an operation or two (e.g. merge) but
5449
want to switch back to your view after that.
5452
To define the current view::
5454
bzr view file1 dir1 ...
5456
To list the current view::
5460
To delete the current view::
5464
To disable the current view without deleting it::
5466
bzr view --switch off
5468
To define a named view and switch to it::
5470
bzr view --name view-name file1 dir1 ...
5472
To list a named view::
5474
bzr view --name view-name
5476
To delete a named view::
5478
bzr view --name view-name --delete
5480
To switch to a named view::
5482
bzr view --switch view-name
5484
To list all views defined::
5488
To delete all views::
5490
bzr view --delete --all
5494
takes_args = ['file*']
5497
help='Apply list or delete action to all views.',
5500
help='Delete the view.',
5503
help='Name of the view to define, list or delete.',
5507
help='Name of the view to switch to.',
5512
def run(self, file_list,
5518
tree, file_list = tree_files(file_list, apply_view=False)
5519
current_view, view_dict = tree.views.get_view_info()
5524
raise errors.BzrCommandError(
5525
"Both --delete and a file list specified")
5527
raise errors.BzrCommandError(
5528
"Both --delete and --switch specified")
5530
tree.views.set_view_info(None, {})
5531
self.outf.write("Deleted all views.\n")
5533
raise errors.BzrCommandError("No current view to delete")
5535
tree.views.delete_view(name)
5536
self.outf.write("Deleted '%s' view.\n" % name)
5539
raise errors.BzrCommandError(
5540
"Both --switch and a file list specified")
5542
raise errors.BzrCommandError(
5543
"Both --switch and --all specified")
5544
elif switch == 'off':
5545
if current_view is None:
5546
raise errors.BzrCommandError("No current view to disable")
5547
tree.views.set_view_info(None, view_dict)
5548
self.outf.write("Disabled '%s' view.\n" % (current_view))
5550
tree.views.set_view_info(switch, view_dict)
5551
view_str = views.view_display_str(tree.views.lookup_view())
5552
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5555
self.outf.write('Views defined:\n')
5556
for view in sorted(view_dict):
5557
if view == current_view:
5561
view_str = views.view_display_str(view_dict[view])
5562
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5564
self.outf.write('No views defined.\n')
5567
# No name given and no current view set
5570
raise errors.BzrCommandError(
5571
"Cannot change the 'off' pseudo view")
5572
tree.views.set_view(name, sorted(file_list))
5573
view_str = views.view_display_str(tree.views.lookup_view())
5574
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5578
# No name given and no current view set
5579
self.outf.write('No current view.\n')
5581
view_str = views.view_display_str(tree.views.lookup_view(name))
5582
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5585
class cmd_hooks(Command):
5591
for hook_key in sorted(hooks.known_hooks.keys()):
5592
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5593
self.outf.write("%s:\n" % type(some_hooks).__name__)
5594
for hook_name, hook_point in sorted(some_hooks.items()):
5595
self.outf.write(" %s:\n" % (hook_name,))
5596
found_hooks = list(hook_point)
5598
for hook in found_hooks:
5599
self.outf.write(" %s\n" %
5600
(some_hooks.get_hook_name(hook),))
5602
self.outf.write(" <no hooks installed>\n")
5605
class cmd_shelve(Command):
5606
"""Temporarily set aside some changes from the current tree.
5608
Shelve allows you to temporarily put changes you've made "on the shelf",
5609
ie. out of the way, until a later time when you can bring them back from
5610
the shelf with the 'unshelve' command. The changes are stored alongside
5611
your working tree, and so they aren't propagated along with your branch nor
5612
will they survive its deletion.
5614
If shelve --list is specified, previously-shelved changes are listed.
5616
Shelve is intended to help separate several sets of changes that have
5617
been inappropriately mingled. If you just want to get rid of all changes
5618
and you don't need to restore them later, use revert. If you want to
5619
shelve all text changes at once, use shelve --all.
5621
If filenames are specified, only the changes to those files will be
5622
shelved. Other files will be left untouched.
5624
If a revision is specified, changes since that revision will be shelved.
5626
You can put multiple items on the shelf, and by default, 'unshelve' will
5627
restore the most recently shelved changes.
5630
takes_args = ['file*']
5634
Option('all', help='Shelve all changes.'),
5636
RegistryOption('writer', 'Method to use for writing diffs.',
5637
bzrlib.option.diff_writer_registry,
5638
value_switches=True, enum_switch=False),
5640
Option('list', help='List shelved changes.'),
5642
help='Destroy removed changes instead of shelving them.'),
5644
_see_also = ['unshelve']
5646
def run(self, revision=None, all=False, file_list=None, message=None,
5647
writer=None, list=False, destroy=False):
5649
return self.run_for_list()
5650
from bzrlib.shelf_ui import Shelver
5652
writer = bzrlib.option.diff_writer_registry.get()
5654
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5655
file_list, message, destroy=destroy)
5659
shelver.work_tree.unlock()
5660
except errors.UserAbort:
5663
def run_for_list(self):
5664
tree = WorkingTree.open_containing('.')[0]
5667
manager = tree.get_shelf_manager()
5668
shelves = manager.active_shelves()
5669
if len(shelves) == 0:
5670
note('No shelved changes.')
5672
for shelf_id in reversed(shelves):
5673
message = manager.get_metadata(shelf_id).get('message')
5675
message = '<no message>'
5676
self.outf.write('%3d: %s\n' % (shelf_id, message))
5682
class cmd_unshelve(Command):
5683
"""Restore shelved changes.
5685
By default, the most recently shelved changes are restored. However if you
5686
specify a shelf by id those changes will be restored instead. This works
5687
best when the changes don't depend on each other.
5690
takes_args = ['shelf_id?']
5692
RegistryOption.from_kwargs(
5693
'action', help="The action to perform.",
5694
enum_switch=False, value_switches=True,
5695
apply="Apply changes and remove from the shelf.",
5696
dry_run="Show changes, but do not apply or remove them.",
5697
delete_only="Delete changes without applying them."
5700
_see_also = ['shelve']
5702
def run(self, shelf_id=None, action='apply'):
5703
from bzrlib.shelf_ui import Unshelver
5704
unshelver = Unshelver.from_args(shelf_id, action)
5708
unshelver.tree.unlock()
5711
class cmd_clean_tree(Command):
5712
"""Remove unwanted files from working tree.
5714
By default, only unknown files, not ignored files, are deleted. Versioned
5715
files are never deleted.
5717
Another class is 'detritus', which includes files emitted by bzr during
5718
normal operations and selftests. (The value of these files decreases with
5721
If no options are specified, unknown files are deleted. Otherwise, option
5722
flags are respected, and may be combined.
5724
To check what clean-tree will do, use --dry-run.
5726
takes_options = [Option('ignored', help='Delete all ignored files.'),
5727
Option('detritus', help='Delete conflict files, merge'
5728
' backups, and failed selftest dirs.'),
5730
help='Delete files unknown to bzr (default).'),
5731
Option('dry-run', help='Show files to delete instead of'
5733
Option('force', help='Do not prompt before deleting.')]
5734
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5736
from bzrlib.clean_tree import clean_tree
5737
if not (unknown or ignored or detritus):
5741
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5742
dry_run=dry_run, no_prompt=force)
5745
class cmd_reference(Command):
5746
"""list, view and set branch locations for nested trees.
5748
If no arguments are provided, lists the branch locations for nested trees.
5749
If one argument is provided, display the branch location for that tree.
5750
If two arguments are provided, set the branch location for that tree.
5755
takes_args = ['path?', 'location?']
5757
def run(self, path=None, location=None):
5759
if path is not None:
5761
tree, branch, relpath =(
5762
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5763
if path is not None:
5766
tree = branch.basis_tree()
5768
info = branch._get_all_reference_info().iteritems()
5769
self._display_reference_info(tree, branch, info)
5771
file_id = tree.path2id(path)
5773
raise errors.NotVersionedError(path)
5774
if location is None:
5775
info = [(file_id, branch.get_reference_info(file_id))]
5776
self._display_reference_info(tree, branch, info)
5778
branch.set_reference_info(file_id, path, location)
5780
def _display_reference_info(self, tree, branch, info):
5782
for file_id, (path, location) in info:
5784
path = tree.id2path(file_id)
5785
except errors.NoSuchId:
5787
ref_list.append((path, location))
5788
for path, location in sorted(ref_list):
5789
self.outf.write('%s %s\n' % (path, location))
4271
5792
# these get imported and then picked up by the scan for cmd_*
4272
5793
# TODO: Some more consistent way to split command definitions across files;
4273
# we do need to load at least some information about them to know of
5794
# we do need to load at least some information about them to know of
4274
5795
# aliases. ideally we would avoid loading the implementation until the
4275
5796
# details were needed.
4276
5797
from bzrlib.cmd_version_info import cmd_version_info