693
1064
' directory exists, but does not already'
694
1065
' have a control directory. This flag will'
695
1066
' allow push to proceed.'),
1068
help='Create a stacked branch that references the public location '
1069
'of the parent branch.'),
1070
Option('stacked-on',
1071
help='Create a stacked branch that refers to another branch '
1072
'for the commit history. Only the work not present in the '
1073
'referenced branch is included in the branch created.',
1076
help='Refuse to push if there are uncommitted changes in'
1077
' the working tree, --no-strict disables the check.'),
697
1079
takes_args = ['location?']
698
1080
encoding_type = 'replace'
700
1082
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
1083
create_prefix=False, verbose=False, revision=None,
1084
use_existing_dir=False, directory=None, stacked_on=None,
1085
stacked=False, strict=None):
1086
from bzrlib.push import _show_push_branch
706
1088
if directory is None:
708
br_from = Branch.open_containing(directory)[0]
709
stored_loc = br_from.get_push_location()
1090
# Get the source branch
1092
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1094
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1095
if strict is None: strict = True # default value
1096
# Get the tip's revision_id
1097
revision = _get_one_revision('push', revision)
1098
if revision is not None:
1099
revision_id = revision.in_history(br_from).rev_id
1102
if strict and tree is not None and revision_id is None:
1103
if (tree.has_changes(tree.basis_tree())
1104
or len(tree.get_parent_ids()) > 1):
1105
raise errors.UncommittedChanges(
1106
tree, more='Use --no-strict to force the push.')
1107
if tree.last_revision() != tree.branch.last_revision():
1108
# The tree has lost sync with its branch, there is little
1109
# chance that the user is aware of it but he can still force
1110
# the push with --no-strict
1111
raise errors.OutOfDateTree(
1112
tree, more='Use --no-strict to force the push.')
1114
# Get the stacked_on branch, if any
1115
if stacked_on is not None:
1116
stacked_on = urlutils.normalize_url(stacked_on)
1118
parent_url = br_from.get_parent()
1120
parent = Branch.open(parent_url)
1121
stacked_on = parent.get_public_branch()
1123
# I considered excluding non-http url's here, thus forcing
1124
# 'public' branches only, but that only works for some
1125
# users, so it's best to just depend on the user spotting an
1126
# error by the feedback given to them. RBC 20080227.
1127
stacked_on = parent_url
1129
raise errors.BzrCommandError(
1130
"Could not determine branch to refer to.")
1132
# Get the destination location
710
1133
if location is None:
1134
stored_loc = br_from.get_push_location()
711
1135
if stored_loc is None:
712
raise errors.BzrCommandError("No push location known or specified.")
1136
raise errors.BzrCommandError(
1137
"No push location known or specified.")
714
1139
display_url = urlutils.unescape_for_display(stored_loc,
715
1140
self.outf.encoding)
716
self.outf.write("Using saved location: %s\n" % display_url)
1141
self.outf.write("Using saved push location: %s\n" % display_url)
717
1142
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
1144
_show_push_branch(br_from, revision_id, location, self.outf,
1145
verbose=verbose, overwrite=overwrite, remember=remember,
1146
stacked_on=stacked_on, create_prefix=create_prefix,
1147
use_existing_dir=use_existing_dir)
835
1150
class cmd_branch(Command):
836
"""Create a new copy of a branch.
1151
"""Create a new branch that is a copy of an existing branch.
838
1153
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
839
1154
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1594
2026
raise errors.BzrCommandError(msg)
2029
def _parse_levels(s):
2033
msg = "The levels argument must be an integer."
2034
raise errors.BzrCommandError(msg)
1597
2037
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
2038
"""Show historical log for a branch or subset of a branch.
2040
log is bzr's default tool for exploring the history of a branch.
2041
The branch to use is taken from the first parameter. If no parameters
2042
are given, the branch containing the working directory is logged.
2043
Here are some simple examples::
2045
bzr log log the current branch
2046
bzr log foo.py log a file in its branch
2047
bzr log http://server/branch log a branch on a server
2049
The filtering, ordering and information shown for each revision can
2050
be controlled as explained below. By default, all revisions are
2051
shown sorted (topologically) so that newer revisions appear before
2052
older ones and descendants always appear before ancestors. If displayed,
2053
merged revisions are shown indented under the revision in which they
2058
The log format controls how information about each revision is
2059
displayed. The standard log formats are called ``long``, ``short``
2060
and ``line``. The default is long. See ``bzr help log-formats``
2061
for more details on log formats.
2063
The following options can be used to control what information is
2066
-l N display a maximum of N revisions
2067
-n N display N levels of revisions (0 for all, 1 for collapsed)
2068
-v display a status summary (delta) for each revision
2069
-p display a diff (patch) for each revision
2070
--show-ids display revision-ids (and file-ids), not just revnos
2072
Note that the default number of levels to display is a function of the
2073
log format. If the -n option is not used, the standard log formats show
2074
just the top level (mainline).
2076
Status summaries are shown using status flags like A, M, etc. To see
2077
the changes explained using words like ``added`` and ``modified``
2078
instead, use the -vv option.
2082
To display revisions from oldest to newest, use the --forward option.
2083
In most cases, using this option will have little impact on the total
2084
time taken to produce a log, though --forward does not incrementally
2085
display revisions like --reverse does when it can.
2087
:Revision filtering:
2089
The -r option can be used to specify what revision or range of revisions
2090
to filter against. The various forms are shown below::
2092
-rX display revision X
2093
-rX.. display revision X and later
2094
-r..Y display up to and including revision Y
2095
-rX..Y display from X to Y inclusive
2097
See ``bzr help revisionspec`` for details on how to specify X and Y.
2098
Some common examples are given below::
2100
-r-1 show just the tip
2101
-r-10.. show the last 10 mainline revisions
2102
-rsubmit:.. show what's new on this branch
2103
-rancestor:path.. show changes since the common ancestor of this
2104
branch and the one at location path
2105
-rdate:yesterday.. show changes since yesterday
2107
When logging a range of revisions using -rX..Y, log starts at
2108
revision Y and searches back in history through the primary
2109
("left-hand") parents until it finds X. When logging just the
2110
top level (using -n1), an error is reported if X is not found
2111
along the way. If multi-level logging is used (-n0), X may be
2112
a nested merge revision and the log will be truncated accordingly.
2116
If parameters are given and the first one is not a branch, the log
2117
will be filtered to show only those revisions that changed the
2118
nominated files or directories.
2120
Filenames are interpreted within their historical context. To log a
2121
deleted file, specify a revision range so that the file existed at
2122
the end or start of the range.
2124
Historical context is also important when interpreting pathnames of
2125
renamed files/directories. Consider the following example:
2127
* revision 1: add tutorial.txt
2128
* revision 2: modify tutorial.txt
2129
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2133
* ``bzr log guide.txt`` will log the file added in revision 1
2135
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2137
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2138
the original file in revision 2.
2140
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2141
was no file called guide.txt in revision 2.
2143
Renames are always followed by log. By design, there is no need to
2144
explicitly ask for this (and no way to stop logging a file back
2145
until it was last renamed).
2149
The --message option can be used for finding revisions that match a
2150
regular expression in a commit message.
2154
GUI tools and IDEs are often better at exploring history than command
2155
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2156
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2157
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2159
Web interfaces are often better at exploring history than command line
2160
tools, particularly for branches on servers. You may prefer Loggerhead
2161
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2163
You may find it useful to add the aliases below to ``bazaar.conf``::
2167
top = log -l10 --line
2170
``bzr tip`` will then show the latest revision while ``bzr top``
2171
will show the last 10 mainline revisions. To see the details of a
2172
particular revision X, ``bzr show -rX``.
2174
If you are interested in looking deeper into a particular merge X,
2175
use ``bzr log -n0 -rX``.
2177
``bzr log -v`` on a branch with lots of history is currently
2178
very slow. A fix for this issue is currently under development.
2179
With or without that fix, it is recommended that a revision range
2180
be given when using the -v option.
2182
bzr has a generic full-text matching plugin, bzr-search, that can be
2183
used to find revisions matching user names, commit messages, etc.
2184
Among other features, this plugin can find all revisions containing
2185
a list of words but not others.
2187
When exploring non-mainline history on large projects with deep
2188
history, the performance of log can be greatly improved by installing
2189
the historycache plugin. This plugin buffers historical information
2190
trading disk space for faster speed.
1620
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1622
takes_args = ['location?']
2192
takes_args = ['file*']
2193
_see_also = ['log-formats', 'revisionspec']
1623
2194
takes_options = [
1624
2195
Option('forward',
1625
2196
help='Show from oldest to newest.'),
1628
help='Display timezone as local, original, or utc.'),
2198
custom_help('verbose',
1631
2199
help='Show files changed in each revision.'),
2203
type=bzrlib.option._parse_revision_str,
2205
help='Show just the specified revision.'
2206
' See also "help revisionspec".'),
2210
help='Number of levels to display - 0 for all, 1 for flat.',
2212
type=_parse_levels),
1635
2213
Option('message',
1636
2214
short_name='m',
1637
2215
help='Show revisions whose message matches this '
1638
2216
'regular expression.',
1640
2218
Option('limit',
1641
2220
help='Limit the output to the first N revisions.',
1643
2222
type=_parse_limit),
2225
help='Show changes made in each revision as a patch.'),
2226
Option('include-merges',
2227
help='Show merged revisions like --levels 0 does.'),
1645
2229
encoding_type = 'replace'
1647
2231
@display_command
1648
def run(self, location=None, timezone='original',
2232
def run(self, file_list=None, timezone='original',
1650
2234
show_ids=False,
1653
2238
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
2243
include_merges=False):
2244
from bzrlib.log import (
2246
make_log_request_dict,
2247
_get_info_for_log_files,
1659
2249
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)
2254
raise errors.BzrCommandError(
2255
'--levels and --include-merges are mutually exclusive')
2257
if change is not None:
2259
raise errors.RangeInChangeOption()
2260
if revision is not None:
2261
raise errors.BzrCommandError(
2262
'--revision and --change are mutually exclusive')
2267
filter_by_dir = False
2269
# find the file ids to log and check for directory filtering
2270
b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2272
for relpath, file_id, kind in file_info_list:
1672
2273
if file_id is None:
1673
2274
raise errors.BzrCommandError(
1674
"Path does not have any revision history: %s" %
2275
"Path unknown at end or start of revision range: %s" %
2277
# If the relpath is the top of the tree, we log everything
2282
file_ids.append(file_id)
2283
filter_by_dir = filter_by_dir or (
2284
kind in ['directory', 'tree-reference'])
1678
# FIXME ? log the current subdir only RBC 20060203
2287
# FIXME ? log the current subdir only RBC 20060203
1679
2288
if revision is not None \
1680
2289
and len(revision) > 0 and revision[0].get_branch():
1681
2290
location = revision[0].get_branch()
1684
2293
dir, relpath = bzrdir.BzrDir.open_containing(location)
1685
2294
b = dir.open_branch()
2295
rev1, rev2 = _get_revision_range(revision, b, self.name())
2297
# Decide on the type of delta & diff filtering to use
2298
# TODO: add an --all-files option to make this configurable & consistent
2306
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.')
2312
# Build the log formatter
1708
2313
if log_format is None:
1709
2314
log_format = log.log_formatter_registry.get_default(b)
1711
2315
lf = log_format(show_ids=show_ids, to_file=self.outf,
1712
show_timezone=timezone)
1718
direction=direction,
1719
start_revision=rev1,
2316
show_timezone=timezone,
2317
delta_format=get_verbosity_level(),
2319
show_advice=levels is None)
2321
# Choose the algorithm for doing the logging. It's annoying
2322
# having multiple code paths like this but necessary until
2323
# the underlying repository format is faster at generating
2324
# deltas or can provide everything we need from the indices.
2325
# The default algorithm - match-using-deltas - works for
2326
# multiple files and directories and is faster for small
2327
# amounts of history (200 revisions say). However, it's too
2328
# slow for logging a single file in a repository with deep
2329
# history, i.e. > 10K revisions. In the spirit of "do no
2330
# evil when adding features", we continue to use the
2331
# original algorithm - per-file-graph - for the "single
2332
# file that isn't a directory without showing a delta" case.
2333
partial_history = revision and b.repository._format.supports_chks
2334
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2335
or delta_type or partial_history)
2337
# Build the LogRequest and execute it
2338
if len(file_ids) == 0:
2340
rqst = make_log_request_dict(
2341
direction=direction, specific_fileids=file_ids,
2342
start_revision=rev1, end_revision=rev2, limit=limit,
2343
message_search=message, delta_type=delta_type,
2344
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2345
Logger(b, rqst).show(lf)
2350
def _get_revision_range(revisionspec_list, branch, command_name):
2351
"""Take the input of a revision option and turn it into a revision range.
2353
It returns RevisionInfo objects which can be used to obtain the rev_id's
2354
of the desired revisions. It does some user input validations.
2356
if revisionspec_list is None:
2359
elif len(revisionspec_list) == 1:
2360
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2361
elif len(revisionspec_list) == 2:
2362
start_spec = revisionspec_list[0]
2363
end_spec = revisionspec_list[1]
2364
if end_spec.get_branch() != start_spec.get_branch():
2365
# b is taken from revision[0].get_branch(), and
2366
# show_log will use its revision_history. Having
2367
# different branches will lead to weird behaviors.
2368
raise errors.BzrCommandError(
2369
"bzr %s doesn't accept two revisions in different"
2370
" branches." % command_name)
2371
rev1 = start_spec.in_history(branch)
2372
# Avoid loading all of history when we know a missing
2373
# end of range means the last revision ...
2374
if end_spec.spec is None:
2375
last_revno, last_revision_id = branch.last_revision_info()
2376
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2378
rev2 = end_spec.in_history(branch)
2380
raise errors.BzrCommandError(
2381
'bzr %s --revision takes one or two values.' % command_name)
2385
def _revision_range_to_revid_range(revision_range):
2388
if revision_range[0] is not None:
2389
rev_id1 = revision_range[0].rev_id
2390
if revision_range[1] is not None:
2391
rev_id2 = revision_range[1].rev_id
2392
return rev_id1, rev_id2
1727
2394
def get_log_format(long=False, short=False, line=False, default='long'):
1728
2395
log_format = default
2527
3390
short_name='x',
2528
3391
help='Exclude tests that match this regular'
2529
3392
' expression.'),
3394
help='Output test progress via subunit.'),
2530
3395
Option('strict', help='Fail on missing dependencies or '
2531
3396
'known failures.'),
3397
Option('load-list', type=str, argname='TESTLISTFILE',
3398
help='Load a test id list from a text file.'),
3399
ListOption('debugflag', type=str, short_name='E',
3400
help='Turn on a selftest debug flag.'),
3401
ListOption('starting-with', type=str, argname='TESTID',
3402
param_name='starting_with', short_name='s',
3404
'Load only the tests starting with TESTID.'),
2533
3406
encoding_type = 'replace'
2535
def run(self, testspecs_list=None, verbose=None, one=False,
3409
Command.__init__(self)
3410
self.additional_selftest_args = {}
3412
def run(self, testspecs_list=None, verbose=False, one=False,
2536
3413
transport=None, benchmark=None,
2537
3414
lsprof_timed=None, cache_dir=None,
2538
3415
first=False, list_only=False,
2539
randomize=None, exclude=None, strict=False):
3416
randomize=None, exclude=None, strict=False,
3417
load_list=None, debugflag=None, starting_with=None, subunit=False,
2541
3419
from bzrlib.tests import selftest
2542
3420
import bzrlib.benchmarks as benchmarks
2543
3421
from bzrlib.benchmarks import tree_creator
2544
from bzrlib.version import show_version
3423
# Make deprecation warnings visible, unless -Werror is set
3424
symbol_versioning.activate_deprecation_warnings(override=False)
2546
3426
if cache_dir is not None:
2547
3427
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
3428
if testspecs_list is not None:
2557
3429
pattern = '|'.join(testspecs_list)
3434
from bzrlib.tests import SubUnitBzrRunner
3436
raise errors.BzrCommandError("subunit not available. subunit "
3437
"needs to be installed to use --subunit.")
3438
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3440
self.additional_selftest_args.setdefault(
3441
'suite_decorators', []).append(parallel)
2561
3443
test_suite_factory = benchmarks.test_suite
3444
# Unless user explicitly asks for quiet, be verbose in benchmarks
3445
verbose = not is_quiet()
2564
3446
# TODO: should possibly lock the history file...
2565
3447
benchfile = open(".perf_history", "at", buffering=1)
2567
3449
test_suite_factory = None
2570
3450
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,
3452
selftest_kwargs = {"verbose": verbose,
3454
"stop_on_failure": one,
3455
"transport": transport,
3456
"test_suite_factory": test_suite_factory,
3457
"lsprof_timed": lsprof_timed,
3458
"bench_history": benchfile,
3459
"matching_tests_first": first,
3460
"list_only": list_only,
3461
"random_seed": randomize,
3462
"exclude_pattern": exclude,
3464
"load_list": load_list,
3465
"debug_flags": debugflag,
3466
"starting_with": starting_with
3468
selftest_kwargs.update(self.additional_selftest_args)
3469
result = selftest(**selftest_kwargs)
2586
3471
if benchfile is not None:
2587
3472
benchfile.close()
2589
info('tests passed')
2591
info('tests failed')
2592
3473
return int(not result)
2595
3476
class cmd_version(Command):
2596
3477
"""Show version of bzr."""
3479
encoding_type = 'replace'
3481
Option("short", help="Print just the version number."),
2598
3484
@display_command
3485
def run(self, short=False):
2600
3486
from bzrlib.version import show_version
3488
self.outf.write(bzrlib.version_string + '\n')
3490
show_version(to_file=self.outf)
2604
3493
class cmd_rocks(Command):
3860
4986
'rather than the one containing the working directory.',
3861
4987
short_name='f',
3863
Option('output', short_name='o', help='Write directive to this file.',
4989
Option('output', short_name='o',
4990
help='Write merge directive to this file; '
4991
'use - for stdout.',
4994
help='Refuse to send if there are uncommitted changes in'
4995
' the working tree, --no-strict disables the check.'),
3865
4996
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',})
5000
Option('body', help='Body for the email.', type=unicode),
5001
RegistryOption('format',
5002
help='Use the specified output format.',
5003
lazy_registry=('bzrlib.send', 'format_registry')),
3875
5006
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
3876
5007
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,
5008
format=None, mail_to=None, message=None, body=None,
5009
strict=None, **kwargs):
5010
from bzrlib.send import send
5011
return send(submit_branch, revision, public_branch, remember,
5012
format, no_bundle, no_patch, output,
5013
kwargs.get('from', '.'), mail_to, message, body,
3982
5018
class cmd_bundle_revisions(cmd_send):
3984
"""Create a merge-directive for submiting changes.
5019
"""Create a merge-directive for submitting changes.
3986
5021
A merge directive provides many things needed for requesting merges:
4122
5164
short_name='d',
5167
RegistryOption.from_kwargs('sort',
5168
'Sort tags by different criteria.', title='Sorting',
5169
alpha='Sort tags lexicographically (default).',
5170
time='Sort tags chronologically.',
4127
5176
@display_command
4131
5183
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
5185
tags = branch.tags.get_tag_dict().items()
5192
graph = branch.repository.get_graph()
5193
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5194
revid1, revid2 = rev1.rev_id, rev2.rev_id
5195
# only show revisions between revid1 and revid2 (inclusive)
5196
tags = [(tag, revid) for tag, revid in tags if
5197
graph.is_between(revid, revid1, revid2)]
5200
elif sort == 'time':
5202
for tag, revid in tags:
5204
revobj = branch.repository.get_revision(revid)
5205
except errors.NoSuchRevision:
5206
timestamp = sys.maxint # place them at the end
5208
timestamp = revobj.timestamp
5209
timestamps[revid] = timestamp
5210
tags.sort(key=lambda x: timestamps[x[1]])
5212
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5213
for index, (tag, revid) in enumerate(tags):
5215
revno = branch.revision_id_to_dotted_revno(revid)
5216
if isinstance(revno, tuple):
5217
revno = '.'.join(map(str, revno))
5218
except errors.NoSuchRevision:
5219
# Bad tag data/merges can lead to tagged revisions
5220
# which are not in this branch. Fail gracefully ...
5222
tags[index] = (tag, revno)
5225
for tag, revspec in tags:
5226
self.outf.write('%-20s %s\n' % (tag, revspec))
5229
class cmd_reconfigure(Command):
5230
"""Reconfigure the type of a bzr directory.
5232
A target configuration must be specified.
5234
For checkouts, the bind-to location will be auto-detected if not specified.
5235
The order of preference is
5236
1. For a lightweight checkout, the current bound location.
5237
2. For branches that used to be checkouts, the previously-bound location.
5238
3. The push location.
5239
4. The parent location.
5240
If none of these is available, --bind-to must be specified.
5243
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5244
takes_args = ['location?']
5246
RegistryOption.from_kwargs(
5248
title='Target type',
5249
help='The type to reconfigure the directory to.',
5250
value_switches=True, enum_switch=False,
5251
branch='Reconfigure to be an unbound branch with no working tree.',
5252
tree='Reconfigure to be an unbound branch with a working tree.',
5253
checkout='Reconfigure to be a bound branch with a working tree.',
5254
lightweight_checkout='Reconfigure to be a lightweight'
5255
' checkout (with no local history).',
5256
standalone='Reconfigure to be a standalone branch '
5257
'(i.e. stop using shared repository).',
5258
use_shared='Reconfigure to use a shared repository.',
5259
with_trees='Reconfigure repository to create '
5260
'working trees on branches by default.',
5261
with_no_trees='Reconfigure repository to not create '
5262
'working trees on branches by default.'
5264
Option('bind-to', help='Branch to bind checkout to.', type=str),
5266
help='Perform reconfiguration even if local changes'
5268
Option('stacked-on',
5269
help='Reconfigure a branch to be stacked on another branch.',
5273
help='Reconfigure a branch to be unstacked. This '
5274
'may require copying substantial data into it.',
5278
def run(self, location=None, target_type=None, bind_to=None, force=False,
5281
directory = bzrdir.BzrDir.open(location)
5282
if stacked_on and unstacked:
5283
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5284
elif stacked_on is not None:
5285
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5287
reconfigure.ReconfigureUnstacked().apply(directory)
5288
# At the moment you can use --stacked-on and a different
5289
# reconfiguration shape at the same time; there seems no good reason
5291
if target_type is None:
5292
if stacked_on or unstacked:
5295
raise errors.BzrCommandError('No target configuration '
5297
elif target_type == 'branch':
5298
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5299
elif target_type == 'tree':
5300
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5301
elif target_type == 'checkout':
5302
reconfiguration = reconfigure.Reconfigure.to_checkout(
5304
elif target_type == 'lightweight-checkout':
5305
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5307
elif target_type == 'use-shared':
5308
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5309
elif target_type == 'standalone':
5310
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5311
elif target_type == 'with-trees':
5312
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5314
elif target_type == 'with-no-trees':
5315
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5317
reconfiguration.apply(force)
5320
class cmd_switch(Command):
5321
"""Set the branch of a checkout and update.
5323
For lightweight checkouts, this changes the branch being referenced.
5324
For heavyweight checkouts, this checks that there are no local commits
5325
versus the current bound branch, then it makes the local branch a mirror
5326
of the new location and binds to it.
5328
In both cases, the working tree is updated and uncommitted changes
5329
are merged. The user can commit or revert these as they desire.
5331
Pending merges need to be committed or reverted before using switch.
5333
The path to the branch to switch to can be specified relative to the parent
5334
directory of the current branch. For example, if you are currently in a
5335
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5338
Bound branches use the nickname of its master branch unless it is set
5339
locally, in which case switching will update the the local nickname to be
5343
takes_args = ['to_location']
5344
takes_options = [Option('force',
5345
help='Switch even if local commits will be lost.'),
5346
Option('create-branch', short_name='b',
5347
help='Create the target branch from this one before'
5348
' switching to it.'),
5351
def run(self, to_location, force=False, create_branch=False):
5352
from bzrlib import switch
5354
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5356
branch = control_dir.open_branch()
5357
had_explicit_nick = branch.get_config().has_explicit_nickname()
5358
except errors.NotBranchError:
5360
had_explicit_nick = False
5363
raise errors.BzrCommandError('cannot create branch without'
5365
if '/' not in to_location and '\\' not in to_location:
5366
# This path is meant to be relative to the existing branch
5367
this_url = self._get_branch_location(control_dir)
5368
to_location = urlutils.join(this_url, '..', to_location)
5369
to_branch = branch.bzrdir.sprout(to_location,
5370
possible_transports=[branch.bzrdir.root_transport],
5371
source_branch=branch).open_branch()
5373
# from_branch = control_dir.open_branch()
5374
# except errors.NotBranchError:
5375
# raise BzrCommandError('Cannot create a branch from this'
5376
# ' location when we cannot open this branch')
5377
# from_branch.bzrdir.sprout(
5381
to_branch = Branch.open(to_location)
5382
except errors.NotBranchError:
5383
this_url = self._get_branch_location(control_dir)
5384
to_branch = Branch.open(
5385
urlutils.join(this_url, '..', to_location))
5386
switch.switch(control_dir, to_branch, force)
5387
if had_explicit_nick:
5388
branch = control_dir.open_branch() #get the new branch!
5389
branch.nick = to_branch.nick
5390
note('Switched to branch: %s',
5391
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5393
def _get_branch_location(self, control_dir):
5394
"""Return location of branch for this control dir."""
5396
this_branch = control_dir.open_branch()
5397
# This may be a heavy checkout, where we want the master branch
5398
master_location = this_branch.get_bound_location()
5399
if master_location is not None:
5400
return master_location
5401
# If not, use a local sibling
5402
return this_branch.base
5403
except errors.NotBranchError:
5404
format = control_dir.find_branch_format()
5405
if getattr(format, 'get_reference', None) is not None:
5406
return format.get_reference(control_dir)
5408
return control_dir.root_transport.base
5411
class cmd_view(Command):
5412
"""Manage filtered views.
5414
Views provide a mask over the tree so that users can focus on
5415
a subset of a tree when doing their work. After creating a view,
5416
commands that support a list of files - status, diff, commit, etc -
5417
effectively have that list of files implicitly given each time.
5418
An explicit list of files can still be given but those files
5419
must be within the current view.
5421
In most cases, a view has a short life-span: it is created to make
5422
a selected change and is deleted once that change is committed.
5423
At other times, you may wish to create one or more named views
5424
and switch between them.
5426
To disable the current view without deleting it, you can switch to
5427
the pseudo view called ``off``. This can be useful when you need
5428
to see the whole tree for an operation or two (e.g. merge) but
5429
want to switch back to your view after that.
5432
To define the current view::
5434
bzr view file1 dir1 ...
5436
To list the current view::
5440
To delete the current view::
5444
To disable the current view without deleting it::
5446
bzr view --switch off
5448
To define a named view and switch to it::
5450
bzr view --name view-name file1 dir1 ...
5452
To list a named view::
5454
bzr view --name view-name
5456
To delete a named view::
5458
bzr view --name view-name --delete
5460
To switch to a named view::
5462
bzr view --switch view-name
5464
To list all views defined::
5468
To delete all views::
5470
bzr view --delete --all
5474
takes_args = ['file*']
5477
help='Apply list or delete action to all views.',
5480
help='Delete the view.',
5483
help='Name of the view to define, list or delete.',
5487
help='Name of the view to switch to.',
5492
def run(self, file_list,
5498
tree, file_list = tree_files(file_list, apply_view=False)
5499
current_view, view_dict = tree.views.get_view_info()
5504
raise errors.BzrCommandError(
5505
"Both --delete and a file list specified")
5507
raise errors.BzrCommandError(
5508
"Both --delete and --switch specified")
5510
tree.views.set_view_info(None, {})
5511
self.outf.write("Deleted all views.\n")
5513
raise errors.BzrCommandError("No current view to delete")
5515
tree.views.delete_view(name)
5516
self.outf.write("Deleted '%s' view.\n" % name)
5519
raise errors.BzrCommandError(
5520
"Both --switch and a file list specified")
5522
raise errors.BzrCommandError(
5523
"Both --switch and --all specified")
5524
elif switch == 'off':
5525
if current_view is None:
5526
raise errors.BzrCommandError("No current view to disable")
5527
tree.views.set_view_info(None, view_dict)
5528
self.outf.write("Disabled '%s' view.\n" % (current_view))
5530
tree.views.set_view_info(switch, view_dict)
5531
view_str = views.view_display_str(tree.views.lookup_view())
5532
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5535
self.outf.write('Views defined:\n')
5536
for view in sorted(view_dict):
5537
if view == current_view:
5541
view_str = views.view_display_str(view_dict[view])
5542
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5544
self.outf.write('No views defined.\n')
5547
# No name given and no current view set
5550
raise errors.BzrCommandError(
5551
"Cannot change the 'off' pseudo view")
5552
tree.views.set_view(name, sorted(file_list))
5553
view_str = views.view_display_str(tree.views.lookup_view())
5554
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5558
# No name given and no current view set
5559
self.outf.write('No current view.\n')
5561
view_str = views.view_display_str(tree.views.lookup_view(name))
5562
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5565
class cmd_hooks(Command):
5571
for hook_key in sorted(hooks.known_hooks.keys()):
5572
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5573
self.outf.write("%s:\n" % type(some_hooks).__name__)
5574
for hook_name, hook_point in sorted(some_hooks.items()):
5575
self.outf.write(" %s:\n" % (hook_name,))
5576
found_hooks = list(hook_point)
5578
for hook in found_hooks:
5579
self.outf.write(" %s\n" %
5580
(some_hooks.get_hook_name(hook),))
5582
self.outf.write(" <no hooks installed>\n")
5585
class cmd_shelve(Command):
5586
"""Temporarily set aside some changes from the current tree.
5588
Shelve allows you to temporarily put changes you've made "on the shelf",
5589
ie. out of the way, until a later time when you can bring them back from
5590
the shelf with the 'unshelve' command. The changes are stored alongside
5591
your working tree, and so they aren't propagated along with your branch nor
5592
will they survive its deletion.
5594
If shelve --list is specified, previously-shelved changes are listed.
5596
Shelve is intended to help separate several sets of changes that have
5597
been inappropriately mingled. If you just want to get rid of all changes
5598
and you don't need to restore them later, use revert. If you want to
5599
shelve all text changes at once, use shelve --all.
5601
If filenames are specified, only the changes to those files will be
5602
shelved. Other files will be left untouched.
5604
If a revision is specified, changes since that revision will be shelved.
5606
You can put multiple items on the shelf, and by default, 'unshelve' will
5607
restore the most recently shelved changes.
5610
takes_args = ['file*']
5614
Option('all', help='Shelve all changes.'),
5616
RegistryOption('writer', 'Method to use for writing diffs.',
5617
bzrlib.option.diff_writer_registry,
5618
value_switches=True, enum_switch=False),
5620
Option('list', help='List shelved changes.'),
5622
help='Destroy removed changes instead of shelving them.'),
5624
_see_also = ['unshelve']
5626
def run(self, revision=None, all=False, file_list=None, message=None,
5627
writer=None, list=False, destroy=False):
5629
return self.run_for_list()
5630
from bzrlib.shelf_ui import Shelver
5632
writer = bzrlib.option.diff_writer_registry.get()
5634
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5635
message, destroy=destroy).run()
5636
except errors.UserAbort:
5639
def run_for_list(self):
5640
tree = WorkingTree.open_containing('.')[0]
5643
manager = tree.get_shelf_manager()
5644
shelves = manager.active_shelves()
5645
if len(shelves) == 0:
5646
note('No shelved changes.')
5648
for shelf_id in reversed(shelves):
5649
message = manager.get_metadata(shelf_id).get('message')
5651
message = '<no message>'
5652
self.outf.write('%3d: %s\n' % (shelf_id, message))
5658
class cmd_unshelve(Command):
5659
"""Restore shelved changes.
5661
By default, the most recently shelved changes are restored. However if you
5662
specify a shelf by id those changes will be restored instead. This works
5663
best when the changes don't depend on each other.
5666
takes_args = ['shelf_id?']
5668
RegistryOption.from_kwargs(
5669
'action', help="The action to perform.",
5670
enum_switch=False, value_switches=True,
5671
apply="Apply changes and remove from the shelf.",
5672
dry_run="Show changes, but do not apply or remove them.",
5673
delete_only="Delete changes without applying them."
5676
_see_also = ['shelve']
5678
def run(self, shelf_id=None, action='apply'):
5679
from bzrlib.shelf_ui import Unshelver
5680
Unshelver.from_args(shelf_id, action).run()
5683
class cmd_clean_tree(Command):
5684
"""Remove unwanted files from working tree.
5686
By default, only unknown files, not ignored files, are deleted. Versioned
5687
files are never deleted.
5689
Another class is 'detritus', which includes files emitted by bzr during
5690
normal operations and selftests. (The value of these files decreases with
5693
If no options are specified, unknown files are deleted. Otherwise, option
5694
flags are respected, and may be combined.
5696
To check what clean-tree will do, use --dry-run.
5698
takes_options = [Option('ignored', help='Delete all ignored files.'),
5699
Option('detritus', help='Delete conflict files, merge'
5700
' backups, and failed selftest dirs.'),
5702
help='Delete files unknown to bzr (default).'),
5703
Option('dry-run', help='Show files to delete instead of'
5705
Option('force', help='Do not prompt before deleting.')]
5706
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5708
from bzrlib.clean_tree import clean_tree
5709
if not (unknown or ignored or detritus):
5713
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5714
dry_run=dry_run, no_prompt=force)
5717
class cmd_reference(Command):
5718
"""list, view and set branch locations for nested trees.
5720
If no arguments are provided, lists the branch locations for nested trees.
5721
If one argument is provided, display the branch location for that tree.
5722
If two arguments are provided, set the branch location for that tree.
5727
takes_args = ['path?', 'location?']
5729
def run(self, path=None, location=None):
5731
if path is not None:
5733
tree, branch, relpath =(
5734
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5735
if path is not None:
5738
tree = branch.basis_tree()
5740
info = branch._get_all_reference_info().iteritems()
5741
self._display_reference_info(tree, branch, info)
5743
file_id = tree.path2id(path)
5745
raise errors.NotVersionedError(path)
5746
if location is None:
5747
info = [(file_id, branch.get_reference_info(file_id))]
5748
self._display_reference_info(tree, branch, info)
5750
branch.set_reference_info(file_id, path, location)
5752
def _display_reference_info(self, tree, branch, info):
5754
for file_id, (path, location) in info:
5756
path = tree.id2path(file_id)
5757
except errors.NoSuchId:
5759
ref_list.append((path, location))
5760
for path, location in sorted(ref_list):
5761
self.outf.write('%s %s\n' % (path, location))
4186
5764
# these get imported and then picked up by the scan for cmd_*
4187
5765
# 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
5766
# we do need to load at least some information about them to know of
4189
5767
# aliases. ideally we would avoid loading the implementation until the
4190
5768
# details were needed.
4191
5769
from bzrlib.cmd_version_info import cmd_version_info