13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
"""builtin bzr commands"""
20
from StringIO import StringIO
22
21
from bzrlib.lazy_import import lazy_import
23
22
lazy_import(globals(), """
31
29
from bzrlib import (
42
40
merge as _mod_merge,
47
45
revision as _mod_revision,
55
52
from bzrlib.branch import Branch
56
53
from bzrlib.conflicts import ConflictList
57
from bzrlib.revisionspec import RevisionSpec
54
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
58
55
from bzrlib.smtp_connection import SMTPConnection
59
56
from bzrlib.workingtree import WorkingTree
62
59
from bzrlib.commands import Command, display_command
63
from bzrlib.option import ListOption, Option, RegistryOption
64
from bzrlib.progress import DummyProgress, ProgressPhase
65
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
68
def tree_files(file_list, default_branch=u'.'):
60
from bzrlib.option import (
67
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
70
def tree_files(file_list, default_branch=u'.', canonicalize=True,
70
return internal_tree_files(file_list, default_branch)
73
return internal_tree_files(file_list, default_branch, canonicalize,
71
75
except errors.FileInWrongBranch, e:
72
76
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
77
(e.path, file_list[0]))
80
def tree_files_for_add(file_list):
82
Return a tree and list of absolute paths from a file list.
84
Similar to tree_files, but add handles files a bit differently, so it a
85
custom implementation. In particular, MutableTreeTree.smart_add expects
86
absolute paths, which it immediately converts to relative paths.
88
# FIXME Would be nice to just return the relative paths like
89
# internal_tree_files does, but there are a large number of unit tests
90
# that assume the current interface to mutabletree.smart_add
92
tree, relpath = WorkingTree.open_containing(file_list[0])
93
if tree.supports_views():
94
view_files = tree.views.lookup_view()
96
for filename in file_list:
97
if not osutils.is_inside_any(view_files, filename):
98
raise errors.FileOutsideView(filename, view_files)
99
file_list = file_list[:]
100
file_list[0] = tree.abspath(relpath)
102
tree = WorkingTree.open_containing(u'.')[0]
103
if tree.supports_views():
104
view_files = tree.views.lookup_view()
106
file_list = view_files
107
view_str = views.view_display_str(view_files)
108
note("Ignoring files outside view. View is %s" % view_str)
109
return tree, file_list
112
def _get_one_revision(command_name, revisions):
113
if revisions is None:
115
if len(revisions) != 1:
116
raise errors.BzrCommandError(
117
'bzr %s --revision takes exactly one revision identifier' % (
122
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
123
"""Get a revision tree. Not suitable for commands that change the tree.
125
Specifically, the basis tree in dirstate trees is coupled to the dirstate
126
and doing a commit/uncommit/pull will at best fail due to changing the
129
If tree is passed in, it should be already locked, for lifetime management
130
of the trees internal cached state.
134
if revisions is None:
136
rev_tree = tree.basis_tree()
138
rev_tree = branch.basis_tree()
140
revision = _get_one_revision(command_name, revisions)
141
rev_tree = revision.as_tree(branch)
76
145
# XXX: Bad function name; should possibly also be a class method of
77
146
# WorkingTree rather than a function.
78
def internal_tree_files(file_list, default_branch=u'.'):
147
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
79
149
"""Convert command-line paths to a WorkingTree and relative paths.
81
151
This is typically used for command-line processors that take one or
693
1073
' directory exists, but does not already'
694
1074
' have a control directory. This flag will'
695
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.'),
697
1088
takes_args = ['location?']
698
1089
encoding_type = 'replace'
700
1091
def run(self, location=None, remember=False, overwrite=False,
701
create_prefix=False, verbose=False,
702
use_existing_dir=False,
704
# 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
706
1097
if directory is None:
708
br_from = Branch.open_containing(directory)[0]
709
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
710
1142
if location is None:
1143
stored_loc = br_from.get_push_location()
711
1144
if stored_loc is None:
712
raise errors.BzrCommandError("No push location known or specified.")
1145
raise errors.BzrCommandError(
1146
"No push location known or specified.")
714
1148
display_url = urlutils.unescape_for_display(stored_loc,
715
1149
self.outf.encoding)
716
self.outf.write("Using saved location: %s\n" % display_url)
1150
self.outf.write("Using saved push location: %s\n" % display_url)
717
1151
location = stored_loc
719
to_transport = transport.get_transport(location)
721
br_to = repository_to = dir_to = None
723
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
724
except errors.NotBranchError:
725
pass # Didn't find anything
727
# If we can open a branch, use its direct repository, otherwise see
728
# if there is a repository without a branch.
730
br_to = dir_to.open_branch()
731
except errors.NotBranchError:
732
# Didn't find a branch, can we find a repository?
734
repository_to = dir_to.find_repository()
735
except errors.NoRepositoryPresent:
738
# Found a branch, so we must have found a repository
739
repository_to = br_to.repository
744
# The destination doesn't exist; create it.
745
# XXX: Refactor the create_prefix/no_create_prefix code into a
746
# common helper function
748
to_transport.mkdir('.')
749
except errors.FileExists:
750
if not use_existing_dir:
751
raise errors.BzrCommandError("Target directory %s"
752
" already exists, but does not have a valid .bzr"
753
" directory. Supply --use-existing-dir to push"
754
" there anyway." % location)
755
except errors.NoSuchFile:
756
if not create_prefix:
757
raise errors.BzrCommandError("Parent directory of %s"
759
"\nYou may supply --create-prefix to create all"
760
" leading parent directories."
762
_create_prefix(to_transport)
764
# Now the target directory exists, but doesn't have a .bzr
765
# directory. So we need to create it, along with any work to create
766
# all of the dependent branches, etc.
767
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
768
revision_id=br_from.last_revision())
769
br_to = dir_to.open_branch()
770
# TODO: Some more useful message about what was copied
771
note('Created new branch.')
772
# We successfully created the target, remember it
773
if br_from.get_push_location() is None or remember:
774
br_from.set_push_location(br_to.base)
775
elif repository_to is None:
776
# we have a bzrdir but no branch or repository
777
# XXX: Figure out what to do other than complain.
778
raise errors.BzrCommandError("At %s you have a valid .bzr control"
779
" directory, but not a branch or repository. This is an"
780
" unsupported configuration. Please move the target directory"
781
" out of the way and try again."
784
# We have a repository but no branch, copy the revisions, and then
786
last_revision_id = br_from.last_revision()
787
repository_to.fetch(br_from.repository,
788
revision_id=last_revision_id)
789
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
790
note('Created new branch.')
791
if br_from.get_push_location() is None or remember:
792
br_from.set_push_location(br_to.base)
793
else: # We have a valid to branch
794
# We were able to connect to the remote location, so remember it
795
# we don't need to successfully push because of possible divergence.
796
if br_from.get_push_location() is None or remember:
797
br_from.set_push_location(br_to.base)
799
old_rh = br_to.revision_history()
802
tree_to = dir_to.open_workingtree()
803
except errors.NotLocalUrl:
804
warning("This transport does not update the working "
805
"tree of: %s. See 'bzr help working-trees' for "
806
"more information." % br_to.base)
807
push_result = br_from.push(br_to, overwrite)
808
except errors.NoWorkingTree:
809
push_result = br_from.push(br_to, overwrite)
813
push_result = br_from.push(tree_to.branch, overwrite)
817
except errors.DivergedBranches:
818
raise errors.BzrCommandError('These branches have diverged.'
819
' Try using "merge" and then "push".')
820
if push_result is not None:
821
push_result.report(self.outf)
823
new_rh = br_to.revision_history()
826
from bzrlib.log import show_changed_revisions
827
show_changed_revisions(br_to, old_rh, new_rh,
830
# 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)
835
1159
class cmd_branch(Command):
836
"""Create a new copy of a branch.
1160
"""Create a new branch that is a copy of an existing branch.
838
1162
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
839
1163
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1594
2035
raise errors.BzrCommandError(msg)
2038
def _parse_levels(s):
2042
msg = "The levels argument must be an integer."
2043
raise errors.BzrCommandError(msg)
1597
2046
class cmd_log(Command):
1598
"""Show log of a branch, file, or directory.
1600
By default show the log of the branch containing the working directory.
1602
To request a range of logs, you can use the command -r begin..end
1603
-r revision requests a specific revision, -r ..end or -r begin.. are
1607
Log the current branch::
1615
Log the last 10 revisions of a branch::
1617
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.
1620
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1622
takes_args = ['location?']
2201
takes_args = ['file*']
2202
_see_also = ['log-formats', 'revisionspec']
1623
2203
takes_options = [
1624
2204
Option('forward',
1625
2205
help='Show from oldest to newest.'),
1628
help='Display timezone as local, original, or utc.'),
2207
custom_help('verbose',
1631
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),
1635
2222
Option('message',
1636
2223
short_name='m',
1637
2224
help='Show revisions whose message matches this '
1638
2225
'regular expression.',
1640
2227
Option('limit',
1641
2229
help='Limit the output to the first N revisions.',
1643
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.'),
1645
2238
encoding_type = 'replace'
1647
2240
@display_command
1648
def run(self, location=None, timezone='original',
2241
def run(self, file_list=None, timezone='original',
1650
2243
show_ids=False,
1653
2247
log_format=None,
1656
from bzrlib.log import show_log
1657
assert message is None or isinstance(message, basestring), \
1658
"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,
1659
2258
direction = (forward and 'forward') or 'reverse'
1664
# find the file id to log:
1666
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1670
tree = b.basis_tree()
1671
file_id = tree.path2id(fp)
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
2278
# find the file ids to log and check for directory filtering
2279
b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2281
for relpath, file_id, kind in file_info_list:
1672
2282
if file_id is None:
1673
2283
raise errors.BzrCommandError(
1674
"Path does not have any revision history: %s" %
2284
"Path unknown at end or start of revision range: %s" %
2286
# If the relpath is the top of the tree, we log everything
2291
file_ids.append(file_id)
2292
filter_by_dir = filter_by_dir or (
2293
kind in ['directory', 'tree-reference'])
1678
# FIXME ? log the current subdir only RBC 20060203
2296
# FIXME ? log the current subdir only RBC 20060203
1679
2297
if revision is not None \
1680
2298
and len(revision) > 0 and revision[0].get_branch():
1681
2299
location = revision[0].get_branch()
1684
2302
dir, relpath = bzrdir.BzrDir.open_containing(location)
1685
2303
b = dir.open_branch()
2304
rev1, rev2 = _get_revision_range(revision, b, self.name())
2306
# Decide on the type of delta & diff filtering to use
2307
# TODO: add an --all-files option to make this configurable & consistent
2315
diff_type = 'partial'
1689
if revision is None:
1692
elif len(revision) == 1:
1693
rev1 = rev2 = revision[0].in_history(b)
1694
elif len(revision) == 2:
1695
if revision[1].get_branch() != revision[0].get_branch():
1696
# b is taken from revision[0].get_branch(), and
1697
# show_log will use its revision_history. Having
1698
# different branches will lead to weird behaviors.
1699
raise errors.BzrCommandError(
1700
"Log doesn't accept two revisions in different"
1702
rev1 = revision[0].in_history(b)
1703
rev2 = revision[1].in_history(b)
1705
raise errors.BzrCommandError(
1706
'bzr log --revision takes one or two values.')
2321
# Build the log formatter
1708
2322
if log_format is None:
1709
2323
log_format = log.log_formatter_registry.get_default(b)
1711
2324
lf = log_format(show_ids=show_ids, to_file=self.outf,
1712
show_timezone=timezone)
1718
direction=direction,
1719
start_revision=rev1,
2325
show_timezone=timezone,
2326
delta_format=get_verbosity_level(),
2328
show_advice=levels is None)
2330
# Choose the algorithm for doing the logging. It's annoying
2331
# having multiple code paths like this but necessary until
2332
# the underlying repository format is faster at generating
2333
# deltas or can provide everything we need from the indices.
2334
# The default algorithm - match-using-deltas - works for
2335
# multiple files and directories and is faster for small
2336
# amounts of history (200 revisions say). However, it's too
2337
# slow for logging a single file in a repository with deep
2338
# history, i.e. > 10K revisions. In the spirit of "do no
2339
# evil when adding features", we continue to use the
2340
# original algorithm - per-file-graph - for the "single
2341
# file that isn't a directory without showing a delta" case.
2342
partial_history = revision and b.repository._format.supports_chks
2343
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2344
or delta_type or partial_history)
2346
# Build the LogRequest and execute it
2347
if len(file_ids) == 0:
2349
rqst = make_log_request_dict(
2350
direction=direction, specific_fileids=file_ids,
2351
start_revision=rev1, end_revision=rev2, limit=limit,
2352
message_search=message, delta_type=delta_type,
2353
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2354
Logger(b, rqst).show(lf)
2359
def _get_revision_range(revisionspec_list, branch, command_name):
2360
"""Take the input of a revision option and turn it into a revision range.
2362
It returns RevisionInfo objects which can be used to obtain the rev_id's
2363
of the desired revisions. It does some user input validations.
2365
if revisionspec_list is None:
2368
elif len(revisionspec_list) == 1:
2369
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2370
elif len(revisionspec_list) == 2:
2371
start_spec = revisionspec_list[0]
2372
end_spec = revisionspec_list[1]
2373
if end_spec.get_branch() != start_spec.get_branch():
2374
# b is taken from revision[0].get_branch(), and
2375
# show_log will use its revision_history. Having
2376
# different branches will lead to weird behaviors.
2377
raise errors.BzrCommandError(
2378
"bzr %s doesn't accept two revisions in different"
2379
" branches." % command_name)
2380
rev1 = start_spec.in_history(branch)
2381
# Avoid loading all of history when we know a missing
2382
# end of range means the last revision ...
2383
if end_spec.spec is None:
2384
last_revno, last_revision_id = branch.last_revision_info()
2385
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2387
rev2 = end_spec.in_history(branch)
2389
raise errors.BzrCommandError(
2390
'bzr %s --revision takes one or two values.' % command_name)
2394
def _revision_range_to_revid_range(revision_range):
2397
if revision_range[0] is not None:
2398
rev_id1 = revision_range[0].rev_id
2399
if revision_range[1] is not None:
2400
rev_id2 = revision_range[1].rev_id
2401
return rev_id1, rev_id2
1727
2403
def get_log_format(long=False, short=False, line=False, default='long'):
1728
2404
log_format = default
2527
3403
short_name='x',
2528
3404
help='Exclude tests that match this regular'
2529
3405
' expression.'),
3407
help='Output test progress via subunit.'),
2530
3408
Option('strict', help='Fail on missing dependencies or '
2531
3409
'known failures.'),
3410
Option('load-list', type=str, argname='TESTLISTFILE',
3411
help='Load a test id list from a text file.'),
3412
ListOption('debugflag', type=str, short_name='E',
3413
help='Turn on a selftest debug flag.'),
3414
ListOption('starting-with', type=str, argname='TESTID',
3415
param_name='starting_with', short_name='s',
3417
'Load only the tests starting with TESTID.'),
2533
3419
encoding_type = 'replace'
2535
def run(self, testspecs_list=None, verbose=None, one=False,
3422
Command.__init__(self)
3423
self.additional_selftest_args = {}
3425
def run(self, testspecs_list=None, verbose=False, one=False,
2536
3426
transport=None, benchmark=None,
2537
3427
lsprof_timed=None, cache_dir=None,
2538
3428
first=False, list_only=False,
2539
randomize=None, exclude=None, strict=False):
3429
randomize=None, exclude=None, strict=False,
3430
load_list=None, debugflag=None, starting_with=None, subunit=False,
2541
3432
from bzrlib.tests import selftest
2542
3433
import bzrlib.benchmarks as benchmarks
2543
3434
from bzrlib.benchmarks import tree_creator
2544
from bzrlib.version import show_version
3436
# Make deprecation warnings visible, unless -Werror is set
3437
symbol_versioning.activate_deprecation_warnings(override=False)
2546
3439
if cache_dir is not None:
2547
3440
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2549
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2550
print ' %s (%s python%s)' % (
2552
bzrlib.version_string,
2553
'.'.join(map(str, sys.version_info)),
2556
3441
if testspecs_list is not None:
2557
3442
pattern = '|'.join(testspecs_list)
3447
from bzrlib.tests import SubUnitBzrRunner
3449
raise errors.BzrCommandError("subunit not available. subunit "
3450
"needs to be installed to use --subunit.")
3451
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3453
self.additional_selftest_args.setdefault(
3454
'suite_decorators', []).append(parallel)
2561
3456
test_suite_factory = benchmarks.test_suite
3457
# Unless user explicitly asks for quiet, be verbose in benchmarks
3458
verbose = not is_quiet()
2564
3459
# TODO: should possibly lock the history file...
2565
3460
benchfile = open(".perf_history", "at", buffering=1)
2567
3462
test_suite_factory = None
2570
3463
benchfile = None
2572
result = selftest(verbose=verbose,
2574
stop_on_failure=one,
2575
transport=transport,
2576
test_suite_factory=test_suite_factory,
2577
lsprof_timed=lsprof_timed,
2578
bench_history=benchfile,
2579
matching_tests_first=first,
2580
list_only=list_only,
2581
random_seed=randomize,
2582
exclude_pattern=exclude,
3465
selftest_kwargs = {"verbose": verbose,
3467
"stop_on_failure": one,
3468
"transport": transport,
3469
"test_suite_factory": test_suite_factory,
3470
"lsprof_timed": lsprof_timed,
3471
"bench_history": benchfile,
3472
"matching_tests_first": first,
3473
"list_only": list_only,
3474
"random_seed": randomize,
3475
"exclude_pattern": exclude,
3477
"load_list": load_list,
3478
"debug_flags": debugflag,
3479
"starting_with": starting_with
3481
selftest_kwargs.update(self.additional_selftest_args)
3482
result = selftest(**selftest_kwargs)
2586
3484
if benchfile is not None:
2587
3485
benchfile.close()
2589
info('tests passed')
2591
info('tests failed')
2592
3486
return int(not result)
2595
3489
class cmd_version(Command):
2596
3490
"""Show version of bzr."""
3492
encoding_type = 'replace'
3494
Option("short", help="Print just the version number."),
2598
3497
@display_command
3498
def run(self, short=False):
2600
3499
from bzrlib.version import show_version
3501
self.outf.write(bzrlib.version_string + '\n')
3503
show_version(to_file=self.outf)
2604
3506
class cmd_rocks(Command):
3860
4999
'rather than the one containing the working directory.',
3861
5000
short_name='f',
3863
Option('output', short_name='o', help='Write directive to this file.',
5002
Option('output', short_name='o',
5003
help='Write merge directive to this file; '
5004
'use - for stdout.',
5007
help='Refuse to send if there are uncommitted changes in'
5008
' the working tree, --no-strict disables the check.'),
3865
5009
Option('mail-to', help='Mail the request to this address.',
3869
RegistryOption.from_kwargs('format',
3870
'Use the specified output format.',
3871
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
3872
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5013
Option('body', help='Body for the email.', type=unicode),
5014
RegistryOption('format',
5015
help='Use the specified output format.',
5016
lazy_registry=('bzrlib.send', 'format_registry')),
3875
5019
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3876
5020
no_patch=False, revision=None, remember=False, output=None,
3877
format='4', mail_to=None, message=None, **kwargs):
3878
return self._run(submit_branch, revision, public_branch, remember,
3879
format, no_bundle, no_patch, output,
3880
kwargs.get('from', '.'), mail_to, message)
3882
def _run(self, submit_branch, revision, public_branch, remember, format,
3883
no_bundle, no_patch, output, from_, mail_to, message):
3884
from bzrlib.revision import ensure_null, NULL_REVISION
3886
outfile = StringIO()
3890
outfile = open(output, 'wb')
3892
branch = Branch.open_containing(from_)[0]
3894
config = branch.get_config()
3896
mail_to = config.get_user_option('submit_to')
3898
raise errors.BzrCommandError('No mail-to address'
3900
mail_client = config.get_mail_client()
3901
if remember and submit_branch is None:
3902
raise errors.BzrCommandError(
3903
'--remember requires a branch to be specified.')
3904
stored_submit_branch = branch.get_submit_branch()
3905
remembered_submit_branch = False
3906
if submit_branch is None:
3907
submit_branch = stored_submit_branch
3908
remembered_submit_branch = True
3910
if stored_submit_branch is None or remember:
3911
branch.set_submit_branch(submit_branch)
3912
if submit_branch is None:
3913
submit_branch = branch.get_parent()
3914
remembered_submit_branch = True
3915
if submit_branch is None:
3916
raise errors.BzrCommandError('No submit branch known or'
3918
if remembered_submit_branch:
3919
note('Using saved location: %s', submit_branch)
3921
stored_public_branch = branch.get_public_branch()
3922
if public_branch is None:
3923
public_branch = stored_public_branch
3924
elif stored_public_branch is None or remember:
3925
branch.set_public_branch(public_branch)
3926
if no_bundle and public_branch is None:
3927
raise errors.BzrCommandError('No public branch specified or'
3929
base_revision_id = None
3931
if revision is not None:
3932
if len(revision) > 2:
3933
raise errors.BzrCommandError('bzr send takes '
3934
'at most two one revision identifiers')
3935
revision_id = revision[-1].in_history(branch).rev_id
3936
if len(revision) == 2:
3937
base_revision_id = revision[0].in_history(branch).rev_id
3938
if revision_id is None:
3939
revision_id = branch.last_revision()
3940
if revision_id == NULL_REVISION:
3941
raise errors.BzrCommandError('No revisions to submit.')
3943
directive = merge_directive.MergeDirective2.from_objects(
3944
branch.repository, revision_id, time.time(),
3945
osutils.local_time_offset(), submit_branch,
3946
public_branch=public_branch, include_patch=not no_patch,
3947
include_bundle=not no_bundle, message=message,
3948
base_revision_id=base_revision_id)
3949
elif format == '0.9':
3952
patch_type = 'bundle'
3954
raise errors.BzrCommandError('Format 0.9 does not'
3955
' permit bundle with no patch')
3961
directive = merge_directive.MergeDirective.from_objects(
3962
branch.repository, revision_id, time.time(),
3963
osutils.local_time_offset(), submit_branch,
3964
public_branch=public_branch, patch_type=patch_type,
3967
outfile.writelines(directive.to_lines())
3969
subject = '[MERGE] '
3970
if message is not None:
3973
revision = branch.repository.get_revision(revision_id)
3974
subject += revision.get_summary()
3975
mail_client.compose_merge_request(mail_to, subject,
5021
format=None, mail_to=None, message=None, body=None,
5022
strict=None, **kwargs):
5023
from bzrlib.send import send
5024
return send(submit_branch, revision, public_branch, remember,
5025
format, no_bundle, no_patch, output,
5026
kwargs.get('from', '.'), mail_to, message, body,
3982
5031
class cmd_bundle_revisions(cmd_send):
3984
"""Create a merge-directive for submiting changes.
5032
"""Create a merge-directive for submitting changes.
3986
5034
A merge directive provides many things needed for requesting merges:
4122
5177
short_name='d',
5180
RegistryOption.from_kwargs('sort',
5181
'Sort tags by different criteria.', title='Sorting',
5182
alpha='Sort tags lexicographically (default).',
5183
time='Sort tags chronologically.',
4127
5189
@display_command
4131
5196
branch, relpath = Branch.open_containing(directory)
4132
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
4133
self.outf.write('%-20s %s\n' % (tag_name, target))
4136
def _create_prefix(cur_transport):
4137
needed = [cur_transport]
4138
# Recurse upwards until we can create a directory successfully
4140
new_transport = cur_transport.clone('..')
4141
if new_transport.base == cur_transport.base:
4142
raise errors.BzrCommandError(
4143
"Failed to create path prefix for %s."
4144
% cur_transport.base)
4146
new_transport.mkdir('.')
4147
except errors.NoSuchFile:
4148
needed.append(new_transport)
4149
cur_transport = new_transport
4152
# Now we only need to create child directories
4154
cur_transport = needed.pop()
4155
cur_transport.ensure_base()
4158
def _get_mergeable_helper(location):
4159
"""Get a merge directive or bundle if 'location' points to one.
4161
Try try to identify a bundle and returns its mergeable form. If it's not,
4162
we return the tried transport anyway so that it can reused to access the
4165
:param location: can point to a bundle or a branch.
4167
:return: mergeable, transport
4170
url = urlutils.normalize_url(location)
4171
url, filename = urlutils.split(url, exclude_trailing_slash=False)
4172
location_transport = transport.get_transport(url)
4175
# There may be redirections but we ignore the intermediate
4176
# and final transports used
4177
read = bundle.read_mergeable_from_transport
4178
mergeable, t = read(location_transport, filename)
4179
except errors.NotABundle:
4180
# Continue on considering this url a Branch but adjust the
4181
# location_transport
4182
location_transport = location_transport.clone(filename)
4183
return mergeable, location_transport
5198
tags = branch.tags.get_tag_dict().items()
5205
graph = branch.repository.get_graph()
5206
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5207
revid1, revid2 = rev1.rev_id, rev2.rev_id
5208
# only show revisions between revid1 and revid2 (inclusive)
5209
tags = [(tag, revid) for tag, revid in tags if
5210
graph.is_between(revid, revid1, revid2)]
5213
elif sort == 'time':
5215
for tag, revid in tags:
5217
revobj = branch.repository.get_revision(revid)
5218
except errors.NoSuchRevision:
5219
timestamp = sys.maxint # place them at the end
5221
timestamp = revobj.timestamp
5222
timestamps[revid] = timestamp
5223
tags.sort(key=lambda x: timestamps[x[1]])
5225
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5226
for index, (tag, revid) in enumerate(tags):
5228
revno = branch.revision_id_to_dotted_revno(revid)
5229
if isinstance(revno, tuple):
5230
revno = '.'.join(map(str, revno))
5231
except errors.NoSuchRevision:
5232
# Bad tag data/merges can lead to tagged revisions
5233
# which are not in this branch. Fail gracefully ...
5235
tags[index] = (tag, revno)
5238
for tag, revspec in tags:
5239
self.outf.write('%-20s %s\n' % (tag, revspec))
5242
class cmd_reconfigure(Command):
5243
"""Reconfigure the type of a bzr directory.
5245
A target configuration must be specified.
5247
For checkouts, the bind-to location will be auto-detected if not specified.
5248
The order of preference is
5249
1. For a lightweight checkout, the current bound location.
5250
2. For branches that used to be checkouts, the previously-bound location.
5251
3. The push location.
5252
4. The parent location.
5253
If none of these is available, --bind-to must be specified.
5256
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5257
takes_args = ['location?']
5259
RegistryOption.from_kwargs(
5261
title='Target type',
5262
help='The type to reconfigure the directory to.',
5263
value_switches=True, enum_switch=False,
5264
branch='Reconfigure to be an unbound branch with no working tree.',
5265
tree='Reconfigure to be an unbound branch with a working tree.',
5266
checkout='Reconfigure to be a bound branch with a working tree.',
5267
lightweight_checkout='Reconfigure to be a lightweight'
5268
' checkout (with no local history).',
5269
standalone='Reconfigure to be a standalone branch '
5270
'(i.e. stop using shared repository).',
5271
use_shared='Reconfigure to use a shared repository.',
5272
with_trees='Reconfigure repository to create '
5273
'working trees on branches by default.',
5274
with_no_trees='Reconfigure repository to not create '
5275
'working trees on branches by default.'
5277
Option('bind-to', help='Branch to bind checkout to.', type=str),
5279
help='Perform reconfiguration even if local changes'
5281
Option('stacked-on',
5282
help='Reconfigure a branch to be stacked on another branch.',
5286
help='Reconfigure a branch to be unstacked. This '
5287
'may require copying substantial data into it.',
5291
def run(self, location=None, target_type=None, bind_to=None, force=False,
5294
directory = bzrdir.BzrDir.open(location)
5295
if stacked_on and unstacked:
5296
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5297
elif stacked_on is not None:
5298
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5300
reconfigure.ReconfigureUnstacked().apply(directory)
5301
# At the moment you can use --stacked-on and a different
5302
# reconfiguration shape at the same time; there seems no good reason
5304
if target_type is None:
5305
if stacked_on or unstacked:
5308
raise errors.BzrCommandError('No target configuration '
5310
elif target_type == 'branch':
5311
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5312
elif target_type == 'tree':
5313
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5314
elif target_type == 'checkout':
5315
reconfiguration = reconfigure.Reconfigure.to_checkout(
5317
elif target_type == 'lightweight-checkout':
5318
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5320
elif target_type == 'use-shared':
5321
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5322
elif target_type == 'standalone':
5323
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5324
elif target_type == 'with-trees':
5325
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5327
elif target_type == 'with-no-trees':
5328
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5330
reconfiguration.apply(force)
5333
class cmd_switch(Command):
5334
"""Set the branch of a checkout and update.
5336
For lightweight checkouts, this changes the branch being referenced.
5337
For heavyweight checkouts, this checks that there are no local commits
5338
versus the current bound branch, then it makes the local branch a mirror
5339
of the new location and binds to it.
5341
In both cases, the working tree is updated and uncommitted changes
5342
are merged. The user can commit or revert these as they desire.
5344
Pending merges need to be committed or reverted before using switch.
5346
The path to the branch to switch to can be specified relative to the parent
5347
directory of the current branch. For example, if you are currently in a
5348
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5351
Bound branches use the nickname of its master branch unless it is set
5352
locally, in which case switching will update the the local nickname to be
5356
takes_args = ['to_location']
5357
takes_options = [Option('force',
5358
help='Switch even if local commits will be lost.'),
5359
Option('create-branch', short_name='b',
5360
help='Create the target branch from this one before'
5361
' switching to it.'),
5364
def run(self, to_location, force=False, create_branch=False):
5365
from bzrlib import switch
5367
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5369
branch = control_dir.open_branch()
5370
had_explicit_nick = branch.get_config().has_explicit_nickname()
5371
except errors.NotBranchError:
5373
had_explicit_nick = False
5376
raise errors.BzrCommandError('cannot create branch without'
5378
if '/' not in to_location and '\\' not in to_location:
5379
# This path is meant to be relative to the existing branch
5380
this_url = self._get_branch_location(control_dir)
5381
to_location = urlutils.join(this_url, '..', to_location)
5382
to_branch = branch.bzrdir.sprout(to_location,
5383
possible_transports=[branch.bzrdir.root_transport],
5384
source_branch=branch).open_branch()
5386
# from_branch = control_dir.open_branch()
5387
# except errors.NotBranchError:
5388
# raise BzrCommandError('Cannot create a branch from this'
5389
# ' location when we cannot open this branch')
5390
# from_branch.bzrdir.sprout(
5394
to_branch = Branch.open(to_location)
5395
except errors.NotBranchError:
5396
this_url = self._get_branch_location(control_dir)
5397
to_branch = Branch.open(
5398
urlutils.join(this_url, '..', to_location))
5399
switch.switch(control_dir, to_branch, force)
5400
if had_explicit_nick:
5401
branch = control_dir.open_branch() #get the new branch!
5402
branch.nick = to_branch.nick
5403
note('Switched to branch: %s',
5404
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5406
def _get_branch_location(self, control_dir):
5407
"""Return location of branch for this control dir."""
5409
this_branch = control_dir.open_branch()
5410
# This may be a heavy checkout, where we want the master branch
5411
master_location = this_branch.get_bound_location()
5412
if master_location is not None:
5413
return master_location
5414
# If not, use a local sibling
5415
return this_branch.base
5416
except errors.NotBranchError:
5417
format = control_dir.find_branch_format()
5418
if getattr(format, 'get_reference', None) is not None:
5419
return format.get_reference(control_dir)
5421
return control_dir.root_transport.base
5424
class cmd_view(Command):
5425
"""Manage filtered views.
5427
Views provide a mask over the tree so that users can focus on
5428
a subset of a tree when doing their work. After creating a view,
5429
commands that support a list of files - status, diff, commit, etc -
5430
effectively have that list of files implicitly given each time.
5431
An explicit list of files can still be given but those files
5432
must be within the current view.
5434
In most cases, a view has a short life-span: it is created to make
5435
a selected change and is deleted once that change is committed.
5436
At other times, you may wish to create one or more named views
5437
and switch between them.
5439
To disable the current view without deleting it, you can switch to
5440
the pseudo view called ``off``. This can be useful when you need
5441
to see the whole tree for an operation or two (e.g. merge) but
5442
want to switch back to your view after that.
5445
To define the current view::
5447
bzr view file1 dir1 ...
5449
To list the current view::
5453
To delete the current view::
5457
To disable the current view without deleting it::
5459
bzr view --switch off
5461
To define a named view and switch to it::
5463
bzr view --name view-name file1 dir1 ...
5465
To list a named view::
5467
bzr view --name view-name
5469
To delete a named view::
5471
bzr view --name view-name --delete
5473
To switch to a named view::
5475
bzr view --switch view-name
5477
To list all views defined::
5481
To delete all views::
5483
bzr view --delete --all
5487
takes_args = ['file*']
5490
help='Apply list or delete action to all views.',
5493
help='Delete the view.',
5496
help='Name of the view to define, list or delete.',
5500
help='Name of the view to switch to.',
5505
def run(self, file_list,
5511
tree, file_list = tree_files(file_list, apply_view=False)
5512
current_view, view_dict = tree.views.get_view_info()
5517
raise errors.BzrCommandError(
5518
"Both --delete and a file list specified")
5520
raise errors.BzrCommandError(
5521
"Both --delete and --switch specified")
5523
tree.views.set_view_info(None, {})
5524
self.outf.write("Deleted all views.\n")
5526
raise errors.BzrCommandError("No current view to delete")
5528
tree.views.delete_view(name)
5529
self.outf.write("Deleted '%s' view.\n" % name)
5532
raise errors.BzrCommandError(
5533
"Both --switch and a file list specified")
5535
raise errors.BzrCommandError(
5536
"Both --switch and --all specified")
5537
elif switch == 'off':
5538
if current_view is None:
5539
raise errors.BzrCommandError("No current view to disable")
5540
tree.views.set_view_info(None, view_dict)
5541
self.outf.write("Disabled '%s' view.\n" % (current_view))
5543
tree.views.set_view_info(switch, view_dict)
5544
view_str = views.view_display_str(tree.views.lookup_view())
5545
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5548
self.outf.write('Views defined:\n')
5549
for view in sorted(view_dict):
5550
if view == current_view:
5554
view_str = views.view_display_str(view_dict[view])
5555
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5557
self.outf.write('No views defined.\n')
5560
# No name given and no current view set
5563
raise errors.BzrCommandError(
5564
"Cannot change the 'off' pseudo view")
5565
tree.views.set_view(name, sorted(file_list))
5566
view_str = views.view_display_str(tree.views.lookup_view())
5567
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5571
# No name given and no current view set
5572
self.outf.write('No current view.\n')
5574
view_str = views.view_display_str(tree.views.lookup_view(name))
5575
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5578
class cmd_hooks(Command):
5584
for hook_key in sorted(hooks.known_hooks.keys()):
5585
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5586
self.outf.write("%s:\n" % type(some_hooks).__name__)
5587
for hook_name, hook_point in sorted(some_hooks.items()):
5588
self.outf.write(" %s:\n" % (hook_name,))
5589
found_hooks = list(hook_point)
5591
for hook in found_hooks:
5592
self.outf.write(" %s\n" %
5593
(some_hooks.get_hook_name(hook),))
5595
self.outf.write(" <no hooks installed>\n")
5598
class cmd_shelve(Command):
5599
"""Temporarily set aside some changes from the current tree.
5601
Shelve allows you to temporarily put changes you've made "on the shelf",
5602
ie. out of the way, until a later time when you can bring them back from
5603
the shelf with the 'unshelve' command. The changes are stored alongside
5604
your working tree, and so they aren't propagated along with your branch nor
5605
will they survive its deletion.
5607
If shelve --list is specified, previously-shelved changes are listed.
5609
Shelve is intended to help separate several sets of changes that have
5610
been inappropriately mingled. If you just want to get rid of all changes
5611
and you don't need to restore them later, use revert. If you want to
5612
shelve all text changes at once, use shelve --all.
5614
If filenames are specified, only the changes to those files will be
5615
shelved. Other files will be left untouched.
5617
If a revision is specified, changes since that revision will be shelved.
5619
You can put multiple items on the shelf, and by default, 'unshelve' will
5620
restore the most recently shelved changes.
5623
takes_args = ['file*']
5627
Option('all', help='Shelve all changes.'),
5629
RegistryOption('writer', 'Method to use for writing diffs.',
5630
bzrlib.option.diff_writer_registry,
5631
value_switches=True, enum_switch=False),
5633
Option('list', help='List shelved changes.'),
5635
help='Destroy removed changes instead of shelving them.'),
5637
_see_also = ['unshelve']
5639
def run(self, revision=None, all=False, file_list=None, message=None,
5640
writer=None, list=False, destroy=False):
5642
return self.run_for_list()
5643
from bzrlib.shelf_ui import Shelver
5645
writer = bzrlib.option.diff_writer_registry.get()
5647
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5648
file_list, message, destroy=destroy)
5652
shelver.work_tree.unlock()
5653
except errors.UserAbort:
5656
def run_for_list(self):
5657
tree = WorkingTree.open_containing('.')[0]
5660
manager = tree.get_shelf_manager()
5661
shelves = manager.active_shelves()
5662
if len(shelves) == 0:
5663
note('No shelved changes.')
5665
for shelf_id in reversed(shelves):
5666
message = manager.get_metadata(shelf_id).get('message')
5668
message = '<no message>'
5669
self.outf.write('%3d: %s\n' % (shelf_id, message))
5675
class cmd_unshelve(Command):
5676
"""Restore shelved changes.
5678
By default, the most recently shelved changes are restored. However if you
5679
specify a shelf by id those changes will be restored instead. This works
5680
best when the changes don't depend on each other.
5683
takes_args = ['shelf_id?']
5685
RegistryOption.from_kwargs(
5686
'action', help="The action to perform.",
5687
enum_switch=False, value_switches=True,
5688
apply="Apply changes and remove from the shelf.",
5689
dry_run="Show changes, but do not apply or remove them.",
5690
delete_only="Delete changes without applying them."
5693
_see_also = ['shelve']
5695
def run(self, shelf_id=None, action='apply'):
5696
from bzrlib.shelf_ui import Unshelver
5697
unshelver = Unshelver.from_args(shelf_id, action)
5701
unshelver.tree.unlock()
5704
class cmd_clean_tree(Command):
5705
"""Remove unwanted files from working tree.
5707
By default, only unknown files, not ignored files, are deleted. Versioned
5708
files are never deleted.
5710
Another class is 'detritus', which includes files emitted by bzr during
5711
normal operations and selftests. (The value of these files decreases with
5714
If no options are specified, unknown files are deleted. Otherwise, option
5715
flags are respected, and may be combined.
5717
To check what clean-tree will do, use --dry-run.
5719
takes_options = [Option('ignored', help='Delete all ignored files.'),
5720
Option('detritus', help='Delete conflict files, merge'
5721
' backups, and failed selftest dirs.'),
5723
help='Delete files unknown to bzr (default).'),
5724
Option('dry-run', help='Show files to delete instead of'
5726
Option('force', help='Do not prompt before deleting.')]
5727
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5729
from bzrlib.clean_tree import clean_tree
5730
if not (unknown or ignored or detritus):
5734
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5735
dry_run=dry_run, no_prompt=force)
5738
class cmd_reference(Command):
5739
"""list, view and set branch locations for nested trees.
5741
If no arguments are provided, lists the branch locations for nested trees.
5742
If one argument is provided, display the branch location for that tree.
5743
If two arguments are provided, set the branch location for that tree.
5748
takes_args = ['path?', 'location?']
5750
def run(self, path=None, location=None):
5752
if path is not None:
5754
tree, branch, relpath =(
5755
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5756
if path is not None:
5759
tree = branch.basis_tree()
5761
info = branch._get_all_reference_info().iteritems()
5762
self._display_reference_info(tree, branch, info)
5764
file_id = tree.path2id(path)
5766
raise errors.NotVersionedError(path)
5767
if location is None:
5768
info = [(file_id, branch.get_reference_info(file_id))]
5769
self._display_reference_info(tree, branch, info)
5771
branch.set_reference_info(file_id, path, location)
5773
def _display_reference_info(self, tree, branch, info):
5775
for file_id, (path, location) in info:
5777
path = tree.id2path(file_id)
5778
except errors.NoSuchId:
5780
ref_list.append((path, location))
5781
for path, location in sorted(ref_list):
5782
self.outf.write('%s %s\n' % (path, location))
4186
5785
# these get imported and then picked up by the scan for cmd_*
4187
5786
# TODO: Some more consistent way to split command definitions across files;
4188
# we do need to load at least some information about them to know of
5787
# we do need to load at least some information about them to know of
4189
5788
# aliases. ideally we would avoid loading the implementation until the
4190
5789
# details were needed.
4191
5790
from bzrlib.cmd_version_info import cmd_version_info