50
52
from bzrlib.branch import Branch
51
53
from bzrlib.conflicts import ConflictList
52
from bzrlib.revisionspec import RevisionSpec
54
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
53
55
from bzrlib.smtp_connection import SMTPConnection
54
56
from bzrlib.workingtree import WorkingTree
57
59
from bzrlib.commands import Command, display_command
58
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
from bzrlib.trace import mutter, note, warning, is_quiet, info
62
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,
64
return internal_tree_files(file_list, default_branch)
73
return internal_tree_files(file_list, default_branch, canonicalize,
65
75
except errors.FileInWrongBranch, e:
66
76
raise errors.BzrCommandError("%s is not in the same branch as %s" %
67
77
(e.path, file_list[0]))
80
def tree_files_for_add(file_list):
81
"""Add handles files a bit differently so it a custom implementation."""
83
tree = WorkingTree.open_containing(file_list[0])[0]
84
if tree.supports_views():
85
view_files = tree.views.lookup_view()
87
for filename in file_list:
88
if not osutils.is_inside_any(view_files, filename):
89
raise errors.FileOutsideView(filename, view_files)
91
tree = WorkingTree.open_containing(u'.')[0]
92
if tree.supports_views():
93
view_files = tree.views.lookup_view()
95
file_list = view_files
96
view_str = views.view_display_str(view_files)
97
note("ignoring files outside view: %s" % view_str)
98
return tree, file_list
101
def _get_one_revision(command_name, revisions):
102
if revisions is None:
104
if len(revisions) != 1:
105
raise errors.BzrCommandError(
106
'bzr %s --revision takes exactly one revision identifier' % (
111
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
114
if revisions is None:
116
rev_tree = tree.basis_tree()
118
rev_tree = branch.basis_tree()
120
revision = _get_one_revision(command_name, revisions)
121
rev_tree = revision.as_tree(branch)
70
125
# XXX: Bad function name; should possibly also be a class method of
71
126
# WorkingTree rather than a function.
72
def internal_tree_files(file_list, default_branch=u'.'):
127
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
73
129
"""Convert command-line paths to a WorkingTree and relative paths.
75
131
This is typically used for command-line processors that take one or
78
134
The filenames given are not required to exist.
80
:param file_list: Filenames to convert.
136
:param file_list: Filenames to convert.
82
138
:param default_branch: Fallback tree path to use if file_list is empty or
141
:param apply_view: if True and a view is set, apply it or check that
142
specified files are within it
85
144
:return: workingtree, [relative_paths]
87
146
if file_list is None or len(file_list) == 0:
88
return WorkingTree.open_containing(default_branch)[0], file_list
147
tree = WorkingTree.open_containing(default_branch)[0]
148
if tree.supports_views() and apply_view:
149
view_files = tree.views.lookup_view()
151
file_list = view_files
152
view_str = views.view_display_str(view_files)
153
note("ignoring files outside view: %s" % view_str)
154
return tree, file_list
89
155
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
156
return tree, safe_relpath_files(tree, file_list, canonicalize,
157
apply_view=apply_view)
160
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
161
"""Convert file_list into a list of relpaths in tree.
163
:param tree: A tree to operate on.
164
:param file_list: A list of user provided paths or None.
165
:param apply_view: if True and a view is set, apply it or check that
166
specified files are within it
167
:return: A list of relative paths.
168
:raises errors.PathNotChild: When a provided path is in a different tree
171
if file_list is None:
173
if tree.supports_views() and apply_view:
174
view_files = tree.views.lookup_view()
178
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
179
# doesn't - fix that up here before we enter the loop.
181
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
91
184
for filename in file_list:
93
new_list.append(tree.relpath(osutils.dereference_path(filename)))
186
relpath = fixer(osutils.dereference_path(filename))
187
if view_files and not osutils.is_inside_any(view_files, relpath):
188
raise errors.FileOutsideView(filename, view_files)
189
new_list.append(relpath)
94
190
except errors.PathNotChild:
95
191
raise errors.FileInWrongBranch(tree.branch, filename)
99
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
100
def get_format_type(typestring):
101
"""Parse and return a format specifier."""
102
# Have to use BzrDirMetaFormat1 directly, so that
103
# RepositoryFormat.set_default_format works
104
if typestring == "default":
105
return bzrdir.BzrDirMetaFormat1()
195
def _get_view_info_for_change_reporter(tree):
196
"""Get the view information from a tree for change reporting."""
107
return bzrdir.format_registry.make_bzrdir(typestring)
109
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
raise errors.BzrCommandError(msg)
199
current_view = tree.views.get_view_info()[0]
200
if current_view is not None:
201
view_info = (current_view, tree.views.lookup_view())
202
except errors.ViewsNotSupported:
113
207
# TODO: Make sure no commands unconditionally use the working directory as a
146
240
To see ignored files use 'bzr ignored'. For details on the
147
241
changes to file texts, use 'bzr diff'.
149
243
Note that --short or -S gives status flags for each item, similar
150
244
to Subversion's status command. To get output similar to svn -q,
153
247
If no arguments are specified, the status of the entire working
154
248
directory is shown. Otherwise, only the status of the specified
155
249
files or directories is reported. If a directory is given, status
156
250
is reported for everything inside that directory.
252
Before merges are committed, the pending merge tip revisions are
253
shown. To see all pending merge revisions, use the -v option.
254
To skip the display of pending merge information altogether, use
255
the no-pending option or specify a file/directory.
158
257
If a revision argument is given, the status is calculated against
159
258
that revision, or between two revisions if two are provided.
162
261
# TODO: --no-recurse, --recurse options
164
263
takes_args = ['file*']
165
takes_options = ['show-ids', 'revision', 'change',
264
takes_options = ['show-ids', 'revision', 'change', 'verbose',
166
265
Option('short', help='Use short status indicators.',
168
267
Option('versioned', help='Only show versioned files.',
269
Option('no-pending', help='Don\'t show pending merges.',
171
272
aliases = ['st', 'stat']
173
274
encoding_type = 'replace'
174
275
_see_also = ['diff', 'revert', 'status-flags']
177
278
def run(self, show_ids=False, file_list=None, revision=None, short=False,
279
versioned=False, no_pending=False, verbose=False):
179
280
from bzrlib.status import show_tree_status
181
282
if revision and len(revision) > 2:
182
283
raise errors.BzrCommandError('bzr status --revision takes exactly'
183
284
' one or two revision specifiers')
185
tree, file_list = tree_files(file_list)
286
tree, relfile_list = tree_files(file_list)
287
# Avoid asking for specific files when that is not needed.
288
if relfile_list == ['']:
290
# Don't disable pending merges for full trees other than '.'.
291
if file_list == ['.']:
293
# A specific path within a tree was given.
294
elif relfile_list is not None:
187
296
show_tree_status(tree, show_ids=show_ids,
188
specific_files=file_list, revision=revision,
189
to_file=self.outf, short=short, versioned=versioned)
297
specific_files=relfile_list, revision=revision,
298
to_file=self.outf, short=short, versioned=versioned,
299
show_pending=(not no_pending), verbose=verbose)
192
302
class cmd_cat_revision(Command):
193
303
"""Write out metadata for a revision.
195
305
The revision to print can either be specified by a specific
196
306
revision identifier, or you can use --revision.
215
325
# TODO: jam 20060112 should cat-revision always output utf-8?
216
326
if revision_id is not None:
217
327
revision_id = osutils.safe_revision_id(revision_id, warn=False)
218
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
329
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
330
except errors.NoSuchRevision:
331
msg = "The repository %s contains no revision %s." % (b.repository.base,
333
raise errors.BzrCommandError(msg)
219
334
elif revision is not None:
220
335
for rev in revision:
222
337
raise errors.BzrCommandError('You cannot specify a NULL'
224
revno, rev_id = rev.in_history(b)
339
rev_id = rev.as_revision_id(b)
225
340
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
343
class cmd_dump_btree(Command):
344
"""Dump the contents of a btree index file to stdout.
346
PATH is a btree index file, it can be any URL. This includes things like
347
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
349
By default, the tuples stored in the index file will be displayed. With
350
--raw, we will uncompress the pages, but otherwise display the raw bytes
354
# TODO: Do we want to dump the internal nodes as well?
355
# TODO: It would be nice to be able to dump the un-parsed information,
356
# rather than only going through iter_all_entries. However, this is
357
# good enough for a start
359
encoding_type = 'exact'
360
takes_args = ['path']
361
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
362
' rather than the parsed tuples.'),
365
def run(self, path, raw=False):
366
dirname, basename = osutils.split(path)
367
t = transport.get_transport(dirname)
369
self._dump_raw_bytes(t, basename)
371
self._dump_entries(t, basename)
373
def _get_index_and_bytes(self, trans, basename):
374
"""Create a BTreeGraphIndex and raw bytes."""
375
bt = btree_index.BTreeGraphIndex(trans, basename, None)
376
bytes = trans.get_bytes(basename)
377
bt._file = cStringIO.StringIO(bytes)
378
bt._size = len(bytes)
381
def _dump_raw_bytes(self, trans, basename):
384
# We need to parse at least the root node.
385
# This is because the first page of every row starts with an
386
# uncompressed header.
387
bt, bytes = self._get_index_and_bytes(trans, basename)
388
for page_idx, page_start in enumerate(xrange(0, len(bytes),
389
btree_index._PAGE_SIZE)):
390
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
391
page_bytes = bytes[page_start:page_end]
393
self.outf.write('Root node:\n')
394
header_end, data = bt._parse_header_from_bytes(page_bytes)
395
self.outf.write(page_bytes[:header_end])
397
self.outf.write('\nPage %d\n' % (page_idx,))
398
decomp_bytes = zlib.decompress(page_bytes)
399
self.outf.write(decomp_bytes)
400
self.outf.write('\n')
402
def _dump_entries(self, trans, basename):
404
st = trans.stat(basename)
405
except errors.TransportNotPossible:
406
# We can't stat, so we'll fake it because we have to do the 'get()'
408
bt, _ = self._get_index_and_bytes(trans, basename)
410
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
411
for node in bt.iter_all_entries():
412
# Node is made up of:
413
# (index, key, value, [references])
414
self.outf.write('%s\n' % (node[1:],))
228
417
class cmd_remove_tree(Command):
229
418
"""Remove the working tree from a given branch/checkout.
544
770
raise errors.BzrCommandError('to mv multiple files the'
545
771
' destination must be a versioned'
547
tree.rename_one(rel_names[0], rel_names[1], after=after)
548
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
774
# for cicp file-systems: the src references an existing inventory
776
src = tree.get_canonical_inventory_path(rel_names[0])
777
# Find the canonical version of the destination: In all cases, the
778
# parent of the target must be in the inventory, so we fetch the
779
# canonical version from there (we do not always *use* the
780
# canonicalized tail portion - we may be attempting to rename the
782
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
783
dest_parent = osutils.dirname(canon_dest)
784
spec_tail = osutils.basename(rel_names[1])
785
# For a CICP file-system, we need to avoid creating 2 inventory
786
# entries that differ only by case. So regardless of the case
787
# we *want* to use (ie, specified by the user or the file-system),
788
# we must always choose to use the case of any existing inventory
789
# items. The only exception to this is when we are attempting a
790
# case-only rename (ie, canonical versions of src and dest are
792
dest_id = tree.path2id(canon_dest)
793
if dest_id is None or tree.path2id(src) == dest_id:
794
# No existing item we care about, so work out what case we
795
# are actually going to use.
797
# If 'after' is specified, the tail must refer to a file on disk.
799
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
801
# pathjoin with an empty tail adds a slash, which breaks
803
dest_parent_fq = tree.basedir
805
dest_tail = osutils.canonical_relpath(
807
osutils.pathjoin(dest_parent_fq, spec_tail))
809
# not 'after', so case as specified is used
810
dest_tail = spec_tail
812
# Use the existing item so 'mv' fails with AlreadyVersioned.
813
dest_tail = os.path.basename(canon_dest)
814
dest = osutils.pathjoin(dest_parent, dest_tail)
815
mutter("attempting to move %s => %s", src, dest)
816
tree.rename_one(src, dest, after=after)
817
self.outf.write("%s => %s\n" % (src, dest))
551
820
class cmd_pull(Command):
552
821
"""Turn this branch into a mirror of another branch.
696
971
' directory exists, but does not already'
697
972
' have a control directory. This flag will'
698
973
' allow push to proceed.'),
975
help='Create a stacked branch that references the public location '
976
'of the parent branch.'),
978
help='Create a stacked branch that refers to another branch '
979
'for the commit history. Only the work not present in the '
980
'referenced branch is included in the branch created.',
700
983
takes_args = ['location?']
701
984
encoding_type = 'replace'
703
986
def run(self, location=None, remember=False, overwrite=False,
704
create_prefix=False, verbose=False,
705
use_existing_dir=False,
707
# FIXME: Way too big! Put this into a function called from the
987
create_prefix=False, verbose=False, revision=None,
988
use_existing_dir=False, directory=None, stacked_on=None,
990
from bzrlib.push import _show_push_branch
992
# Get the source branch and revision_id
709
993
if directory is None:
711
995
br_from = Branch.open_containing(directory)[0]
712
stored_loc = br_from.get_push_location()
996
revision = _get_one_revision('push', revision)
997
if revision is not None:
998
revision_id = revision.in_history(br_from).rev_id
1000
revision_id = br_from.last_revision()
1002
# Get the stacked_on branch, if any
1003
if stacked_on is not None:
1004
stacked_on = urlutils.normalize_url(stacked_on)
1006
parent_url = br_from.get_parent()
1008
parent = Branch.open(parent_url)
1009
stacked_on = parent.get_public_branch()
1011
# I considered excluding non-http url's here, thus forcing
1012
# 'public' branches only, but that only works for some
1013
# users, so it's best to just depend on the user spotting an
1014
# error by the feedback given to them. RBC 20080227.
1015
stacked_on = parent_url
1017
raise errors.BzrCommandError(
1018
"Could not determine branch to refer to.")
1020
# Get the destination location
713
1021
if location is None:
1022
stored_loc = br_from.get_push_location()
714
1023
if stored_loc is None:
715
raise errors.BzrCommandError("No push location known or specified.")
1024
raise errors.BzrCommandError(
1025
"No push location known or specified.")
717
1027
display_url = urlutils.unescape_for_display(stored_loc,
718
1028
self.outf.encoding)
719
self.outf.write("Using saved location: %s\n" % display_url)
1029
self.outf.write("Using saved push location: %s\n" % display_url)
720
1030
location = stored_loc
722
to_transport = transport.get_transport(location)
724
br_to = repository_to = dir_to = None
726
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
727
except errors.NotBranchError:
728
pass # Didn't find anything
730
# If we can open a branch, use its direct repository, otherwise see
731
# if there is a repository without a branch.
733
br_to = dir_to.open_branch()
734
except errors.NotBranchError:
735
# Didn't find a branch, can we find a repository?
737
repository_to = dir_to.find_repository()
738
except errors.NoRepositoryPresent:
741
# Found a branch, so we must have found a repository
742
repository_to = br_to.repository
747
# The destination doesn't exist; create it.
748
# XXX: Refactor the create_prefix/no_create_prefix code into a
749
# common helper function
751
def make_directory(transport):
755
def redirected(redirected_transport, e, redirection_notice):
756
return transport.get_transport(e.get_target_url())
759
to_transport = transport.do_catching_redirections(
760
make_directory, to_transport, redirected)
761
except errors.FileExists:
762
if not use_existing_dir:
763
raise errors.BzrCommandError("Target directory %s"
764
" already exists, but does not have a valid .bzr"
765
" directory. Supply --use-existing-dir to push"
766
" there anyway." % location)
767
except errors.NoSuchFile:
768
if not create_prefix:
769
raise errors.BzrCommandError("Parent directory of %s"
771
"\nYou may supply --create-prefix to create all"
772
" leading parent directories."
774
_create_prefix(to_transport)
775
except errors.TooManyRedirections:
776
raise errors.BzrCommandError("Too many redirections trying "
777
"to make %s." % location)
779
# Now the target directory exists, but doesn't have a .bzr
780
# directory. So we need to create it, along with any work to create
781
# all of the dependent branches, etc.
782
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
783
revision_id=br_from.last_revision())
784
br_to = dir_to.open_branch()
785
# TODO: Some more useful message about what was copied
786
note('Created new branch.')
787
# We successfully created the target, remember it
788
if br_from.get_push_location() is None or remember:
789
br_from.set_push_location(br_to.base)
790
elif repository_to is None:
791
# we have a bzrdir but no branch or repository
792
# XXX: Figure out what to do other than complain.
793
raise errors.BzrCommandError("At %s you have a valid .bzr control"
794
" directory, but not a branch or repository. This is an"
795
" unsupported configuration. Please move the target directory"
796
" out of the way and try again."
799
# We have a repository but no branch, copy the revisions, and then
801
last_revision_id = br_from.last_revision()
802
repository_to.fetch(br_from.repository,
803
revision_id=last_revision_id)
804
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
805
note('Created new branch.')
806
if br_from.get_push_location() is None or remember:
807
br_from.set_push_location(br_to.base)
808
else: # We have a valid to branch
809
# We were able to connect to the remote location, so remember it
810
# we don't need to successfully push because of possible divergence.
811
if br_from.get_push_location() is None or remember:
812
br_from.set_push_location(br_to.base)
814
old_rh = br_to.revision_history()
817
tree_to = dir_to.open_workingtree()
818
except errors.NotLocalUrl:
819
warning("This transport does not update the working "
820
"tree of: %s. See 'bzr help working-trees' for "
821
"more information." % br_to.base)
822
push_result = br_from.push(br_to, overwrite)
823
except errors.NoWorkingTree:
824
push_result = br_from.push(br_to, overwrite)
828
push_result = br_from.push(tree_to.branch, overwrite)
832
except errors.DivergedBranches:
833
raise errors.BzrCommandError('These branches have diverged.'
834
' Try using "merge" and then "push".')
835
if push_result is not None:
836
push_result.report(self.outf)
838
new_rh = br_to.revision_history()
841
from bzrlib.log import show_changed_revisions
842
show_changed_revisions(br_to, old_rh, new_rh,
845
# we probably did a clone rather than a push, so a message was
1032
_show_push_branch(br_from, revision_id, location, self.outf,
1033
verbose=verbose, overwrite=overwrite, remember=remember,
1034
stacked_on=stacked_on, create_prefix=create_prefix,
1035
use_existing_dir=use_existing_dir)
850
1038
class cmd_branch(Command):
1322
1558
_create_prefix(to_transport)
1325
existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1561
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1326
1562
except errors.NotBranchError:
1327
1563
# really a NotBzrDir error...
1328
1564
create_branch = bzrdir.BzrDir.create_branch_convenience
1329
1565
branch = create_branch(to_transport.base, format=format,
1330
1566
possible_transports=[to_transport])
1567
a_bzrdir = branch.bzrdir
1332
1569
from bzrlib.transport.local import LocalTransport
1333
if existing_bzrdir.has_branch():
1570
if a_bzrdir.has_branch():
1334
1571
if (isinstance(to_transport, LocalTransport)
1335
and not existing_bzrdir.has_workingtree()):
1572
and not a_bzrdir.has_workingtree()):
1336
1573
raise errors.BranchExistsWithoutWorkingTree(location)
1337
1574
raise errors.AlreadyBranchError(location)
1339
branch = existing_bzrdir.create_branch()
1340
existing_bzrdir.create_workingtree()
1575
branch = a_bzrdir.create_branch()
1576
a_bzrdir.create_workingtree()
1341
1577
if append_revisions_only:
1343
1579
branch.set_append_revisions_only(True)
1344
1580
except errors.UpgradeRequired:
1345
1581
raise errors.BzrCommandError('This branch format cannot be set'
1346
1582
' to append-revisions-only. Try --experimental-branch6')
1584
from bzrlib.info import describe_layout, describe_format
1586
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1587
except (errors.NoWorkingTree, errors.NotLocalUrl):
1589
repository = branch.repository
1590
layout = describe_layout(repository, branch, tree).lower()
1591
format = describe_format(a_bzrdir, repository, branch, tree)
1592
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1593
if repository.is_shared():
1594
#XXX: maybe this can be refactored into transport.path_or_url()
1595
url = repository.bzrdir.root_transport.external_url()
1597
url = urlutils.local_path_from_url(url)
1598
except errors.InvalidURL:
1600
self.outf.write("Using shared repository: %s\n" % url)
1349
1603
class cmd_init_repository(Command):
1614
1888
raise errors.BzrCommandError(msg)
1891
def _parse_levels(s):
1895
msg = "The levels argument must be an integer."
1896
raise errors.BzrCommandError(msg)
1617
1899
class cmd_log(Command):
1618
"""Show log of a branch, file, or directory.
1620
By default show the log of the branch containing the working directory.
1622
To request a range of logs, you can use the command -r begin..end
1623
-r revision requests a specific revision, -r ..end or -r begin.. are
1627
Log the current branch::
1635
Log the last 10 revisions of a branch::
1637
bzr log -r -10.. http://server/branch
1900
"""Show historical log for a branch or subset of a branch.
1902
log is bzr's default tool for exploring the history of a branch.
1903
The branch to use is taken from the first parameter. If no parameters
1904
are given, the branch containing the working directory is logged.
1905
Here are some simple examples::
1907
bzr log log the current branch
1908
bzr log foo.py log a file in its branch
1909
bzr log http://server/branch log a branch on a server
1911
The filtering, ordering and information shown for each revision can
1912
be controlled as explained below. By default, all revisions are
1913
shown sorted (topologically) so that newer revisions appear before
1914
older ones and descendants always appear before ancestors. If displayed,
1915
merged revisions are shown indented under the revision in which they
1920
The log format controls how information about each revision is
1921
displayed. The standard log formats are called ``long``, ``short``
1922
and ``line``. The default is long. See ``bzr help log-formats``
1923
for more details on log formats.
1925
The following options can be used to control what information is
1928
-l N display a maximum of N revisions
1929
-n N display N levels of revisions (0 for all, 1 for collapsed)
1930
-v display a status summary (delta) for each revision
1931
-p display a diff (patch) for each revision
1932
--show-ids display revision-ids (and file-ids), not just revnos
1934
Note that the default number of levels to display is a function of the
1935
log format. If the -n option is not used, ``short`` and ``line`` show
1936
just the top level (mainline) while ``long`` shows all levels of merged
1939
Status summaries are shown using status flags like A, M, etc. To see
1940
the changes explained using words like ``added`` and ``modified``
1941
instead, use the -vv option.
1945
To display revisions from oldest to newest, use the --forward option.
1946
In most cases, using this option will have little impact on the total
1947
time taken to produce a log, though --forward does not incrementally
1948
display revisions like --reverse does when it can.
1950
:Revision filtering:
1952
The -r option can be used to specify what revision or range of revisions
1953
to filter against. The various forms are shown below::
1955
-rX display revision X
1956
-rX.. display revision X and later
1957
-r..Y display up to and including revision Y
1958
-rX..Y display from X to Y inclusive
1960
See ``bzr help revisionspec`` for details on how to specify X and Y.
1961
Some common examples are given below::
1963
-r-1 show just the tip
1964
-r-10.. show the last 10 mainline revisions
1965
-rsubmit:.. show what's new on this branch
1966
-rancestor:path.. show changes since the common ancestor of this
1967
branch and the one at location path
1968
-rdate:yesterday.. show changes since yesterday
1970
When logging a range of revisions using -rX..Y, log starts at
1971
revision Y and searches back in history through the primary
1972
("left-hand") parents until it finds X. When logging just the
1973
top level (using -n1), an error is reported if X is not found
1974
along the way. If multi-level logging is used (-n0), X may be
1975
a nested merge revision and the log will be truncated accordingly.
1979
If a parameter is given and it's not a branch, the log will be filtered
1980
to show only those revisions that changed the nominated file or
1983
Filenames are interpreted within their historical context. To log a
1984
deleted file, specify a revision range so that the file existed at
1985
the end or start of the range.
1987
Historical context is also important when interpreting pathnames of
1988
renamed files/directories. Consider the following example:
1990
* revision 1: add tutorial.txt
1991
* revision 2: modify tutorial.txt
1992
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
1996
* ``bzr log guide.txt`` will log the file added in revision 1
1998
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2000
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2001
the original file in revision 2.
2003
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2004
was no file called guide.txt in revision 2.
2006
Renames are always followed by log. By design, there is no need to
2007
explicitly ask for this (and no way to stop logging a file back
2008
until it was last renamed).
2010
Note: If the path is a directory, only revisions that directly changed
2011
that directory object are currently shown. This is considered a bug.
2012
(Support for filtering against multiple files and for files within a
2013
directory is under development.)
2017
The --message option can be used for finding revisions that match a
2018
regular expression in a commit message.
2022
GUI tools and IDEs are often better at exploring history than command
2023
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2024
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2025
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2027
Web interfaces are often better at exploring history than command line
2028
tools, particularly for branches on servers. You may prefer Loggerhead
2029
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2031
You may find it useful to add the aliases below to ``bazaar.conf``::
2035
top = log -r-10.. --short --forward
2036
show = log -v -p -n1 --long
2038
``bzr tip`` will then show the latest revision while ``bzr top``
2039
will show the last 10 mainline revisions. To see the details of a
2040
particular revision X, ``bzr show -rX``.
2042
As many GUI tools and Web interfaces do, you may prefer viewing
2043
history collapsed initially. If you are interested in looking deeper
2044
into a particular merge X, use ``bzr log -n0 -rX``. If you like
2045
working this way, you may wish to either:
2047
* change your default log format to short (or line)
2048
* add this alias: log = log -n1
2050
``bzr log -v`` on a branch with lots of history is currently
2051
very slow. A fix for this issue is currently under development.
2052
With or without that fix, it is recommended that a revision range
2053
be given when using the -v option.
2055
bzr has a generic full-text matching plugin, bzr-search, that can be
2056
used to find revisions matching user names, commit messages, etc.
2057
Among other features, this plugin can find all revisions containing
2058
a list of words but not others.
2060
When exploring non-mainline history on large projects with deep
2061
history, the performance of log can be greatly improved by installing
2062
the revnocache plugin. This plugin buffers historical information
2063
trading disk space for faster speed.
1640
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1642
2065
takes_args = ['location?']
2066
_see_also = ['log-formats', 'revisionspec']
1643
2067
takes_options = [
1644
2068
Option('forward',
1645
2069
help='Show from oldest to newest.'),
1648
help='Display timezone as local, original, or utc.'),
1649
2071
custom_help('verbose',
1650
2072
help='Show files changed in each revision.'),
2076
type=bzrlib.option._parse_revision_str,
2078
help='Show just the specified revision.'
2079
' See also "help revisionspec".'),
2083
help='Number of levels to display - 0 for all, 1 for flat.',
2085
type=_parse_levels),
1654
2086
Option('message',
1655
2087
short_name='m',
1656
2088
help='Show revisions whose message matches this '
2126
2583
branch.lock_read()
2128
2585
return self._run(tree, branch, relpath, filename, revision,
2586
name_from_revision, filters)
2131
2588
branch.unlock()
2133
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2590
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2134
2592
if tree is None:
2135
2593
tree = b.basis_tree()
2136
if revision is None:
2137
revision_id = b.last_revision()
2139
revision_id = revision[0].in_history(b).rev_id
2594
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2141
cur_file_id = tree.path2id(relpath)
2142
rev_tree = b.repository.revision_tree(revision_id)
2143
2596
old_file_id = rev_tree.path2id(relpath)
2145
2598
if name_from_revision:
2599
# Try in revision if requested
2146
2600
if old_file_id is None:
2147
raise errors.BzrCommandError("%r is not present in revision %s"
2148
% (filename, revision_id))
2601
raise errors.BzrCommandError(
2602
"%r is not present in revision %s" % (
2603
filename, rev_tree.get_revision_id()))
2150
rev_tree.print_file(old_file_id)
2151
elif cur_file_id is not None:
2152
rev_tree.print_file(cur_file_id)
2153
elif old_file_id is not None:
2154
rev_tree.print_file(old_file_id)
2156
raise errors.BzrCommandError("%r is not present in revision %s" %
2157
(filename, revision_id))
2605
content = rev_tree.get_file_text(old_file_id)
2607
cur_file_id = tree.path2id(relpath)
2609
if cur_file_id is not None:
2610
# Then try with the actual file id
2612
content = rev_tree.get_file_text(cur_file_id)
2614
except errors.NoSuchId:
2615
# The actual file id didn't exist at that time
2617
if not found and old_file_id is not None:
2618
# Finally try with the old file id
2619
content = rev_tree.get_file_text(old_file_id)
2622
# Can't be found anywhere
2623
raise errors.BzrCommandError(
2624
"%r is not present in revision %s" % (
2625
filename, rev_tree.get_revision_id()))
2627
from bzrlib.filters import (
2628
ContentFilterContext,
2629
filtered_output_bytes,
2631
filters = rev_tree._content_filter_stack(relpath)
2632
chunks = content.splitlines(True)
2633
content = filtered_output_bytes(chunks, filters,
2634
ContentFilterContext(relpath, rev_tree))
2635
self.outf.writelines(content)
2637
self.outf.write(content)
2160
2640
class cmd_local_time_offset(Command):
2161
2641
"""Show the offset in seconds from GMT to local time."""
2163
2643
@display_command
2165
2645
print osutils.local_time_offset()
2366
2860
in the checked revisions. Texts can be repeated when their file
2367
2861
entries are modified, but the file contents are not. It does not
2368
2862
indicate a problem.
2864
If no restrictions are specified, all Bazaar data that is found at the given
2865
location will be checked.
2869
Check the tree and branch at 'foo'::
2871
bzr check --tree --branch foo
2873
Check only the repository at 'bar'::
2875
bzr check --repo bar
2877
Check everything at 'baz'::
2371
2882
_see_also = ['reconcile']
2372
takes_args = ['branch?']
2373
takes_options = ['verbose']
2883
takes_args = ['path?']
2884
takes_options = ['verbose',
2885
Option('branch', help="Check the branch related to the"
2886
" current directory."),
2887
Option('repo', help="Check the repository related to the"
2888
" current directory."),
2889
Option('tree', help="Check the working tree related to"
2890
" the current directory.")]
2375
def run(self, branch=None, verbose=False):
2376
from bzrlib.check import check
2378
branch_obj = Branch.open_containing('.')[0]
2380
branch_obj = Branch.open(branch)
2381
check(branch_obj, verbose)
2382
# bit hacky, check the tree parent is accurate
2385
tree = WorkingTree.open_containing('.')[0]
2387
tree = WorkingTree.open(branch)
2388
except (errors.NoWorkingTree, errors.NotLocalUrl):
2391
# This is a primitive 'check' for tree state. Currently this is not
2392
# integrated into the main check logic as yet.
2395
tree_basis = tree.basis_tree()
2396
tree_basis.lock_read()
2398
repo_basis = tree.branch.repository.revision_tree(
2399
tree.last_revision())
2400
if len(list(repo_basis._iter_changes(tree_basis))):
2401
raise errors.BzrCheckError(
2402
"Mismatched basis inventory content.")
2892
def run(self, path=None, verbose=False, branch=False, repo=False,
2894
from bzrlib.check import check_dwim
2897
if not branch and not repo and not tree:
2898
branch = repo = tree = True
2899
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2410
2902
class cmd_upgrade(Command):
2504
2999
print branch.nick
3002
class cmd_alias(Command):
3003
"""Set/unset and display aliases.
3006
Show the current aliases::
3010
Show the alias specified for 'll'::
3014
Set an alias for 'll'::
3016
bzr alias ll="log --line -r-10..-1"
3018
To remove an alias for 'll'::
3020
bzr alias --remove ll
3023
takes_args = ['name?']
3025
Option('remove', help='Remove the alias.'),
3028
def run(self, name=None, remove=False):
3030
self.remove_alias(name)
3032
self.print_aliases()
3034
equal_pos = name.find('=')
3036
self.print_alias(name)
3038
self.set_alias(name[:equal_pos], name[equal_pos+1:])
3040
def remove_alias(self, alias_name):
3041
if alias_name is None:
3042
raise errors.BzrCommandError(
3043
'bzr alias --remove expects an alias to remove.')
3044
# If alias is not found, print something like:
3045
# unalias: foo: not found
3046
c = config.GlobalConfig()
3047
c.unset_alias(alias_name)
3050
def print_aliases(self):
3051
"""Print out the defined aliases in a similar format to bash."""
3052
aliases = config.GlobalConfig().get_aliases()
3053
for key, value in sorted(aliases.iteritems()):
3054
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3057
def print_alias(self, alias_name):
3058
from bzrlib.commands import get_alias
3059
alias = get_alias(alias_name)
3061
self.outf.write("bzr alias: %s: not found\n" % alias_name)
3064
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3066
def set_alias(self, alias_name, alias_command):
3067
"""Save the alias in the global config."""
3068
c = config.GlobalConfig()
3069
c.set_alias(alias_name, alias_command)
2507
3072
class cmd_selftest(Command):
2508
3073
"""Run internal test suite.
2510
3075
If arguments are given, they are regular expressions that say which tests
2511
3076
should run. Tests matching any expression are run, and other tests are
2596
3161
short_name='x',
2597
3162
help='Exclude tests that match this regular'
2598
3163
' expression.'),
3165
help='Output test progress via subunit.'),
2599
3166
Option('strict', help='Fail on missing dependencies or '
2600
3167
'known failures.'),
2601
Option('coverage', type=str, argname="DIRECTORY",
2602
help='Generate line coverage report in this '
3168
Option('load-list', type=str, argname='TESTLISTFILE',
3169
help='Load a test id list from a text file.'),
3170
ListOption('debugflag', type=str, short_name='E',
3171
help='Turn on a selftest debug flag.'),
3172
ListOption('starting-with', type=str, argname='TESTID',
3173
param_name='starting_with', short_name='s',
3175
'Load only the tests starting with TESTID.'),
2605
3177
encoding_type = 'replace'
3180
Command.__init__(self)
3181
self.additional_selftest_args = {}
2607
3183
def run(self, testspecs_list=None, verbose=False, one=False,
2608
3184
transport=None, benchmark=None,
2609
3185
lsprof_timed=None, cache_dir=None,
2610
3186
first=False, list_only=False,
2611
randomize=None, exclude=None, strict=False, coverage=None):
3187
randomize=None, exclude=None, strict=False,
3188
load_list=None, debugflag=None, starting_with=None, subunit=False):
2613
3189
from bzrlib.tests import selftest
2614
3190
import bzrlib.benchmarks as benchmarks
2615
3191
from bzrlib.benchmarks import tree_creator
3193
# Make deprecation warnings visible, unless -Werror is set
3194
symbol_versioning.activate_deprecation_warnings(override=False)
2617
3196
if cache_dir is not None:
2618
3197
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2619
3198
if not list_only:
2943
3582
``revision`` and ``index`` must be supplied.)
2945
3584
Otherwise, the ``location`` parameter is used. If it is None, then the
2946
``parent`` location is used, and a note is printed.
3585
``submit`` or ``parent`` location is used, and a note is printed.
2948
3587
:param tree: The working tree to select a branch for merging into
2949
3588
:param location: The location entered by the user
2950
3589
:param revision: The revision parameter to the command
2951
3590
:param index: The index to use for the revision parameter. Negative
2952
3591
indices are permitted.
2953
:return: (selected_location, default_location). The default location
2954
will be the user-entered location, if any, or else the remembered
3592
:return: (selected_location, user_location). The default location
3593
will be the user-entered location.
2957
3595
if (revision is not None and index is not None
2958
3596
and revision[index] is not None):
2959
3597
branch = revision[index].get_branch()
2960
3598
if branch is not None:
2961
return branch, location
2962
location = self._get_remembered_parent(tree, location, 'Merging from')
2963
return location, location
3599
return branch, branch
3600
if user_location is None:
3601
location = self._get_remembered(tree, 'Merging from')
3603
location = user_location
3604
return location, user_location
2965
# TODO: move up to common parent; this isn't merge-specific anymore.
2966
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3606
def _get_remembered(self, tree, verb_string):
2967
3607
"""Use tree.branch's parent if none was supplied.
2969
3609
Report if the remembered location was used.
2971
if supplied_location is not None:
2972
return supplied_location
2973
stored_location = tree.branch.get_parent()
3611
stored_location = tree.branch.get_submit_branch()
3612
stored_location_type = "submit"
3613
if stored_location is None:
3614
stored_location = tree.branch.get_parent()
3615
stored_location_type = "parent"
2974
3616
mutter("%s", stored_location)
2975
3617
if stored_location is None:
2976
3618
raise errors.BzrCommandError("No location specified or remembered")
2977
display_url = urlutils.unescape_for_display(stored_location,
2979
self.outf.write("%s remembered location %s\n" % (verb_string,
3619
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3620
note(u"%s remembered %s location %s", verb_string,
3621
stored_location_type, display_url)
2981
3622
return stored_location
3185
3824
takes_args = ['context?']
3186
3825
aliases = ['s-c']
3189
3828
@display_command
3190
3829
def run(self, context=None):
3191
3830
import shellcomplete
3192
3831
shellcomplete.shellcomplete(context)
3195
class cmd_fetch(Command):
3196
"""Copy in history from another branch but don't merge it.
3198
This is an internal method used for pull and merge.
3201
takes_args = ['from_branch', 'to_branch']
3202
def run(self, from_branch, to_branch):
3203
from bzrlib.fetch import Fetcher
3204
from_b = Branch.open(from_branch)
3205
to_b = Branch.open(to_branch)
3206
Fetcher(to_b, from_b)
3209
3834
class cmd_missing(Command):
3210
3835
"""Show unmerged/unpulled revisions between two branches.
3212
3837
OTHER_BRANCH may be local or remote.
3839
To filter on a range of revisions, you can use the command -r begin..end
3840
-r revision requests a specific revision, -r ..end or -r begin.. are
3845
Determine the missing revisions between this and the branch at the
3846
remembered pull location::
3850
Determine the missing revisions between this and another branch::
3852
bzr missing http://server/branch
3854
Determine the missing revisions up to a specific revision on the other
3857
bzr missing -r ..-10
3859
Determine the missing revisions up to a specific revision on this
3862
bzr missing --my-revision ..-10
3215
3865
_see_also = ['merge', 'pull']
3216
3866
takes_args = ['other_branch?']
3217
3867
takes_options = [
3218
Option('reverse', 'Reverse the order of revisions.'),
3220
'Display changes in the local branch only.'),
3221
Option('this' , 'Same as --mine-only.'),
3222
Option('theirs-only',
3223
'Display changes in the remote branch only.'),
3224
Option('other', 'Same as --theirs-only.'),
3868
Option('reverse', 'Reverse the order of revisions.'),
3870
'Display changes in the local branch only.'),
3871
Option('this' , 'Same as --mine-only.'),
3872
Option('theirs-only',
3873
'Display changes in the remote branch only.'),
3874
Option('other', 'Same as --theirs-only.'),
3878
custom_help('revision',
3879
help='Filter on other branch revisions (inclusive). '
3880
'See "help revisionspec" for details.'),
3881
Option('my-revision',
3882
type=_parse_revision_str,
3883
help='Filter on local branch revisions (inclusive). '
3884
'See "help revisionspec" for details.'),
3885
Option('include-merges', 'Show merged revisions.'),
3229
3887
encoding_type = 'replace'
3231
3889
@display_command
3232
3890
def run(self, other_branch=None, reverse=False, mine_only=False,
3233
theirs_only=False, log_format=None, long=False, short=False, line=False,
3234
show_ids=False, verbose=False, this=False, other=False):
3892
log_format=None, long=False, short=False, line=False,
3893
show_ids=False, verbose=False, this=False, other=False,
3894
include_merges=False, revision=None, my_revision=None):
3235
3895
from bzrlib.missing import find_unmerged, iter_log_revisions
3904
# TODO: We should probably check that we don't have mine-only and
3905
# theirs-only set, but it gets complicated because we also have
3906
# this and other which could be used.
3242
3913
local_branch = Branch.open_containing(u".")[0]
3243
3914
parent = local_branch.get_parent()
3248
3919
" or specified.")
3249
3920
display_url = urlutils.unescape_for_display(parent,
3250
3921
self.outf.encoding)
3251
self.outf.write("Using last location: " + display_url + "\n")
3922
message("Using saved parent location: "
3923
+ display_url + "\n")
3253
3925
remote_branch = Branch.open(other_branch)
3254
3926
if remote_branch.base == local_branch.base:
3255
3927
remote_branch = local_branch
3929
local_revid_range = _revision_range_to_revid_range(
3930
_get_revision_range(my_revision, local_branch,
3933
remote_revid_range = _revision_range_to_revid_range(
3934
_get_revision_range(revision,
3935
remote_branch, self.name()))
3256
3937
local_branch.lock_read()
3258
3939
remote_branch.lock_read()
3260
local_extra, remote_extra = find_unmerged(local_branch,
3941
local_extra, remote_extra = find_unmerged(
3942
local_branch, remote_branch, restrict,
3943
backward=not reverse,
3944
include_merges=include_merges,
3945
local_revid_range=local_revid_range,
3946
remote_revid_range=remote_revid_range)
3262
3948
if log_format is None:
3263
3949
registry = log.log_formatter_registry
3264
3950
log_format = registry.get_default(local_branch)
3265
3951
lf = log_format(to_file=self.outf,
3266
3952
show_ids=show_ids,
3267
3953
show_timezone='original')
3268
if reverse is False:
3269
local_extra.reverse()
3270
remote_extra.reverse()
3271
3956
if local_extra and not theirs_only:
3272
self.outf.write("You have %d extra revision(s):\n" %
3957
message("You have %d extra revision(s):\n" %
3274
3959
for revision in iter_log_revisions(local_extra,
3275
3960
local_branch.repository,
3277
3962
lf.log_revision(revision)
3278
3963
printed_local = True
3280
3966
printed_local = False
3281
3968
if remote_extra and not mine_only:
3282
3969
if printed_local is True:
3283
self.outf.write("\n\n\n")
3284
self.outf.write("You are missing %d revision(s):\n" %
3971
message("You are missing %d revision(s):\n" %
3286
3973
for revision in iter_log_revisions(remote_extra,
3287
3974
remote_branch.repository,
3289
3976
lf.log_revision(revision)
3290
if not remote_extra and not local_extra:
3292
self.outf.write("Branches are up to date.\n")
3294
3977
status_code = 1
3979
if mine_only and not local_extra:
3980
# We checked local, and found nothing extra
3981
message('This branch is up to date.\n')
3982
elif theirs_only and not remote_extra:
3983
# We checked remote, and found nothing extra
3984
message('Other branch is up to date.\n')
3985
elif not (mine_only or theirs_only or local_extra or
3987
# We checked both branches, and neither one had extra
3989
message("Branches are up to date.\n")
3296
3991
remote_branch.unlock()
3712
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4452
def run_smart_server(self, smart_server):
4453
"""Run 'smart_server' forever, with no UI output at all."""
4454
# For the duration of this server, no UI output is permitted. note
4455
# that this may cause problems with blackbox tests. This should be
4456
# changed with care though, as we dont want to use bandwidth sending
4457
# progress over stderr to smart server clients!
3713
4458
from bzrlib import lockdir
4459
old_factory = ui.ui_factory
4460
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4462
ui.ui_factory = ui.SilentUIFactory()
4463
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4464
smart_server.serve()
4466
ui.ui_factory = old_factory
4467
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4469
def get_host_and_port(self, port):
4470
"""Return the host and port to run the smart server on.
4472
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4473
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4475
If 'port' has a colon in it, the string before the colon will be
4476
interpreted as the host.
4478
:param port: A string of the port to run the server on.
4479
:return: A tuple of (host, port), where 'host' is a host name or IP,
4480
and port is an integer TCP/IP port.
4482
from bzrlib.smart import medium
4483
host = medium.BZR_DEFAULT_INTERFACE
4485
port = medium.BZR_DEFAULT_PORT
4488
host, port = port.split(':')
4492
def get_smart_server(self, transport, inet, port):
4493
"""Construct a smart server.
4495
:param transport: The base transport from which branches will be
4497
:param inet: If True, serve over stdin and stdout. Used for running
4499
:param port: The port to listen on. By default, it's `
4500
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4502
:return: A smart server.
3714
4504
from bzrlib.smart import medium, server
4506
smart_server = medium.SmartServerPipeStreamMedium(
4507
sys.stdin, sys.stdout, transport)
4509
host, port = self.get_host_and_port(port)
4510
smart_server = server.SmartTCPServer(
4511
transport, host=host, port=port)
4512
note('listening on port: %s' % smart_server.port)
4515
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3715
4516
from bzrlib.transport import get_transport
3716
4517
from bzrlib.transport.chroot import ChrootServer
3717
4518
if directory is None:
4311
5127
If none of these is available, --bind-to must be specified.
5130
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4314
5131
takes_args = ['location?']
4315
takes_options = [RegistryOption.from_kwargs('target_type',
4316
title='Target type',
4317
help='The type to reconfigure the directory to.',
4318
value_switches=True, enum_switch=False,
4319
branch='Reconfigure to a branch.',
4320
tree='Reconfigure to a tree.',
4321
checkout='Reconfigure to a checkout.',
4322
lightweight_checkout='Reconfigure to a lightweight'
4324
Option('bind-to', help='Branch to bind checkout to.',
4327
help='Perform reconfiguration even if local changes'
5133
RegistryOption.from_kwargs(
5135
title='Target type',
5136
help='The type to reconfigure the directory to.',
5137
value_switches=True, enum_switch=False,
5138
branch='Reconfigure to be an unbound branch with no working tree.',
5139
tree='Reconfigure to be an unbound branch with a working tree.',
5140
checkout='Reconfigure to be a bound branch with a working tree.',
5141
lightweight_checkout='Reconfigure to be a lightweight'
5142
' checkout (with no local history).',
5143
standalone='Reconfigure to be a standalone branch '
5144
'(i.e. stop using shared repository).',
5145
use_shared='Reconfigure to use a shared repository.',
5146
with_trees='Reconfigure repository to create '
5147
'working trees on branches by default.',
5148
with_no_trees='Reconfigure repository to not create '
5149
'working trees on branches by default.'
5151
Option('bind-to', help='Branch to bind checkout to.', type=str),
5153
help='Perform reconfiguration even if local changes'
4331
5157
def run(self, location=None, target_type=None, bind_to=None, force=False):
4332
5158
directory = bzrdir.BzrDir.open(location)
4367
5212
def run(self, to_location, force=False):
4368
5213
from bzrlib import switch
4369
to_branch = Branch.open(to_location)
4370
5214
tree_location = '.'
4371
5215
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5216
branch = control_dir.open_branch()
5218
to_branch = Branch.open(to_location)
5219
except errors.NotBranchError:
5220
this_branch = control_dir.open_branch()
5221
# This may be a heavy checkout, where we want the master branch
5222
this_url = this_branch.get_bound_location()
5223
# If not, use a local sibling
5224
if this_url is None:
5225
this_url = this_branch.base
5226
to_branch = Branch.open(
5227
urlutils.join(this_url, '..', to_location))
4372
5228
switch.switch(control_dir, to_branch, force)
5229
if branch.get_config().has_explicit_nickname():
5230
branch = control_dir.open_branch() #get the new branch!
5231
branch.nick = to_branch.nick
4373
5232
note('Switched to branch: %s',
4374
5233
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5236
class cmd_view(Command):
5237
"""Manage filtered views.
5239
Views provide a mask over the tree so that users can focus on
5240
a subset of a tree when doing their work. After creating a view,
5241
commands that support a list of files - status, diff, commit, etc -
5242
effectively have that list of files implicitly given each time.
5243
An explicit list of files can still be given but those files
5244
must be within the current view.
5246
In most cases, a view has a short life-span: it is created to make
5247
a selected change and is deleted once that change is committed.
5248
At other times, you may wish to create one or more named views
5249
and switch between them.
5251
To disable the current view without deleting it, you can switch to
5252
the pseudo view called ``off``. This can be useful when you need
5253
to see the whole tree for an operation or two (e.g. merge) but
5254
want to switch back to your view after that.
5257
To define the current view::
5259
bzr view file1 dir1 ...
5261
To list the current view::
5265
To delete the current view::
5269
To disable the current view without deleting it::
5271
bzr view --switch off
5273
To define a named view and switch to it::
5275
bzr view --name view-name file1 dir1 ...
5277
To list a named view::
5279
bzr view --name view-name
5281
To delete a named view::
5283
bzr view --name view-name --delete
5285
To switch to a named view::
5287
bzr view --switch view-name
5289
To list all views defined::
5293
To delete all views::
5295
bzr view --delete --all
5299
takes_args = ['file*']
5302
help='Apply list or delete action to all views.',
5305
help='Delete the view.',
5308
help='Name of the view to define, list or delete.',
5312
help='Name of the view to switch to.',
5317
def run(self, file_list,
5323
tree, file_list = tree_files(file_list, apply_view=False)
5324
current_view, view_dict = tree.views.get_view_info()
5329
raise errors.BzrCommandError(
5330
"Both --delete and a file list specified")
5332
raise errors.BzrCommandError(
5333
"Both --delete and --switch specified")
5335
tree.views.set_view_info(None, {})
5336
self.outf.write("Deleted all views.\n")
5338
raise errors.BzrCommandError("No current view to delete")
5340
tree.views.delete_view(name)
5341
self.outf.write("Deleted '%s' view.\n" % name)
5344
raise errors.BzrCommandError(
5345
"Both --switch and a file list specified")
5347
raise errors.BzrCommandError(
5348
"Both --switch and --all specified")
5349
elif switch == 'off':
5350
if current_view is None:
5351
raise errors.BzrCommandError("No current view to disable")
5352
tree.views.set_view_info(None, view_dict)
5353
self.outf.write("Disabled '%s' view.\n" % (current_view))
5355
tree.views.set_view_info(switch, view_dict)
5356
view_str = views.view_display_str(tree.views.lookup_view())
5357
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5360
self.outf.write('Views defined:\n')
5361
for view in sorted(view_dict):
5362
if view == current_view:
5366
view_str = views.view_display_str(view_dict[view])
5367
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5369
self.outf.write('No views defined.\n')
5372
# No name given and no current view set
5375
raise errors.BzrCommandError(
5376
"Cannot change the 'off' pseudo view")
5377
tree.views.set_view(name, sorted(file_list))
5378
view_str = views.view_display_str(tree.views.lookup_view())
5379
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5383
# No name given and no current view set
5384
self.outf.write('No current view.\n')
5386
view_str = views.view_display_str(tree.views.lookup_view(name))
5387
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5390
class cmd_hooks(Command):
5396
for hook_key in sorted(hooks.known_hooks.keys()):
5397
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5398
self.outf.write("%s:\n" % type(some_hooks).__name__)
5399
for hook_name, hook_point in sorted(some_hooks.items()):
5400
self.outf.write(" %s:\n" % (hook_name,))
5401
found_hooks = list(hook_point)
5403
for hook in found_hooks:
5404
self.outf.write(" %s\n" %
5405
(some_hooks.get_hook_name(hook),))
5407
self.outf.write(" <no hooks installed>\n")
5410
class cmd_shelve(Command):
5411
"""Temporarily set aside some changes from the current tree.
5413
Shelve allows you to temporarily put changes you've made "on the shelf",
5414
ie. out of the way, until a later time when you can bring them back from
5415
the shelf with the 'unshelve' command. The changes are stored alongside
5416
your working tree, and so they aren't propagated along with your branch nor
5417
will they survive its deletion.
5419
If shelve --list is specified, previously-shelved changes are listed.
5421
Shelve is intended to help separate several sets of changes that have
5422
been inappropriately mingled. If you just want to get rid of all changes
5423
and you don't need to restore them later, use revert. If you want to
5424
shelve all text changes at once, use shelve --all.
5426
If filenames are specified, only the changes to those files will be
5427
shelved. Other files will be left untouched.
5429
If a revision is specified, changes since that revision will be shelved.
5431
You can put multiple items on the shelf, and by default, 'unshelve' will
5432
restore the most recently shelved changes.
5435
takes_args = ['file*']
5439
Option('all', help='Shelve all changes.'),
5441
RegistryOption('writer', 'Method to use for writing diffs.',
5442
bzrlib.option.diff_writer_registry,
5443
value_switches=True, enum_switch=False),
5445
Option('list', help='List shelved changes.'),
5447
help='Destroy removed changes instead of shelving them.'),
5449
_see_also = ['unshelve']
5451
def run(self, revision=None, all=False, file_list=None, message=None,
5452
writer=None, list=False, destroy=False):
5454
return self.run_for_list()
5455
from bzrlib.shelf_ui import Shelver
5457
writer = bzrlib.option.diff_writer_registry.get()
5459
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5460
message, destroy=destroy).run()
5461
except errors.UserAbort:
5464
def run_for_list(self):
5465
tree = WorkingTree.open_containing('.')[0]
5468
manager = tree.get_shelf_manager()
5469
shelves = manager.active_shelves()
5470
if len(shelves) == 0:
5471
note('No shelved changes.')
5473
for shelf_id in reversed(shelves):
5474
message = manager.get_metadata(shelf_id).get('message')
5476
message = '<no message>'
5477
self.outf.write('%3d: %s\n' % (shelf_id, message))
5483
class cmd_unshelve(Command):
5484
"""Restore shelved changes.
5486
By default, the most recently shelved changes are restored. However if you
5487
specify a shelf by id those changes will be restored instead. This works
5488
best when the changes don't depend on each other.
5491
takes_args = ['shelf_id?']
5493
RegistryOption.from_kwargs(
5494
'action', help="The action to perform.",
5495
enum_switch=False, value_switches=True,
5496
apply="Apply changes and remove from the shelf.",
5497
dry_run="Show changes, but do not apply or remove them.",
5498
delete_only="Delete changes without applying them."
5501
_see_also = ['shelve']
5503
def run(self, shelf_id=None, action='apply'):
5504
from bzrlib.shelf_ui import Unshelver
5505
Unshelver.from_args(shelf_id, action).run()
5508
class cmd_clean_tree(Command):
5509
"""Remove unwanted files from working tree.
5511
By default, only unknown files, not ignored files, are deleted. Versioned
5512
files are never deleted.
5514
Another class is 'detritus', which includes files emitted by bzr during
5515
normal operations and selftests. (The value of these files decreases with
5518
If no options are specified, unknown files are deleted. Otherwise, option
5519
flags are respected, and may be combined.
5521
To check what clean-tree will do, use --dry-run.
5523
takes_options = [Option('ignored', help='Delete all ignored files.'),
5524
Option('detritus', help='Delete conflict files, merge'
5525
' backups, and failed selftest dirs.'),
5527
help='Delete files unknown to bzr (default).'),
5528
Option('dry-run', help='Show files to delete instead of'
5530
Option('force', help='Do not prompt before deleting.')]
5531
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5533
from bzrlib.clean_tree import clean_tree
5534
if not (unknown or ignored or detritus):
5538
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5539
dry_run=dry_run, no_prompt=force)
4377
5542
def _create_prefix(cur_transport):
4378
5543
needed = [cur_transport]
4379
5544
# Recurse upwards until we can create a directory successfully