29
29
from bzrlib import (
40
39
merge as _mod_merge,
45
43
revision as _mod_revision,
53
50
from bzrlib.branch import Branch
54
51
from bzrlib.conflicts import ConflictList
55
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
52
from bzrlib.revisionspec import RevisionSpec
56
53
from bzrlib.smtp_connection import SMTPConnection
57
54
from bzrlib.workingtree import WorkingTree
60
57
from bzrlib.commands import Command, display_command
61
from bzrlib.option import (
68
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
71
def tree_files(file_list, default_branch=u'.', canonicalize=True,
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'.'):
74
return internal_tree_files(file_list, default_branch, canonicalize,
64
return internal_tree_files(file_list, default_branch)
76
65
except errors.FileInWrongBranch, e:
77
66
raise errors.BzrCommandError("%s is not in the same branch as %s" %
78
67
(e.path, file_list[0]))
81
def tree_files_for_add(file_list):
83
Return a tree and list of absolute paths from a file list.
85
Similar to tree_files, but add handles files a bit differently, so it a
86
custom implementation. In particular, MutableTreeTree.smart_add expects
87
absolute paths, which it immediately converts to relative paths.
89
# FIXME Would be nice to just return the relative paths like
90
# internal_tree_files does, but there are a large number of unit tests
91
# that assume the current interface to mutabletree.smart_add
93
tree, relpath = WorkingTree.open_containing(file_list[0])
94
if tree.supports_views():
95
view_files = tree.views.lookup_view()
97
for filename in file_list:
98
if not osutils.is_inside_any(view_files, filename):
99
raise errors.FileOutsideView(filename, view_files)
100
file_list = file_list[:]
101
file_list[0] = tree.abspath(relpath)
103
tree = WorkingTree.open_containing(u'.')[0]
104
if tree.supports_views():
105
view_files = tree.views.lookup_view()
107
file_list = view_files
108
view_str = views.view_display_str(view_files)
109
note("Ignoring files outside view. View is %s" % view_str)
110
return tree, file_list
113
def _get_one_revision(command_name, revisions):
114
if revisions is None:
116
if len(revisions) != 1:
117
raise errors.BzrCommandError(
118
'bzr %s --revision takes exactly one revision identifier' % (
123
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
126
if revisions is None:
128
rev_tree = tree.basis_tree()
130
rev_tree = branch.basis_tree()
132
revision = _get_one_revision(command_name, revisions)
133
rev_tree = revision.as_tree(branch)
137
70
# XXX: Bad function name; should possibly also be a class method of
138
71
# WorkingTree rather than a function.
139
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
72
def internal_tree_files(file_list, default_branch=u'.'):
141
73
"""Convert command-line paths to a WorkingTree and relative paths.
143
75
This is typically used for command-line processors that take one or
146
78
The filenames given are not required to exist.
148
:param file_list: Filenames to convert.
80
:param file_list: Filenames to convert.
150
82
:param default_branch: Fallback tree path to use if file_list is empty or
153
:param apply_view: if True and a view is set, apply it or check that
154
specified files are within it
156
85
:return: workingtree, [relative_paths]
158
87
if file_list is None or len(file_list) == 0:
159
tree = WorkingTree.open_containing(default_branch)[0]
160
if tree.supports_views() and apply_view:
161
view_files = tree.views.lookup_view()
163
file_list = view_files
164
view_str = views.view_display_str(view_files)
165
note("Ignoring files outside view. View is %s" % view_str)
166
return tree, file_list
88
return WorkingTree.open_containing(default_branch)[0], file_list
167
89
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
168
return tree, safe_relpath_files(tree, file_list, canonicalize,
169
apply_view=apply_view)
172
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
173
"""Convert file_list into a list of relpaths in tree.
175
:param tree: A tree to operate on.
176
:param file_list: A list of user provided paths or None.
177
:param apply_view: if True and a view is set, apply it or check that
178
specified files are within it
179
:return: A list of relative paths.
180
:raises errors.PathNotChild: When a provided path is in a different tree
183
if file_list is None:
185
if tree.supports_views() and apply_view:
186
view_files = tree.views.lookup_view()
190
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
191
# doesn't - fix that up here before we enter the loop.
193
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
196
91
for filename in file_list:
198
relpath = fixer(osutils.dereference_path(filename))
199
if view_files and not osutils.is_inside_any(view_files, relpath):
200
raise errors.FileOutsideView(filename, view_files)
201
new_list.append(relpath)
93
new_list.append(tree.relpath(osutils.dereference_path(filename)))
202
94
except errors.PathNotChild:
203
95
raise errors.FileInWrongBranch(tree.branch, filename)
207
def _get_view_info_for_change_reporter(tree):
208
"""Get the view information from a tree for change reporting."""
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()
211
current_view = tree.views.get_view_info()[0]
212
if current_view is not None:
213
view_info = (current_view, tree.views.lookup_view())
214
except errors.ViewsNotSupported:
107
return bzrdir.format_registry.make_bzrdir(typestring)
109
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
raise errors.BzrCommandError(msg)
219
113
# TODO: Make sure no commands unconditionally use the working directory as a
252
146
To see ignored files use 'bzr ignored'. For details on the
253
147
changes to file texts, use 'bzr diff'.
255
149
Note that --short or -S gives status flags for each item, similar
256
150
to Subversion's status command. To get output similar to svn -q,
259
153
If no arguments are specified, the status of the entire working
260
154
directory is shown. Otherwise, only the status of the specified
261
155
files or directories is reported. If a directory is given, status
262
156
is reported for everything inside that directory.
264
Before merges are committed, the pending merge tip revisions are
265
shown. To see all pending merge revisions, use the -v option.
266
To skip the display of pending merge information altogether, use
267
the no-pending option or specify a file/directory.
269
158
If a revision argument is given, the status is calculated against
270
159
that revision, or between two revisions if two are provided.
273
162
# TODO: --no-recurse, --recurse options
275
164
takes_args = ['file*']
276
takes_options = ['show-ids', 'revision', 'change', 'verbose',
165
takes_options = ['show-ids', 'revision', 'change',
277
166
Option('short', help='Use short status indicators.',
279
168
Option('versioned', help='Only show versioned files.',
281
Option('no-pending', help='Don\'t show pending merges.',
284
171
aliases = ['st', 'stat']
286
173
encoding_type = 'replace'
287
174
_see_also = ['diff', 'revert', 'status-flags']
290
177
def run(self, show_ids=False, file_list=None, revision=None, short=False,
291
versioned=False, no_pending=False, verbose=False):
292
179
from bzrlib.status import show_tree_status
294
181
if revision and len(revision) > 2:
295
182
raise errors.BzrCommandError('bzr status --revision takes exactly'
296
183
' one or two revision specifiers')
298
tree, relfile_list = tree_files(file_list)
299
# Avoid asking for specific files when that is not needed.
300
if relfile_list == ['']:
302
# Don't disable pending merges for full trees other than '.'.
303
if file_list == ['.']:
305
# A specific path within a tree was given.
306
elif relfile_list is not None:
185
tree, file_list = tree_files(file_list)
308
187
show_tree_status(tree, show_ids=show_ids,
309
specific_files=relfile_list, revision=revision,
310
to_file=self.outf, short=short, versioned=versioned,
311
show_pending=(not no_pending), verbose=verbose)
188
specific_files=file_list, revision=revision,
189
to_file=self.outf, short=short, versioned=versioned)
314
192
class cmd_cat_revision(Command):
315
193
"""Write out metadata for a revision.
317
195
The revision to print can either be specified by a specific
318
196
revision identifier, or you can use --revision.
337
215
# TODO: jam 20060112 should cat-revision always output utf-8?
338
216
if revision_id is not None:
339
217
revision_id = osutils.safe_revision_id(revision_id, warn=False)
341
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
342
except errors.NoSuchRevision:
343
msg = "The repository %s contains no revision %s." % (b.repository.base,
345
raise errors.BzrCommandError(msg)
218
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
346
219
elif revision is not None:
347
220
for rev in revision:
349
222
raise errors.BzrCommandError('You cannot specify a NULL'
351
rev_id = rev.as_revision_id(b)
224
revno, rev_id = rev.in_history(b)
352
225
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
355
class cmd_dump_btree(Command):
356
"""Dump the contents of a btree index file to stdout.
358
PATH is a btree index file, it can be any URL. This includes things like
359
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
361
By default, the tuples stored in the index file will be displayed. With
362
--raw, we will uncompress the pages, but otherwise display the raw bytes
366
# TODO: Do we want to dump the internal nodes as well?
367
# TODO: It would be nice to be able to dump the un-parsed information,
368
# rather than only going through iter_all_entries. However, this is
369
# good enough for a start
371
encoding_type = 'exact'
372
takes_args = ['path']
373
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
374
' rather than the parsed tuples.'),
377
def run(self, path, raw=False):
378
dirname, basename = osutils.split(path)
379
t = transport.get_transport(dirname)
381
self._dump_raw_bytes(t, basename)
383
self._dump_entries(t, basename)
385
def _get_index_and_bytes(self, trans, basename):
386
"""Create a BTreeGraphIndex and raw bytes."""
387
bt = btree_index.BTreeGraphIndex(trans, basename, None)
388
bytes = trans.get_bytes(basename)
389
bt._file = cStringIO.StringIO(bytes)
390
bt._size = len(bytes)
393
def _dump_raw_bytes(self, trans, basename):
396
# We need to parse at least the root node.
397
# This is because the first page of every row starts with an
398
# uncompressed header.
399
bt, bytes = self._get_index_and_bytes(trans, basename)
400
for page_idx, page_start in enumerate(xrange(0, len(bytes),
401
btree_index._PAGE_SIZE)):
402
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
403
page_bytes = bytes[page_start:page_end]
405
self.outf.write('Root node:\n')
406
header_end, data = bt._parse_header_from_bytes(page_bytes)
407
self.outf.write(page_bytes[:header_end])
409
self.outf.write('\nPage %d\n' % (page_idx,))
410
decomp_bytes = zlib.decompress(page_bytes)
411
self.outf.write(decomp_bytes)
412
self.outf.write('\n')
414
def _dump_entries(self, trans, basename):
416
st = trans.stat(basename)
417
except errors.TransportNotPossible:
418
# We can't stat, so we'll fake it because we have to do the 'get()'
420
bt, _ = self._get_index_and_bytes(trans, basename)
422
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
423
for node in bt.iter_all_entries():
424
# Node is made up of:
425
# (index, key, value, [references])
426
self.outf.write('%s\n' % (node[1:],))
429
228
class cmd_remove_tree(Command):
430
229
"""Remove the working tree from a given branch/checkout.
734
523
takes_args = ['names*']
735
524
takes_options = [Option("after", help="Move only the bzr identifier"
736
525
" of the file, because the file has already been moved."),
737
Option('auto', help='Automatically guess renames.'),
738
Option('dry-run', help='Avoid making changes when guessing renames.'),
740
527
aliases = ['move', 'rename']
741
528
encoding_type = 'replace'
743
def run(self, names_list, after=False, auto=False, dry_run=False):
745
return self.run_auto(names_list, after, dry_run)
747
raise errors.BzrCommandError('--dry-run requires --auto.')
530
def run(self, names_list, after=False):
748
531
if names_list is None:
750
534
if len(names_list) < 2:
751
535
raise errors.BzrCommandError("missing file argument")
752
tree, rel_names = tree_files(names_list, canonicalize=False)
755
self._run(tree, names_list, rel_names, after)
759
def run_auto(self, names_list, after, dry_run):
760
if names_list is not None and len(names_list) > 1:
761
raise errors.BzrCommandError('Only one path may be specified to'
764
raise errors.BzrCommandError('--after cannot be specified with'
766
work_tree, file_list = tree_files(names_list, default_branch='.')
767
work_tree.lock_write()
769
rename_map.RenameMap.guess_renames(work_tree, dry_run)
773
def _run(self, tree, names_list, rel_names, after):
774
into_existing = osutils.isdir(names_list[-1])
775
if into_existing and len(names_list) == 2:
777
# a. case-insensitive filesystem and change case of dir
778
# b. move directory after the fact (if the source used to be
779
# a directory, but now doesn't exist in the working tree
780
# and the target is an existing directory, just rename it)
781
if (not tree.case_sensitive
782
and rel_names[0].lower() == rel_names[1].lower()):
783
into_existing = False
786
# 'fix' the case of a potential 'from'
787
from_id = tree.path2id(
788
tree.get_canonical_inventory_path(rel_names[0]))
789
if (not osutils.lexists(names_list[0]) and
790
from_id and inv.get_file_kind(from_id) == "directory"):
791
into_existing = False
536
tree, rel_names = tree_files(names_list)
538
dest = names_list[-1]
539
isdir = os.path.isdir(dest)
540
if (isdir and not tree.case_sensitive and len(rel_names) == 2
541
and rel_names[0].lower() == rel_names[1].lower()):
794
544
# move into existing directory
795
# All entries reference existing inventory items, so fix them up
796
# for cicp file-systems.
797
rel_names = tree.get_canonical_inventory_paths(rel_names)
798
545
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
799
546
self.outf.write("%s => %s\n" % pair)
1013
702
' directory exists, but does not already'
1014
703
' have a control directory. This flag will'
1015
704
' allow push to proceed.'),
1017
help='Create a stacked branch that references the public location '
1018
'of the parent branch.'),
1019
Option('stacked-on',
1020
help='Create a stacked branch that refers to another branch '
1021
'for the commit history. Only the work not present in the '
1022
'referenced branch is included in the branch created.',
1025
706
takes_args = ['location?']
1026
707
encoding_type = 'replace'
1028
709
def run(self, location=None, remember=False, overwrite=False,
1029
create_prefix=False, verbose=False, revision=None,
1030
use_existing_dir=False, directory=None, stacked_on=None,
1032
from bzrlib.push import _show_push_branch
1034
# Get the source branch and revision_id
710
create_prefix=False, verbose=False, revision=None,
711
use_existing_dir=False,
713
# FIXME: Way too big! Put this into a function called from the
1035
715
if directory is None:
1037
717
br_from = Branch.open_containing(directory)[0]
1038
revision = _get_one_revision('push', revision)
1039
if revision is not None:
1040
revision_id = revision.in_history(br_from).rev_id
1044
# Get the stacked_on branch, if any
1045
if stacked_on is not None:
1046
stacked_on = urlutils.normalize_url(stacked_on)
1048
parent_url = br_from.get_parent()
1050
parent = Branch.open(parent_url)
1051
stacked_on = parent.get_public_branch()
1053
# I considered excluding non-http url's here, thus forcing
1054
# 'public' branches only, but that only works for some
1055
# users, so it's best to just depend on the user spotting an
1056
# error by the feedback given to them. RBC 20080227.
1057
stacked_on = parent_url
1059
raise errors.BzrCommandError(
1060
"Could not determine branch to refer to.")
1062
# Get the destination location
718
stored_loc = br_from.get_push_location()
1063
719
if location is None:
1064
stored_loc = br_from.get_push_location()
1065
720
if stored_loc is None:
1066
raise errors.BzrCommandError(
1067
"No push location known or specified.")
721
raise errors.BzrCommandError("No push location known or specified.")
1069
723
display_url = urlutils.unescape_for_display(stored_loc,
1070
724
self.outf.encoding)
1071
self.outf.write("Using saved push location: %s\n" % display_url)
725
self.outf.write("Using saved location: %s\n" % display_url)
1072
726
location = stored_loc
1074
_show_push_branch(br_from, revision_id, location, self.outf,
1075
verbose=verbose, overwrite=overwrite, remember=remember,
1076
stacked_on=stacked_on, create_prefix=create_prefix,
1077
use_existing_dir=use_existing_dir)
728
to_transport = transport.get_transport(location)
730
br_to = repository_to = dir_to = None
732
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
733
except errors.NotBranchError:
734
pass # Didn't find anything
736
# If we can open a branch, use its direct repository, otherwise see
737
# if there is a repository without a branch.
739
br_to = dir_to.open_branch()
740
except errors.NotBranchError:
741
# Didn't find a branch, can we find a repository?
743
repository_to = dir_to.find_repository()
744
except errors.NoRepositoryPresent:
747
# Found a branch, so we must have found a repository
748
repository_to = br_to.repository
750
if revision is not None:
751
if len(revision) == 1:
752
revision_id = revision[0].in_history(br_from).rev_id
754
raise errors.BzrCommandError(
755
'bzr push --revision takes one value.')
757
revision_id = br_from.last_revision()
763
# The destination doesn't exist; create it.
764
# XXX: Refactor the create_prefix/no_create_prefix code into a
765
# common helper function
767
def make_directory(transport):
771
def redirected(redirected_transport, e, redirection_notice):
772
return transport.get_transport(e.get_target_url())
775
to_transport = transport.do_catching_redirections(
776
make_directory, to_transport, redirected)
777
except errors.FileExists:
778
if not use_existing_dir:
779
raise errors.BzrCommandError("Target directory %s"
780
" already exists, but does not have a valid .bzr"
781
" directory. Supply --use-existing-dir to push"
782
" there anyway." % location)
783
except errors.NoSuchFile:
784
if not create_prefix:
785
raise errors.BzrCommandError("Parent directory of %s"
787
"\nYou may supply --create-prefix to create all"
788
" leading parent directories."
790
_create_prefix(to_transport)
791
except errors.TooManyRedirections:
792
raise errors.BzrCommandError("Too many redirections trying "
793
"to make %s." % location)
795
# Now the target directory exists, but doesn't have a .bzr
796
# directory. So we need to create it, along with any work to create
797
# all of the dependent branches, etc.
798
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
799
revision_id=revision_id)
800
br_to = dir_to.open_branch()
801
# TODO: Some more useful message about what was copied
802
note('Created new branch.')
803
# We successfully created the target, remember it
804
if br_from.get_push_location() is None or remember:
805
br_from.set_push_location(br_to.base)
806
elif repository_to is None:
807
# we have a bzrdir but no branch or repository
808
# XXX: Figure out what to do other than complain.
809
raise errors.BzrCommandError("At %s you have a valid .bzr control"
810
" directory, but not a branch or repository. This is an"
811
" unsupported configuration. Please move the target directory"
812
" out of the way and try again."
815
# We have a repository but no branch, copy the revisions, and then
817
repository_to.fetch(br_from.repository, revision_id=revision_id)
818
br_to = br_from.clone(dir_to, revision_id=revision_id)
819
note('Created new branch.')
820
if br_from.get_push_location() is None or remember:
821
br_from.set_push_location(br_to.base)
822
else: # We have a valid to branch
823
# We were able to connect to the remote location, so remember it
824
# we don't need to successfully push because of possible divergence.
825
if br_from.get_push_location() is None or remember:
826
br_from.set_push_location(br_to.base)
828
old_rh = br_to.revision_history()
831
tree_to = dir_to.open_workingtree()
832
except errors.NotLocalUrl:
833
warning("This transport does not update the working "
834
"tree of: %s. See 'bzr help working-trees' for "
835
"more information." % br_to.base)
836
push_result = br_from.push(br_to, overwrite,
837
stop_revision=revision_id)
838
except errors.NoWorkingTree:
839
push_result = br_from.push(br_to, overwrite,
840
stop_revision=revision_id)
844
push_result = br_from.push(tree_to.branch, overwrite,
845
stop_revision=revision_id)
849
except errors.DivergedBranches:
850
raise errors.BzrCommandError('These branches have diverged.'
851
' Try using "merge" and then "push".')
852
if push_result is not None:
853
push_result.report(self.outf)
855
new_rh = br_to.revision_history()
858
from bzrlib.log import show_changed_revisions
859
show_changed_revisions(br_to, old_rh, new_rh,
862
# we probably did a clone rather than a push, so a message was
1080
867
class cmd_branch(Command):
1930
1637
raise errors.BzrCommandError(msg)
1933
def _parse_levels(s):
1937
msg = "The levels argument must be an integer."
1938
raise errors.BzrCommandError(msg)
1941
1640
class cmd_log(Command):
1942
"""Show historical log for a branch or subset of a branch.
1944
log is bzr's default tool for exploring the history of a branch.
1945
The branch to use is taken from the first parameter. If no parameters
1946
are given, the branch containing the working directory is logged.
1947
Here are some simple examples::
1949
bzr log log the current branch
1950
bzr log foo.py log a file in its branch
1951
bzr log http://server/branch log a branch on a server
1953
The filtering, ordering and information shown for each revision can
1954
be controlled as explained below. By default, all revisions are
1955
shown sorted (topologically) so that newer revisions appear before
1956
older ones and descendants always appear before ancestors. If displayed,
1957
merged revisions are shown indented under the revision in which they
1962
The log format controls how information about each revision is
1963
displayed. The standard log formats are called ``long``, ``short``
1964
and ``line``. The default is long. See ``bzr help log-formats``
1965
for more details on log formats.
1967
The following options can be used to control what information is
1970
-l N display a maximum of N revisions
1971
-n N display N levels of revisions (0 for all, 1 for collapsed)
1972
-v display a status summary (delta) for each revision
1973
-p display a diff (patch) for each revision
1974
--show-ids display revision-ids (and file-ids), not just revnos
1976
Note that the default number of levels to display is a function of the
1977
log format. If the -n option is not used, the standard log formats show
1978
just the top level (mainline).
1980
Status summaries are shown using status flags like A, M, etc. To see
1981
the changes explained using words like ``added`` and ``modified``
1982
instead, use the -vv option.
1986
To display revisions from oldest to newest, use the --forward option.
1987
In most cases, using this option will have little impact on the total
1988
time taken to produce a log, though --forward does not incrementally
1989
display revisions like --reverse does when it can.
1991
:Revision filtering:
1993
The -r option can be used to specify what revision or range of revisions
1994
to filter against. The various forms are shown below::
1996
-rX display revision X
1997
-rX.. display revision X and later
1998
-r..Y display up to and including revision Y
1999
-rX..Y display from X to Y inclusive
2001
See ``bzr help revisionspec`` for details on how to specify X and Y.
2002
Some common examples are given below::
2004
-r-1 show just the tip
2005
-r-10.. show the last 10 mainline revisions
2006
-rsubmit:.. show what's new on this branch
2007
-rancestor:path.. show changes since the common ancestor of this
2008
branch and the one at location path
2009
-rdate:yesterday.. show changes since yesterday
2011
When logging a range of revisions using -rX..Y, log starts at
2012
revision Y and searches back in history through the primary
2013
("left-hand") parents until it finds X. When logging just the
2014
top level (using -n1), an error is reported if X is not found
2015
along the way. If multi-level logging is used (-n0), X may be
2016
a nested merge revision and the log will be truncated accordingly.
2020
If parameters are given and the first one is not a branch, the log
2021
will be filtered to show only those revisions that changed the
2022
nominated files or directories.
2024
Filenames are interpreted within their historical context. To log a
2025
deleted file, specify a revision range so that the file existed at
2026
the end or start of the range.
2028
Historical context is also important when interpreting pathnames of
2029
renamed files/directories. Consider the following example:
2031
* revision 1: add tutorial.txt
2032
* revision 2: modify tutorial.txt
2033
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2037
* ``bzr log guide.txt`` will log the file added in revision 1
2039
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2041
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2042
the original file in revision 2.
2044
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2045
was no file called guide.txt in revision 2.
2047
Renames are always followed by log. By design, there is no need to
2048
explicitly ask for this (and no way to stop logging a file back
2049
until it was last renamed).
2053
The --message option can be used for finding revisions that match a
2054
regular expression in a commit message.
2058
GUI tools and IDEs are often better at exploring history than command
2059
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2060
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2061
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2063
Web interfaces are often better at exploring history than command line
2064
tools, particularly for branches on servers. You may prefer Loggerhead
2065
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2067
You may find it useful to add the aliases below to ``bazaar.conf``::
2071
top = log -l10 --line
2074
``bzr tip`` will then show the latest revision while ``bzr top``
2075
will show the last 10 mainline revisions. To see the details of a
2076
particular revision X, ``bzr show -rX``.
2078
If you are interested in looking deeper into a particular merge X,
2079
use ``bzr log -n0 -rX``.
2081
``bzr log -v`` on a branch with lots of history is currently
2082
very slow. A fix for this issue is currently under development.
2083
With or without that fix, it is recommended that a revision range
2084
be given when using the -v option.
2086
bzr has a generic full-text matching plugin, bzr-search, that can be
2087
used to find revisions matching user names, commit messages, etc.
2088
Among other features, this plugin can find all revisions containing
2089
a list of words but not others.
2091
When exploring non-mainline history on large projects with deep
2092
history, the performance of log can be greatly improved by installing
2093
the historycache plugin. This plugin buffers historical information
2094
trading disk space for faster speed.
1641
"""Show log of a branch, file, or directory.
1643
By default show the log of the branch containing the working directory.
1645
To request a range of logs, you can use the command -r begin..end
1646
-r revision requests a specific revision, -r ..end or -r begin.. are
1650
Log the current branch::
1658
Log the last 10 revisions of a branch::
1660
bzr log -r -10.. http://server/branch
2096
takes_args = ['file*']
2097
_see_also = ['log-formats', 'revisionspec']
1663
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1665
takes_args = ['location?']
2098
1666
takes_options = [
2099
1667
Option('forward',
2100
1668
help='Show from oldest to newest.'),
1671
help='Display timezone as local, original, or utc.'),
2102
1672
custom_help('verbose',
2103
1673
help='Show files changed in each revision.'),
2107
type=bzrlib.option._parse_revision_str,
2109
help='Show just the specified revision.'
2110
' See also "help revisionspec".'),
2114
help='Number of levels to display - 0 for all, 1 for flat.',
2116
type=_parse_levels),
2117
1677
Option('message',
2118
1678
short_name='m',
2119
1679
help='Show revisions whose message matches this '
2197
1727
dir, relpath = bzrdir.BzrDir.open_containing(location)
2198
1728
b = dir.open_branch()
2199
rev1, rev2 = _get_revision_range(revision, b, self.name())
2201
# Decide on the type of delta & diff filtering to use
2202
# TODO: add an --all-files option to make this configurable & consistent
2210
diff_type = 'partial'
2216
# Build the log formatter
1732
if revision is None:
1735
elif len(revision) == 1:
1736
rev1 = rev2 = revision[0].in_history(b)
1737
elif len(revision) == 2:
1738
if revision[1].get_branch() != revision[0].get_branch():
1739
# b is taken from revision[0].get_branch(), and
1740
# show_log will use its revision_history. Having
1741
# different branches will lead to weird behaviors.
1742
raise errors.BzrCommandError(
1743
"Log doesn't accept two revisions in different"
1745
rev1 = revision[0].in_history(b)
1746
rev2 = revision[1].in_history(b)
1748
raise errors.BzrCommandError(
1749
'bzr log --revision takes one or two values.')
2217
1751
if log_format is None:
2218
1752
log_format = log.log_formatter_registry.get_default(b)
2219
1754
lf = log_format(show_ids=show_ids, to_file=self.outf,
2220
show_timezone=timezone,
2221
delta_format=get_verbosity_level(),
2223
show_advice=levels is None)
2225
# Choose the algorithm for doing the logging. It's annoying
2226
# having multiple code paths like this but necessary until
2227
# the underlying repository format is faster at generating
2228
# deltas or can provide everything we need from the indices.
2229
# The default algorithm - match-using-deltas - works for
2230
# multiple files and directories and is faster for small
2231
# amounts of history (200 revisions say). However, it's too
2232
# slow for logging a single file in a repository with deep
2233
# history, i.e. > 10K revisions. In the spirit of "do no
2234
# evil when adding features", we continue to use the
2235
# original algorithm - per-file-graph - for the "single
2236
# file that isn't a directory without showing a delta" case.
2237
partial_history = revision and b.repository._format.supports_chks
2238
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2239
or delta_type or partial_history)
2241
# Build the LogRequest and execute it
2242
if len(file_ids) == 0:
2244
rqst = make_log_request_dict(
2245
direction=direction, specific_fileids=file_ids,
2246
start_revision=rev1, end_revision=rev2, limit=limit,
2247
message_search=message, delta_type=delta_type,
2248
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2249
Logger(b, rqst).show(lf)
1755
show_timezone=timezone)
1761
direction=direction,
1762
start_revision=rev1,
2254
def _get_revision_range(revisionspec_list, branch, command_name):
2255
"""Take the input of a revision option and turn it into a revision range.
2257
It returns RevisionInfo objects which can be used to obtain the rev_id's
2258
of the desired revisions. It does some user input validations.
2260
if revisionspec_list is None:
2263
elif len(revisionspec_list) == 1:
2264
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2265
elif len(revisionspec_list) == 2:
2266
start_spec = revisionspec_list[0]
2267
end_spec = revisionspec_list[1]
2268
if end_spec.get_branch() != start_spec.get_branch():
2269
# b is taken from revision[0].get_branch(), and
2270
# show_log will use its revision_history. Having
2271
# different branches will lead to weird behaviors.
2272
raise errors.BzrCommandError(
2273
"bzr %s doesn't accept two revisions in different"
2274
" branches." % command_name)
2275
rev1 = start_spec.in_history(branch)
2276
# Avoid loading all of history when we know a missing
2277
# end of range means the last revision ...
2278
if end_spec.spec is None:
2279
last_revno, last_revision_id = branch.last_revision_info()
2280
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2282
rev2 = end_spec.in_history(branch)
2284
raise errors.BzrCommandError(
2285
'bzr %s --revision takes one or two values.' % command_name)
2289
def _revision_range_to_revid_range(revision_range):
2292
if revision_range[0] is not None:
2293
rev_id1 = revision_range[0].rev_id
2294
if revision_range[1] is not None:
2295
rev_id2 = revision_range[1].rev_id
2296
return rev_id1, rev_id2
2298
1770
def get_log_format(long=False, short=False, line=False, default='long'):
2299
1771
log_format = default
2728
2196
class cmd_commit(Command):
2729
2197
"""Commit changes into a new revision.
2731
An explanatory message needs to be given for each commit. This is
2732
often done by using the --message option (getting the message from the
2733
command line) or by using the --file option (getting the message from
2734
a file). If neither of these options is given, an editor is opened for
2735
the user to enter the message. To see the changed files in the
2736
boilerplate text loaded into the editor, use the --show-diff option.
2738
By default, the entire tree is committed and the person doing the
2739
commit is assumed to be the author. These defaults can be overridden
2744
If selected files are specified, only changes to those files are
2745
committed. If a directory is specified then the directory and
2746
everything within it is committed.
2748
When excludes are given, they take precedence over selected files.
2749
For example, to commit only changes within foo, but not changes
2752
bzr commit foo -x foo/bar
2754
A selective commit after a merge is not yet supported.
2758
If the author of the change is not the same person as the committer,
2759
you can specify the author's name using the --author option. The
2760
name should be in the same format as a committer-id, e.g.
2761
"John Doe <jdoe@example.com>". If there is more than one author of
2762
the change you can specify the option multiple times, once for each
2767
A common mistake is to forget to add a new file or directory before
2768
running the commit command. The --strict option checks for unknown
2769
files and aborts the commit if any are found. More advanced pre-commit
2770
checks can be implemented by defining hooks. See ``bzr help hooks``
2775
If you accidentially commit the wrong changes or make a spelling
2776
mistake in the commit message say, you can use the uncommit command
2777
to undo it. See ``bzr help uncommit`` for details.
2779
Hooks can also be configured to run after a commit. This allows you
2780
to trigger updates to external systems like bug trackers. The --fixes
2781
option can be used to record the association between a revision and
2782
one or more bugs. See ``bzr help bugs`` for details.
2784
A selective commit may fail in some cases where the committed
2785
tree would be invalid. Consider::
2790
bzr commit foo -m "committing foo"
2791
bzr mv foo/bar foo/baz
2794
bzr commit foo/bar -m "committing bar but not baz"
2796
In the example above, the last commit will fail by design. This gives
2797
the user the opportunity to decide whether they want to commit the
2798
rename at the same time, separately first, or not at all. (As a general
2799
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2199
If no arguments are given, the entire tree is committed.
2201
If selected files are specified, only changes to those files are
2202
committed. If a directory is specified then the directory and everything
2203
within it is committed.
2205
If author of the change is not the same person as the committer, you can
2206
specify the author's name using the --author option. The name should be
2207
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2209
A selected-file commit may fail in some cases where the committed
2210
tree would be invalid. Consider::
2215
bzr commit foo -m "committing foo"
2216
bzr mv foo/bar foo/baz
2219
bzr commit foo/bar -m "committing bar but not baz"
2221
In the example above, the last commit will fail by design. This gives
2222
the user the opportunity to decide whether they want to commit the
2223
rename at the same time, separately first, or not at all. (As a general
2224
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2226
Note: A selected-file commit after a merge is not yet supported.
2801
2228
# TODO: Run hooks on tree to-be-committed, and after commit.
3931
3232
takes_args = ['context?']
3932
3233
aliases = ['s-c']
3935
3236
@display_command
3936
3237
def run(self, context=None):
3937
3238
import shellcomplete
3938
3239
shellcomplete.shellcomplete(context)
3242
class cmd_fetch(Command):
3243
"""Copy in history from another branch but don't merge it.
3245
This is an internal method used for pull and merge.
3248
takes_args = ['from_branch', 'to_branch']
3249
def run(self, from_branch, to_branch):
3250
from bzrlib.fetch import Fetcher
3251
from_b = Branch.open(from_branch)
3252
to_b = Branch.open(to_branch)
3253
Fetcher(to_b, from_b)
3941
3256
class cmd_missing(Command):
3942
3257
"""Show unmerged/unpulled revisions between two branches.
3944
3259
OTHER_BRANCH may be local or remote.
3946
To filter on a range of revisions, you can use the command -r begin..end
3947
-r revision requests a specific revision, -r ..end or -r begin.. are
3952
Determine the missing revisions between this and the branch at the
3953
remembered pull location::
3957
Determine the missing revisions between this and another branch::
3959
bzr missing http://server/branch
3961
Determine the missing revisions up to a specific revision on the other
3964
bzr missing -r ..-10
3966
Determine the missing revisions up to a specific revision on this
3969
bzr missing --my-revision ..-10
3972
3262
_see_also = ['merge', 'pull']
3973
3263
takes_args = ['other_branch?']
3974
3264
takes_options = [
3975
Option('reverse', 'Reverse the order of revisions.'),
3977
'Display changes in the local branch only.'),
3978
Option('this' , 'Same as --mine-only.'),
3979
Option('theirs-only',
3980
'Display changes in the remote branch only.'),
3981
Option('other', 'Same as --theirs-only.'),
3985
custom_help('revision',
3986
help='Filter on other branch revisions (inclusive). '
3987
'See "help revisionspec" for details.'),
3988
Option('my-revision',
3989
type=_parse_revision_str,
3990
help='Filter on local branch revisions (inclusive). '
3991
'See "help revisionspec" for details.'),
3992
Option('include-merges',
3993
'Show all revisions in addition to the mainline ones.'),
3265
Option('reverse', 'Reverse the order of revisions.'),
3267
'Display changes in the local branch only.'),
3268
Option('this' , 'Same as --mine-only.'),
3269
Option('theirs-only',
3270
'Display changes in the remote branch only.'),
3271
Option('other', 'Same as --theirs-only.'),
3995
3276
encoding_type = 'replace'
3997
3278
@display_command
3998
3279
def run(self, other_branch=None, reverse=False, mine_only=False,
4000
log_format=None, long=False, short=False, line=False,
4001
show_ids=False, verbose=False, this=False, other=False,
4002
include_merges=False, revision=None, my_revision=None):
3280
theirs_only=False, log_format=None, long=False, short=False, line=False,
3281
show_ids=False, verbose=False, this=False, other=False):
4003
3282
from bzrlib.missing import find_unmerged, iter_log_revisions
4012
# TODO: We should probably check that we don't have mine-only and
4013
# theirs-only set, but it gets complicated because we also have
4014
# this and other which could be used.
4021
3289
local_branch = Branch.open_containing(u".")[0]
4022
3290
parent = local_branch.get_parent()
4564
def get_host_and_port(self, port):
4565
"""Return the host and port to run the smart server on.
4567
If 'port' is None, None will be returned for the host and port.
4569
If 'port' has a colon in it, the string before the colon will be
4570
interpreted as the host.
4572
:param port: A string of the port to run the server on.
4573
:return: A tuple of (host, port), where 'host' is a host name or IP,
4574
and port is an integer TCP/IP port.
4577
if port is not None:
4579
host, port = port.split(':')
4583
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4585
from bzrlib.transport import get_transport, transport_server_registry
3784
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3785
from bzrlib import lockdir
3786
from bzrlib.smart import medium, server
3787
from bzrlib.transport import get_transport
3788
from bzrlib.transport.chroot import ChrootServer
4586
3789
if directory is None:
4587
3790
directory = os.getcwd()
4588
if protocol is None:
4589
protocol = transport_server_registry.get()
4590
host, port = self.get_host_and_port(port)
4591
3791
url = urlutils.local_path_to_url(directory)
4592
3792
if not allow_writes:
4593
3793
url = 'readonly+' + url
4594
transport = get_transport(url)
4595
protocol(transport, host, port, inet)
3794
chroot_server = ChrootServer(get_transport(url))
3795
chroot_server.setUp()
3796
t = get_transport(chroot_server.get_url())
3798
smart_server = medium.SmartServerPipeStreamMedium(
3799
sys.stdin, sys.stdout, t)
3801
host = medium.BZR_DEFAULT_INTERFACE
3803
port = medium.BZR_DEFAULT_PORT
3806
host, port = port.split(':')
3808
smart_server = server.SmartTCPServer(t, host=host, port=port)
3809
print 'listening on port: ', smart_server.port
3811
# for the duration of this server, no UI output is permitted.
3812
# note that this may cause problems with blackbox tests. This should
3813
# be changed with care though, as we dont want to use bandwidth sending
3814
# progress over stderr to smart server clients!
3815
old_factory = ui.ui_factory
3816
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3818
ui.ui_factory = ui.SilentUIFactory()
3819
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3820
smart_server.serve()
3822
ui.ui_factory = old_factory
3823
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4598
3826
class cmd_join(Command):
4599
"""Combine a tree into its containing tree.
4601
This command requires the target tree to be in a rich-root format.
3827
"""Combine a subtree into its containing tree.
3829
This command is for experimental use only. It requires the target tree
3830
to be in dirstate-with-subtree format, which cannot be converted into
4603
3833
The TREE argument should be an independent tree, inside another tree, but
4604
3834
not part of it. (Such trees can be produced by "bzr split", but also by
4835
4069
'rather than the one containing the working directory.',
4836
4070
short_name='f',
4838
Option('output', short_name='o',
4839
help='Write merge directive to this file; '
4840
'use - for stdout.',
4072
Option('output', short_name='o', help='Write directive to this file.',
4842
4074
Option('mail-to', help='Mail the request to this address.',
4846
Option('body', help='Body for the email.', type=unicode),
4847
RegistryOption('format',
4848
help='Use the specified output format.',
4849
lazy_registry=('bzrlib.send', 'format_registry'))
4078
RegistryOption.from_kwargs('format',
4079
'Use the specified output format.',
4080
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4081
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4852
4084
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4853
4085
no_patch=False, revision=None, remember=False, output=None,
4854
format=None, mail_to=None, message=None, body=None, **kwargs):
4855
from bzrlib.send import send
4856
return send(submit_branch, revision, public_branch, remember,
4086
format='4', mail_to=None, message=None, **kwargs):
4087
return self._run(submit_branch, revision, public_branch, remember,
4857
4088
format, no_bundle, no_patch, output,
4858
kwargs.get('from', '.'), mail_to, message, body,
4089
kwargs.get('from', '.'), mail_to, message)
4091
def _run(self, submit_branch, revision, public_branch, remember, format,
4092
no_bundle, no_patch, output, from_, mail_to, message):
4093
from bzrlib.revision import NULL_REVISION
4094
branch = Branch.open_containing(from_)[0]
4096
outfile = StringIO()
4100
outfile = open(output, 'wb')
4101
# we may need to write data into branch's repository to calculate
4106
config = branch.get_config()
4108
mail_to = config.get_user_option('submit_to')
4109
mail_client = config.get_mail_client()
4110
if remember and submit_branch is None:
4111
raise errors.BzrCommandError(
4112
'--remember requires a branch to be specified.')
4113
stored_submit_branch = branch.get_submit_branch()
4114
remembered_submit_branch = False
4115
if submit_branch is None:
4116
submit_branch = stored_submit_branch
4117
remembered_submit_branch = True
4119
if stored_submit_branch is None or remember:
4120
branch.set_submit_branch(submit_branch)
4121
if submit_branch is None:
4122
submit_branch = branch.get_parent()
4123
remembered_submit_branch = True
4124
if submit_branch is None:
4125
raise errors.BzrCommandError('No submit branch known or'
4127
if remembered_submit_branch:
4128
note('Using saved location: %s', submit_branch)
4131
submit_config = Branch.open(submit_branch).get_config()
4132
mail_to = submit_config.get_user_option("child_submit_to")
4134
stored_public_branch = branch.get_public_branch()
4135
if public_branch is None:
4136
public_branch = stored_public_branch
4137
elif stored_public_branch is None or remember:
4138
branch.set_public_branch(public_branch)
4139
if no_bundle and public_branch is None:
4140
raise errors.BzrCommandError('No public branch specified or'
4142
base_revision_id = None
4144
if revision is not None:
4145
if len(revision) > 2:
4146
raise errors.BzrCommandError('bzr send takes '
4147
'at most two one revision identifiers')
4148
revision_id = revision[-1].in_history(branch).rev_id
4149
if len(revision) == 2:
4150
base_revision_id = revision[0].in_history(branch).rev_id
4151
if revision_id is None:
4152
revision_id = branch.last_revision()
4153
if revision_id == NULL_REVISION:
4154
raise errors.BzrCommandError('No revisions to submit.')
4156
directive = merge_directive.MergeDirective2.from_objects(
4157
branch.repository, revision_id, time.time(),
4158
osutils.local_time_offset(), submit_branch,
4159
public_branch=public_branch, include_patch=not no_patch,
4160
include_bundle=not no_bundle, message=message,
4161
base_revision_id=base_revision_id)
4162
elif format == '0.9':
4165
patch_type = 'bundle'
4167
raise errors.BzrCommandError('Format 0.9 does not'
4168
' permit bundle with no patch')
4174
directive = merge_directive.MergeDirective.from_objects(
4175
branch.repository, revision_id, time.time(),
4176
osutils.local_time_offset(), submit_branch,
4177
public_branch=public_branch, patch_type=patch_type,
4180
outfile.writelines(directive.to_lines())
4182
subject = '[MERGE] '
4183
if message is not None:
4186
revision = branch.repository.get_revision(revision_id)
4187
subject += revision.get_summary()
4188
basename = directive.get_disk_name(branch)
4189
mail_client.compose_merge_request(mail_to, subject,
4190
outfile.getvalue(), basename)
4862
4197
class cmd_bundle_revisions(cmd_send):
4863
"""Create a merge-directive for submitting changes.
4199
"""Create a merge-directive for submiting changes.
4865
4201
A merge directive provides many things needed for requesting merges:
5166
4445
def run(self, to_location, force=False):
5167
4446
from bzrlib import switch
4447
to_branch = Branch.open(to_location)
5168
4448
tree_location = '.'
5169
4449
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5171
branch = control_dir.open_branch()
5172
had_explicit_nick = branch.get_config().has_explicit_nickname()
5173
except errors.NotBranchError:
5174
had_explicit_nick = False
5176
to_branch = Branch.open(to_location)
5177
except errors.NotBranchError:
5178
this_url = self._get_branch_location(control_dir)
5179
to_branch = Branch.open(
5180
urlutils.join(this_url, '..', to_location))
5181
4450
switch.switch(control_dir, to_branch, force)
5182
if had_explicit_nick:
5183
branch = control_dir.open_branch() #get the new branch!
5184
branch.nick = to_branch.nick
5185
4451
note('Switched to branch: %s',
5186
4452
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5188
def _get_branch_location(self, control_dir):
5189
"""Return location of branch for this control dir."""
5191
this_branch = control_dir.open_branch()
5192
# This may be a heavy checkout, where we want the master branch
5193
master_location = this_branch.get_bound_location()
5194
if master_location is not None:
5195
return master_location
5196
# If not, use a local sibling
5197
return this_branch.base
5198
except errors.NotBranchError:
5199
format = control_dir.find_branch_format()
5200
if getattr(format, 'get_reference', None) is not None:
5201
return format.get_reference(control_dir)
5203
return control_dir.root_transport.base
5206
class cmd_view(Command):
5207
"""Manage filtered views.
5209
Views provide a mask over the tree so that users can focus on
5210
a subset of a tree when doing their work. After creating a view,
5211
commands that support a list of files - status, diff, commit, etc -
5212
effectively have that list of files implicitly given each time.
5213
An explicit list of files can still be given but those files
5214
must be within the current view.
5216
In most cases, a view has a short life-span: it is created to make
5217
a selected change and is deleted once that change is committed.
5218
At other times, you may wish to create one or more named views
5219
and switch between them.
5221
To disable the current view without deleting it, you can switch to
5222
the pseudo view called ``off``. This can be useful when you need
5223
to see the whole tree for an operation or two (e.g. merge) but
5224
want to switch back to your view after that.
5227
To define the current view::
5229
bzr view file1 dir1 ...
5231
To list the current view::
5235
To delete the current view::
5239
To disable the current view without deleting it::
5241
bzr view --switch off
5243
To define a named view and switch to it::
5245
bzr view --name view-name file1 dir1 ...
5247
To list a named view::
5249
bzr view --name view-name
5251
To delete a named view::
5253
bzr view --name view-name --delete
5255
To switch to a named view::
5257
bzr view --switch view-name
5259
To list all views defined::
5263
To delete all views::
5265
bzr view --delete --all
5269
takes_args = ['file*']
5272
help='Apply list or delete action to all views.',
5275
help='Delete the view.',
5278
help='Name of the view to define, list or delete.',
5282
help='Name of the view to switch to.',
5287
def run(self, file_list,
5293
tree, file_list = tree_files(file_list, apply_view=False)
5294
current_view, view_dict = tree.views.get_view_info()
5299
raise errors.BzrCommandError(
5300
"Both --delete and a file list specified")
5302
raise errors.BzrCommandError(
5303
"Both --delete and --switch specified")
5305
tree.views.set_view_info(None, {})
5306
self.outf.write("Deleted all views.\n")
5308
raise errors.BzrCommandError("No current view to delete")
5310
tree.views.delete_view(name)
5311
self.outf.write("Deleted '%s' view.\n" % name)
5314
raise errors.BzrCommandError(
5315
"Both --switch and a file list specified")
5317
raise errors.BzrCommandError(
5318
"Both --switch and --all specified")
5319
elif switch == 'off':
5320
if current_view is None:
5321
raise errors.BzrCommandError("No current view to disable")
5322
tree.views.set_view_info(None, view_dict)
5323
self.outf.write("Disabled '%s' view.\n" % (current_view))
5325
tree.views.set_view_info(switch, view_dict)
5326
view_str = views.view_display_str(tree.views.lookup_view())
5327
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5330
self.outf.write('Views defined:\n')
5331
for view in sorted(view_dict):
5332
if view == current_view:
5336
view_str = views.view_display_str(view_dict[view])
5337
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5339
self.outf.write('No views defined.\n')
5342
# No name given and no current view set
5345
raise errors.BzrCommandError(
5346
"Cannot change the 'off' pseudo view")
5347
tree.views.set_view(name, sorted(file_list))
5348
view_str = views.view_display_str(tree.views.lookup_view())
5349
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5353
# No name given and no current view set
5354
self.outf.write('No current view.\n')
5356
view_str = views.view_display_str(tree.views.lookup_view(name))
5357
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5360
4455
class cmd_hooks(Command):
5366
for hook_key in sorted(hooks.known_hooks.keys()):
5367
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5368
self.outf.write("%s:\n" % type(some_hooks).__name__)
5369
for hook_name, hook_point in sorted(some_hooks.items()):
5370
self.outf.write(" %s:\n" % (hook_name,))
5371
found_hooks = list(hook_point)
5373
for hook in found_hooks:
5374
self.outf.write(" %s\n" %
5375
(some_hooks.get_hook_name(hook),))
5377
self.outf.write(" <no hooks installed>\n")
5380
class cmd_shelve(Command):
5381
"""Temporarily set aside some changes from the current tree.
5383
Shelve allows you to temporarily put changes you've made "on the shelf",
5384
ie. out of the way, until a later time when you can bring them back from
5385
the shelf with the 'unshelve' command. The changes are stored alongside
5386
your working tree, and so they aren't propagated along with your branch nor
5387
will they survive its deletion.
5389
If shelve --list is specified, previously-shelved changes are listed.
5391
Shelve is intended to help separate several sets of changes that have
5392
been inappropriately mingled. If you just want to get rid of all changes
5393
and you don't need to restore them later, use revert. If you want to
5394
shelve all text changes at once, use shelve --all.
5396
If filenames are specified, only the changes to those files will be
5397
shelved. Other files will be left untouched.
5399
If a revision is specified, changes since that revision will be shelved.
5401
You can put multiple items on the shelf, and by default, 'unshelve' will
5402
restore the most recently shelved changes.
5405
takes_args = ['file*']
5409
Option('all', help='Shelve all changes.'),
5411
RegistryOption('writer', 'Method to use for writing diffs.',
5412
bzrlib.option.diff_writer_registry,
5413
value_switches=True, enum_switch=False),
5415
Option('list', help='List shelved changes.'),
5417
help='Destroy removed changes instead of shelving them.'),
5419
_see_also = ['unshelve']
5421
def run(self, revision=None, all=False, file_list=None, message=None,
5422
writer=None, list=False, destroy=False):
5424
return self.run_for_list()
5425
from bzrlib.shelf_ui import Shelver
5427
writer = bzrlib.option.diff_writer_registry.get()
5429
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5430
message, destroy=destroy).run()
5431
except errors.UserAbort:
5434
def run_for_list(self):
5435
tree = WorkingTree.open_containing('.')[0]
5438
manager = tree.get_shelf_manager()
5439
shelves = manager.active_shelves()
5440
if len(shelves) == 0:
5441
note('No shelved changes.')
5443
for shelf_id in reversed(shelves):
5444
message = manager.get_metadata(shelf_id).get('message')
5446
message = '<no message>'
5447
self.outf.write('%3d: %s\n' % (shelf_id, message))
5453
class cmd_unshelve(Command):
5454
"""Restore shelved changes.
5456
By default, the most recently shelved changes are restored. However if you
5457
specify a shelf by id those changes will be restored instead. This works
5458
best when the changes don't depend on each other.
5461
takes_args = ['shelf_id?']
5463
RegistryOption.from_kwargs(
5464
'action', help="The action to perform.",
5465
enum_switch=False, value_switches=True,
5466
apply="Apply changes and remove from the shelf.",
5467
dry_run="Show changes, but do not apply or remove them.",
5468
delete_only="Delete changes without applying them."
5471
_see_also = ['shelve']
5473
def run(self, shelf_id=None, action='apply'):
5474
from bzrlib.shelf_ui import Unshelver
5475
Unshelver.from_args(shelf_id, action).run()
5478
class cmd_clean_tree(Command):
5479
"""Remove unwanted files from working tree.
5481
By default, only unknown files, not ignored files, are deleted. Versioned
5482
files are never deleted.
5484
Another class is 'detritus', which includes files emitted by bzr during
5485
normal operations and selftests. (The value of these files decreases with
5488
If no options are specified, unknown files are deleted. Otherwise, option
5489
flags are respected, and may be combined.
5491
To check what clean-tree will do, use --dry-run.
5493
takes_options = [Option('ignored', help='Delete all ignored files.'),
5494
Option('detritus', help='Delete conflict files, merge'
5495
' backups, and failed selftest dirs.'),
5497
help='Delete files unknown to bzr (default).'),
5498
Option('dry-run', help='Show files to delete instead of'
5500
Option('force', help='Do not prompt before deleting.')]
5501
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5503
from bzrlib.clean_tree import clean_tree
5504
if not (unknown or ignored or detritus):
5508
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5509
dry_run=dry_run, no_prompt=force)
5512
class cmd_reference(Command):
5513
"""list, view and set branch locations for nested trees.
5515
If no arguments are provided, lists the branch locations for nested trees.
5516
If one argument is provided, display the branch location for that tree.
5517
If two arguments are provided, set the branch location for that tree.
5522
takes_args = ['path?', 'location?']
5524
def run(self, path=None, location=None):
5526
if path is not None:
5528
tree, branch, relpath =(
5529
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5530
if path is not None:
5533
tree = branch.basis_tree()
4456
"""Show a branch's currently registered hooks.
4460
takes_args = ['path?']
4462
def run(self, path=None):
5534
4463
if path is None:
5535
info = branch._get_all_reference_info().iteritems()
5536
self._display_reference_info(tree, branch, info)
4465
branch_hooks = Branch.open(path).hooks
4466
for hook_type in branch_hooks:
4467
hooks = branch_hooks[hook_type]
4468
self.outf.write("%s:\n" % (hook_type,))
4471
self.outf.write(" %s\n" %
4472
(branch_hooks.get_hook_name(hook),))
4474
self.outf.write(" <no hooks installed>\n")
4477
def _create_prefix(cur_transport):
4478
needed = [cur_transport]
4479
# Recurse upwards until we can create a directory successfully
4481
new_transport = cur_transport.clone('..')
4482
if new_transport.base == cur_transport.base:
4483
raise errors.BzrCommandError(
4484
"Failed to create path prefix for %s."
4485
% cur_transport.base)
4487
new_transport.mkdir('.')
4488
except errors.NoSuchFile:
4489
needed.append(new_transport)
4490
cur_transport = new_transport
5538
file_id = tree.path2id(path)
5540
raise errors.NotVersionedError(path)
5541
if location is None:
5542
info = [(file_id, branch.get_reference_info(file_id))]
5543
self._display_reference_info(tree, branch, info)
5545
branch.set_reference_info(file_id, path, location)
5547
def _display_reference_info(self, tree, branch, info):
5549
for file_id, (path, location) in info:
5551
path = tree.id2path(file_id)
5552
except errors.NoSuchId:
5554
ref_list.append((path, location))
5555
for path, location in sorted(ref_list):
5556
self.outf.write('%s %s\n' % (path, location))
4493
# Now we only need to create child directories
4495
cur_transport = needed.pop()
4496
cur_transport.ensure_base()
4499
def _get_mergeable_helper(location):
4500
"""Get a merge directive or bundle if 'location' points to one.
4502
Try try to identify a bundle and returns its mergeable form. If it's not,
4503
we return the tried transport anyway so that it can reused to access the
4506
:param location: can point to a bundle or a branch.
4508
:return: mergeable, transport
4511
url = urlutils.normalize_url(location)
4512
url, filename = urlutils.split(url, exclude_trailing_slash=False)
4513
location_transport = transport.get_transport(url)
4516
# There may be redirections but we ignore the intermediate
4517
# and final transports used
4518
read = bundle.read_mergeable_from_transport
4519
mergeable, t = read(location_transport, filename)
4520
except errors.NotABundle:
4521
# Continue on considering this url a Branch but adjust the
4522
# location_transport
4523
location_transport = location_transport.clone(filename)
4524
return mergeable, location_transport
5559
4527
# these get imported and then picked up by the scan for cmd_*
5560
4528
# TODO: Some more consistent way to split command definitions across files;
5561
# we do need to load at least some information about them to know of
4529
# we do need to load at least some information about them to know of
5562
4530
# aliases. ideally we would avoid loading the implementation until the
5563
4531
# details were needed.
5564
4532
from bzrlib.cmd_version_info import cmd_version_info