1
# Copyright (C) 2005-2011 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""builtin bzr commands"""
21
from bzrlib.lazy_import import lazy_import
22
lazy_import(globals(), """
35
config as _mod_config,
45
revision as _mod_revision,
54
from bzrlib.branch import Branch
55
from bzrlib.conflicts import ConflictList
56
from bzrlib.transport import memory
57
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
58
from bzrlib.smtp_connection import SMTPConnection
59
from bzrlib.workingtree import WorkingTree
62
from bzrlib.commands import (
64
builtin_command_registry,
67
from bzrlib.option import (
74
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
80
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
81
def tree_files(file_list, default_branch=u'.', canonicalize=True,
83
return internal_tree_files(file_list, default_branch, canonicalize,
87
def tree_files_for_add(file_list):
89
Return a tree and list of absolute paths from a file list.
91
Similar to tree_files, but add handles files a bit differently, so it a
92
custom implementation. In particular, MutableTreeTree.smart_add expects
93
absolute paths, which it immediately converts to relative paths.
95
# FIXME Would be nice to just return the relative paths like
96
# internal_tree_files does, but there are a large number of unit tests
97
# that assume the current interface to mutabletree.smart_add
99
tree, relpath = WorkingTree.open_containing(file_list[0])
100
if tree.supports_views():
101
view_files = tree.views.lookup_view()
103
for filename in file_list:
104
if not osutils.is_inside_any(view_files, filename):
105
raise errors.FileOutsideView(filename, view_files)
106
file_list = file_list[:]
107
file_list[0] = tree.abspath(relpath)
109
tree = WorkingTree.open_containing(u'.')[0]
110
if tree.supports_views():
111
view_files = tree.views.lookup_view()
113
file_list = view_files
114
view_str = views.view_display_str(view_files)
115
note("Ignoring files outside view. View is %s" % view_str)
116
return tree, file_list
119
def _get_one_revision(command_name, revisions):
120
if revisions is None:
122
if len(revisions) != 1:
123
raise errors.BzrCommandError(
124
'bzr %s --revision takes exactly one revision identifier' % (
129
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
130
"""Get a revision tree. Not suitable for commands that change the tree.
132
Specifically, the basis tree in dirstate trees is coupled to the dirstate
133
and doing a commit/uncommit/pull will at best fail due to changing the
136
If tree is passed in, it should be already locked, for lifetime management
137
of the trees internal cached state.
141
if revisions is None:
143
rev_tree = tree.basis_tree()
145
rev_tree = branch.basis_tree()
147
revision = _get_one_revision(command_name, revisions)
148
rev_tree = revision.as_tree(branch)
152
# XXX: Bad function name; should possibly also be a class method of
153
# WorkingTree rather than a function.
154
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
155
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
157
"""Convert command-line paths to a WorkingTree and relative paths.
159
Deprecated: use WorkingTree.open_containing_paths instead.
161
This is typically used for command-line processors that take one or
162
more filenames, and infer the workingtree that contains them.
164
The filenames given are not required to exist.
166
:param file_list: Filenames to convert.
168
:param default_branch: Fallback tree path to use if file_list is empty or
171
:param apply_view: if True and a view is set, apply it or check that
172
specified files are within it
174
:return: workingtree, [relative_paths]
176
return WorkingTree.open_containing_paths(
177
file_list, default_directory='.',
182
def _get_view_info_for_change_reporter(tree):
183
"""Get the view information from a tree for change reporting."""
186
current_view = tree.views.get_view_info()[0]
187
if current_view is not None:
188
view_info = (current_view, tree.views.lookup_view())
189
except errors.ViewsNotSupported:
194
def _open_directory_or_containing_tree_or_branch(filename, directory):
195
"""Open the tree or branch containing the specified file, unless
196
the --directory option is used to specify a different branch."""
197
if directory is not None:
198
return (None, Branch.open(directory), filename)
199
return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
202
# TODO: Make sure no commands unconditionally use the working directory as a
203
# branch. If a filename argument is used, the first of them should be used to
204
# specify the branch. (Perhaps this can be factored out into some kind of
205
# Argument class, representing a file in a branch, where the first occurrence
208
class cmd_status(Command):
209
__doc__ = """Display status summary.
211
This reports on versioned and unknown files, reporting them
212
grouped by state. Possible states are:
215
Versioned in the working copy but not in the previous revision.
218
Versioned in the previous revision but removed or deleted
222
Path of this file changed from the previous revision;
223
the text may also have changed. This includes files whose
224
parent directory was renamed.
227
Text has changed since the previous revision.
230
File kind has been changed (e.g. from file to directory).
233
Not versioned and not matching an ignore pattern.
235
Additionally for directories, symlinks and files with a changed
236
executable bit, Bazaar indicates their type using a trailing
237
character: '/', '@' or '*' respectively. These decorations can be
238
disabled using the '--no-classify' option.
240
To see ignored files use 'bzr ignored'. For details on the
241
changes to file texts, use 'bzr diff'.
243
Note that --short or -S gives status flags for each item, similar
244
to Subversion's status command. To get output similar to svn -q,
247
If no arguments are specified, the status of the entire working
248
directory is shown. Otherwise, only the status of the specified
249
files or directories is reported. If a directory is given, status
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.
257
To compare the working directory to a specific revision, pass a
258
single revision to the revision argument.
260
To see which files have changed in a specific revision, or between
261
two revisions, pass a revision range to the revision argument.
262
This will produce the same results as calling 'bzr diff --summarize'.
265
# TODO: --no-recurse, --recurse options
267
takes_args = ['file*']
268
takes_options = ['show-ids', 'revision', 'change', 'verbose',
269
Option('short', help='Use short status indicators.',
271
Option('versioned', help='Only show versioned files.',
273
Option('no-pending', help='Don\'t show pending merges.',
275
Option('no-classify',
276
help='Do not mark object type using indicator.',
279
aliases = ['st', 'stat']
281
encoding_type = 'replace'
282
_see_also = ['diff', 'revert', 'status-flags']
285
def run(self, show_ids=False, file_list=None, revision=None, short=False,
286
versioned=False, no_pending=False, verbose=False,
288
from bzrlib.status import show_tree_status
290
if revision and len(revision) > 2:
291
raise errors.BzrCommandError('bzr status --revision takes exactly'
292
' one or two revision specifiers')
294
tree, relfile_list = WorkingTree.open_containing_paths(file_list)
295
# Avoid asking for specific files when that is not needed.
296
if relfile_list == ['']:
298
# Don't disable pending merges for full trees other than '.'.
299
if file_list == ['.']:
301
# A specific path within a tree was given.
302
elif relfile_list is not None:
304
show_tree_status(tree, show_ids=show_ids,
305
specific_files=relfile_list, revision=revision,
306
to_file=self.outf, short=short, versioned=versioned,
307
show_pending=(not no_pending), verbose=verbose,
308
classify=not no_classify)
311
class cmd_cat_revision(Command):
312
__doc__ = """Write out metadata for a revision.
314
The revision to print can either be specified by a specific
315
revision identifier, or you can use --revision.
319
takes_args = ['revision_id?']
320
takes_options = ['directory', 'revision']
321
# cat-revision is more for frontends so should be exact
324
def print_revision(self, revisions, revid):
325
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
326
record = stream.next()
327
if record.storage_kind == 'absent':
328
raise errors.NoSuchRevision(revisions, revid)
329
revtext = record.get_bytes_as('fulltext')
330
self.outf.write(revtext.decode('utf-8'))
333
def run(self, revision_id=None, revision=None, directory=u'.'):
334
if revision_id is not None and revision is not None:
335
raise errors.BzrCommandError('You can only supply one of'
336
' revision_id or --revision')
337
if revision_id is None and revision is None:
338
raise errors.BzrCommandError('You must supply either'
339
' --revision or a revision_id')
341
b = bzrdir.BzrDir.open_containing_tree_or_branch(directory)[1]
343
revisions = b.repository.revisions
344
if revisions is None:
345
raise errors.BzrCommandError('Repository %r does not support '
346
'access to raw revision texts')
348
b.repository.lock_read()
350
# TODO: jam 20060112 should cat-revision always output utf-8?
351
if revision_id is not None:
352
revision_id = osutils.safe_revision_id(revision_id, warn=False)
354
self.print_revision(revisions, revision_id)
355
except errors.NoSuchRevision:
356
msg = "The repository %s contains no revision %s." % (
357
b.repository.base, revision_id)
358
raise errors.BzrCommandError(msg)
359
elif revision is not None:
362
raise errors.BzrCommandError(
363
'You cannot specify a NULL revision.')
364
rev_id = rev.as_revision_id(b)
365
self.print_revision(revisions, rev_id)
367
b.repository.unlock()
370
class cmd_dump_btree(Command):
371
__doc__ = """Dump the contents of a btree index file to stdout.
373
PATH is a btree index file, it can be any URL. This includes things like
374
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
376
By default, the tuples stored in the index file will be displayed. With
377
--raw, we will uncompress the pages, but otherwise display the raw bytes
381
# TODO: Do we want to dump the internal nodes as well?
382
# TODO: It would be nice to be able to dump the un-parsed information,
383
# rather than only going through iter_all_entries. However, this is
384
# good enough for a start
386
encoding_type = 'exact'
387
takes_args = ['path']
388
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
389
' rather than the parsed tuples.'),
392
def run(self, path, raw=False):
393
dirname, basename = osutils.split(path)
394
t = transport.get_transport(dirname)
396
self._dump_raw_bytes(t, basename)
398
self._dump_entries(t, basename)
400
def _get_index_and_bytes(self, trans, basename):
401
"""Create a BTreeGraphIndex and raw bytes."""
402
bt = btree_index.BTreeGraphIndex(trans, basename, None)
403
bytes = trans.get_bytes(basename)
404
bt._file = cStringIO.StringIO(bytes)
405
bt._size = len(bytes)
408
def _dump_raw_bytes(self, trans, basename):
411
# We need to parse at least the root node.
412
# This is because the first page of every row starts with an
413
# uncompressed header.
414
bt, bytes = self._get_index_and_bytes(trans, basename)
415
for page_idx, page_start in enumerate(xrange(0, len(bytes),
416
btree_index._PAGE_SIZE)):
417
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
418
page_bytes = bytes[page_start:page_end]
420
self.outf.write('Root node:\n')
421
header_end, data = bt._parse_header_from_bytes(page_bytes)
422
self.outf.write(page_bytes[:header_end])
424
self.outf.write('\nPage %d\n' % (page_idx,))
425
if len(page_bytes) == 0:
426
self.outf.write('(empty)\n');
428
decomp_bytes = zlib.decompress(page_bytes)
429
self.outf.write(decomp_bytes)
430
self.outf.write('\n')
432
def _dump_entries(self, trans, basename):
434
st = trans.stat(basename)
435
except errors.TransportNotPossible:
436
# We can't stat, so we'll fake it because we have to do the 'get()'
438
bt, _ = self._get_index_and_bytes(trans, basename)
440
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
441
for node in bt.iter_all_entries():
442
# Node is made up of:
443
# (index, key, value, [references])
447
refs_as_tuples = None
449
refs_as_tuples = static_tuple.as_tuples(refs)
450
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
451
self.outf.write('%s\n' % (as_tuple,))
454
class cmd_remove_tree(Command):
455
__doc__ = """Remove the working tree from a given branch/checkout.
457
Since a lightweight checkout is little more than a working tree
458
this will refuse to run against one.
460
To re-create the working tree, use "bzr checkout".
462
_see_also = ['checkout', 'working-trees']
463
takes_args = ['location*']
466
help='Remove the working tree even if it has '
467
'uncommitted or shelved changes.'),
470
def run(self, location_list, force=False):
471
if not location_list:
474
for location in location_list:
475
d = bzrdir.BzrDir.open(location)
478
working = d.open_workingtree()
479
except errors.NoWorkingTree:
480
raise errors.BzrCommandError("No working tree to remove")
481
except errors.NotLocalUrl:
482
raise errors.BzrCommandError("You cannot remove the working tree"
485
if (working.has_changes()):
486
raise errors.UncommittedChanges(working)
487
if working.get_shelf_manager().last_shelf() is not None:
488
raise errors.ShelvedChanges(working)
490
if working.user_url != working.branch.user_url:
491
raise errors.BzrCommandError("You cannot remove the working tree"
492
" from a lightweight checkout")
494
d.destroy_workingtree()
497
class cmd_repair_workingtree(Command):
498
__doc__ = """Reset the working tree state file.
500
This is not meant to be used normally, but more as a way to recover from
501
filesystem corruption, etc. This rebuilds the working inventory back to a
502
'known good' state. Any new modifications (adding a file, renaming, etc)
503
will be lost, though modified files will still be detected as such.
505
Most users will want something more like "bzr revert" or "bzr update"
506
unless the state file has become corrupted.
508
By default this attempts to recover the current state by looking at the
509
headers of the state file. If the state file is too corrupted to even do
510
that, you can supply --revision to force the state of the tree.
513
takes_options = ['revision', 'directory',
515
help='Reset the tree even if it doesn\'t appear to be'
520
def run(self, revision=None, directory='.', force=False):
521
tree, _ = WorkingTree.open_containing(directory)
522
self.add_cleanup(tree.lock_tree_write().unlock)
526
except errors.BzrError:
527
pass # There seems to be a real error here, so we'll reset
530
raise errors.BzrCommandError(
531
'The tree does not appear to be corrupt. You probably'
532
' want "bzr revert" instead. Use "--force" if you are'
533
' sure you want to reset the working tree.')
537
revision_ids = [r.as_revision_id(tree.branch) for r in revision]
539
tree.reset_state(revision_ids)
540
except errors.BzrError, e:
541
if revision_ids is None:
542
extra = (', the header appears corrupt, try passing -r -1'
543
' to set the state to the last commit')
546
raise errors.BzrCommandError('failed to reset the tree state'
550
class cmd_revno(Command):
551
__doc__ = """Show current revision number.
553
This is equal to the number of revisions on this branch.
557
takes_args = ['location?']
559
Option('tree', help='Show revno of working tree'),
563
def run(self, tree=False, location=u'.'):
566
wt = WorkingTree.open_containing(location)[0]
567
self.add_cleanup(wt.lock_read().unlock)
568
except (errors.NoWorkingTree, errors.NotLocalUrl):
569
raise errors.NoWorkingTree(location)
570
revid = wt.last_revision()
572
revno_t = wt.branch.revision_id_to_dotted_revno(revid)
573
except errors.NoSuchRevision:
575
revno = ".".join(str(n) for n in revno_t)
577
b = Branch.open_containing(location)[0]
578
self.add_cleanup(b.lock_read().unlock)
581
self.outf.write(str(revno) + '\n')
584
class cmd_revision_info(Command):
585
__doc__ = """Show revision number and revision id for a given revision identifier.
588
takes_args = ['revision_info*']
591
custom_help('directory',
592
help='Branch to examine, '
593
'rather than the one containing the working directory.'),
594
Option('tree', help='Show revno of working tree'),
598
def run(self, revision=None, directory=u'.', tree=False,
599
revision_info_list=[]):
602
wt = WorkingTree.open_containing(directory)[0]
604
self.add_cleanup(wt.lock_read().unlock)
605
except (errors.NoWorkingTree, errors.NotLocalUrl):
607
b = Branch.open_containing(directory)[0]
608
self.add_cleanup(b.lock_read().unlock)
610
if revision is not None:
611
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
612
if revision_info_list is not None:
613
for rev_str in revision_info_list:
614
rev_spec = RevisionSpec.from_string(rev_str)
615
revision_ids.append(rev_spec.as_revision_id(b))
616
# No arguments supplied, default to the last revision
617
if len(revision_ids) == 0:
620
raise errors.NoWorkingTree(directory)
621
revision_ids.append(wt.last_revision())
623
revision_ids.append(b.last_revision())
627
for revision_id in revision_ids:
629
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
630
revno = '.'.join(str(i) for i in dotted_revno)
631
except errors.NoSuchRevision:
633
maxlen = max(maxlen, len(revno))
634
revinfos.append([revno, revision_id])
638
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
641
class cmd_add(Command):
642
__doc__ = """Add specified files or directories.
644
In non-recursive mode, all the named items are added, regardless
645
of whether they were previously ignored. A warning is given if
646
any of the named files are already versioned.
648
In recursive mode (the default), files are treated the same way
649
but the behaviour for directories is different. Directories that
650
are already versioned do not give a warning. All directories,
651
whether already versioned or not, are searched for files or
652
subdirectories that are neither versioned or ignored, and these
653
are added. This search proceeds recursively into versioned
654
directories. If no names are given '.' is assumed.
656
Therefore simply saying 'bzr add' will version all files that
657
are currently unknown.
659
Adding a file whose parent directory is not versioned will
660
implicitly add the parent, and so on up to the root. This means
661
you should never need to explicitly add a directory, they'll just
662
get added when you add a file in the directory.
664
--dry-run will show which files would be added, but not actually
667
--file-ids-from will try to use the file ids from the supplied path.
668
It looks up ids trying to find a matching parent directory with the
669
same filename, and then by pure path. This option is rarely needed
670
but can be useful when adding the same logical file into two
671
branches that will be merged later (without showing the two different
672
adds as a conflict). It is also useful when merging another project
673
into a subdirectory of this one.
675
Any files matching patterns in the ignore list will not be added
676
unless they are explicitly mentioned.
678
In recursive mode, files larger than the configuration option
679
add.maximum_file_size will be skipped. Named items are never skipped due
682
takes_args = ['file*']
685
help="Don't recursively add the contents of directories."),
687
help="Show what would be done, but don't actually do anything."),
689
Option('file-ids-from',
691
help='Lookup file ids from this tree.'),
693
encoding_type = 'replace'
694
_see_also = ['remove', 'ignore']
696
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
701
if file_ids_from is not None:
703
base_tree, base_path = WorkingTree.open_containing(
705
except errors.NoWorkingTree:
706
base_branch, base_path = Branch.open_containing(
708
base_tree = base_branch.basis_tree()
710
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
711
to_file=self.outf, should_print=(not is_quiet()))
713
action = bzrlib.add.AddWithSkipLargeAction(to_file=self.outf,
714
should_print=(not is_quiet()))
717
self.add_cleanup(base_tree.lock_read().unlock)
718
tree, file_list = tree_files_for_add(file_list)
719
added, ignored = tree.smart_add(file_list, not
720
no_recurse, action=action, save=not dry_run)
724
for glob in sorted(ignored.keys()):
725
for path in ignored[glob]:
726
self.outf.write("ignored %s matching \"%s\"\n"
730
class cmd_mkdir(Command):
731
__doc__ = """Create a new versioned directory.
733
This is equivalent to creating the directory and then adding it.
736
takes_args = ['dir+']
737
encoding_type = 'replace'
739
def run(self, dir_list):
741
wt, dd = WorkingTree.open_containing(d)
742
base = os.path.dirname(dd)
743
id = wt.path2id(base)
747
self.outf.write('added %s\n' % d)
749
raise errors.NotVersionedError(path=base)
752
class cmd_relpath(Command):
753
__doc__ = """Show path of a file relative to root"""
755
takes_args = ['filename']
759
def run(self, filename):
760
# TODO: jam 20050106 Can relpath return a munged path if
761
# sys.stdout encoding cannot represent it?
762
tree, relpath = WorkingTree.open_containing(filename)
763
self.outf.write(relpath)
764
self.outf.write('\n')
767
class cmd_inventory(Command):
768
__doc__ = """Show inventory of the current working copy or a revision.
770
It is possible to limit the output to a particular entry
771
type using the --kind option. For example: --kind file.
773
It is also possible to restrict the list of files to a specific
774
set. For example: bzr inventory --show-ids this/file
783
help='List entries of a particular kind: file, directory, symlink.',
786
takes_args = ['file*']
789
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
790
if kind and kind not in ['file', 'directory', 'symlink']:
791
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
793
revision = _get_one_revision('inventory', revision)
794
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
795
self.add_cleanup(work_tree.lock_read().unlock)
796
if revision is not None:
797
tree = revision.as_tree(work_tree.branch)
799
extra_trees = [work_tree]
800
self.add_cleanup(tree.lock_read().unlock)
805
if file_list is not None:
806
file_ids = tree.paths2ids(file_list, trees=extra_trees,
807
require_versioned=True)
808
# find_ids_across_trees may include some paths that don't
811
(tree.id2path(file_id), tree.inventory[file_id])
812
for file_id in file_ids if tree.has_id(file_id))
814
entries = tree.inventory.entries()
817
for path, entry in entries:
818
if kind and kind != entry.kind:
821
self.outf.write('%-50s %s\n' % (path, entry.file_id))
823
self.outf.write(path)
824
self.outf.write('\n')
827
class cmd_mv(Command):
828
__doc__ = """Move or rename a file.
831
bzr mv OLDNAME NEWNAME
833
bzr mv SOURCE... DESTINATION
835
If the last argument is a versioned directory, all the other names
836
are moved into it. Otherwise, there must be exactly two arguments
837
and the file is changed to a new name.
839
If OLDNAME does not exist on the filesystem but is versioned and
840
NEWNAME does exist on the filesystem but is not versioned, mv
841
assumes that the file has been manually moved and only updates
842
its internal inventory to reflect that change.
843
The same is valid when moving many SOURCE files to a DESTINATION.
845
Files cannot be moved between branches.
848
takes_args = ['names*']
849
takes_options = [Option("after", help="Move only the bzr identifier"
850
" of the file, because the file has already been moved."),
851
Option('auto', help='Automatically guess renames.'),
852
Option('dry-run', help='Avoid making changes when guessing renames.'),
854
aliases = ['move', 'rename']
855
encoding_type = 'replace'
857
def run(self, names_list, after=False, auto=False, dry_run=False):
859
return self.run_auto(names_list, after, dry_run)
861
raise errors.BzrCommandError('--dry-run requires --auto.')
862
if names_list is None:
864
if len(names_list) < 2:
865
raise errors.BzrCommandError("missing file argument")
866
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
867
self.add_cleanup(tree.lock_tree_write().unlock)
868
self._run(tree, names_list, rel_names, after)
870
def run_auto(self, names_list, after, dry_run):
871
if names_list is not None and len(names_list) > 1:
872
raise errors.BzrCommandError('Only one path may be specified to'
875
raise errors.BzrCommandError('--after cannot be specified with'
877
work_tree, file_list = WorkingTree.open_containing_paths(
878
names_list, default_directory='.')
879
self.add_cleanup(work_tree.lock_tree_write().unlock)
880
rename_map.RenameMap.guess_renames(work_tree, dry_run)
882
def _run(self, tree, names_list, rel_names, after):
883
into_existing = osutils.isdir(names_list[-1])
884
if into_existing and len(names_list) == 2:
886
# a. case-insensitive filesystem and change case of dir
887
# b. move directory after the fact (if the source used to be
888
# a directory, but now doesn't exist in the working tree
889
# and the target is an existing directory, just rename it)
890
if (not tree.case_sensitive
891
and rel_names[0].lower() == rel_names[1].lower()):
892
into_existing = False
895
# 'fix' the case of a potential 'from'
896
from_id = tree.path2id(
897
tree.get_canonical_inventory_path(rel_names[0]))
898
if (not osutils.lexists(names_list[0]) and
899
from_id and inv.get_file_kind(from_id) == "directory"):
900
into_existing = False
903
# move into existing directory
904
# All entries reference existing inventory items, so fix them up
905
# for cicp file-systems.
906
rel_names = tree.get_canonical_inventory_paths(rel_names)
907
for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
909
self.outf.write("%s => %s\n" % (src, dest))
911
if len(names_list) != 2:
912
raise errors.BzrCommandError('to mv multiple files the'
913
' destination must be a versioned'
916
# for cicp file-systems: the src references an existing inventory
918
src = tree.get_canonical_inventory_path(rel_names[0])
919
# Find the canonical version of the destination: In all cases, the
920
# parent of the target must be in the inventory, so we fetch the
921
# canonical version from there (we do not always *use* the
922
# canonicalized tail portion - we may be attempting to rename the
924
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
925
dest_parent = osutils.dirname(canon_dest)
926
spec_tail = osutils.basename(rel_names[1])
927
# For a CICP file-system, we need to avoid creating 2 inventory
928
# entries that differ only by case. So regardless of the case
929
# we *want* to use (ie, specified by the user or the file-system),
930
# we must always choose to use the case of any existing inventory
931
# items. The only exception to this is when we are attempting a
932
# case-only rename (ie, canonical versions of src and dest are
934
dest_id = tree.path2id(canon_dest)
935
if dest_id is None or tree.path2id(src) == dest_id:
936
# No existing item we care about, so work out what case we
937
# are actually going to use.
939
# If 'after' is specified, the tail must refer to a file on disk.
941
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
943
# pathjoin with an empty tail adds a slash, which breaks
945
dest_parent_fq = tree.basedir
947
dest_tail = osutils.canonical_relpath(
949
osutils.pathjoin(dest_parent_fq, spec_tail))
951
# not 'after', so case as specified is used
952
dest_tail = spec_tail
954
# Use the existing item so 'mv' fails with AlreadyVersioned.
955
dest_tail = os.path.basename(canon_dest)
956
dest = osutils.pathjoin(dest_parent, dest_tail)
957
mutter("attempting to move %s => %s", src, dest)
958
tree.rename_one(src, dest, after=after)
960
self.outf.write("%s => %s\n" % (src, dest))
963
class cmd_pull(Command):
964
__doc__ = """Turn this branch into a mirror of another branch.
966
By default, this command only works on branches that have not diverged.
967
Branches are considered diverged if the destination branch's most recent
968
commit is one that has not been merged (directly or indirectly) into the
971
If branches have diverged, you can use 'bzr merge' to integrate the changes
972
from one into the other. Once one branch has merged, the other should
973
be able to pull it again.
975
If you want to replace your local changes and just want your branch to
976
match the remote one, use pull --overwrite. This will work even if the two
977
branches have diverged.
979
If there is no default location set, the first pull will set it (use
980
--no-remember to avoid setting it). After that, you can omit the
981
location to use the default. To change the default, use --remember. The
982
value will only be saved if the remote location can be accessed.
984
Note: The location can be specified either in the form of a branch,
985
or in the form of a path to a file containing a merge directive generated
989
_see_also = ['push', 'update', 'status-flags', 'send']
990
takes_options = ['remember', 'overwrite', 'revision',
991
custom_help('verbose',
992
help='Show logs of pulled revisions.'),
993
custom_help('directory',
994
help='Branch to pull into, '
995
'rather than the one containing the working directory.'),
997
help="Perform a local pull in a bound "
998
"branch. Local pulls are not applied to "
1002
help="Show base revision text in conflicts.")
1004
takes_args = ['location?']
1005
encoding_type = 'replace'
1007
def run(self, location=None, remember=None, overwrite=False,
1008
revision=None, verbose=False,
1009
directory=None, local=False,
1011
# FIXME: too much stuff is in the command class
1014
if directory is None:
1017
tree_to = WorkingTree.open_containing(directory)[0]
1018
branch_to = tree_to.branch
1019
self.add_cleanup(tree_to.lock_write().unlock)
1020
except errors.NoWorkingTree:
1022
branch_to = Branch.open_containing(directory)[0]
1023
self.add_cleanup(branch_to.lock_write().unlock)
1025
if tree_to is None and show_base:
1026
raise errors.BzrCommandError("Need working tree for --show-base.")
1028
if local and not branch_to.get_bound_location():
1029
raise errors.LocalRequiresBoundBranch()
1031
possible_transports = []
1032
if location is not None:
1034
mergeable = bundle.read_mergeable_from_url(location,
1035
possible_transports=possible_transports)
1036
except errors.NotABundle:
1039
stored_loc = branch_to.get_parent()
1040
if location is None:
1041
if stored_loc is None:
1042
raise errors.BzrCommandError("No pull location known or"
1045
display_url = urlutils.unescape_for_display(stored_loc,
1048
self.outf.write("Using saved parent location: %s\n" % display_url)
1049
location = stored_loc
1051
revision = _get_one_revision('pull', revision)
1052
if mergeable is not None:
1053
if revision is not None:
1054
raise errors.BzrCommandError(
1055
'Cannot use -r with merge directives or bundles')
1056
mergeable.install_revisions(branch_to.repository)
1057
base_revision_id, revision_id, verified = \
1058
mergeable.get_merge_request(branch_to.repository)
1059
branch_from = branch_to
1061
branch_from = Branch.open(location,
1062
possible_transports=possible_transports)
1063
self.add_cleanup(branch_from.lock_read().unlock)
1064
# Remembers if asked explicitly or no previous location is set
1066
or (remember is None and branch_to.get_parent() is None)):
1067
branch_to.set_parent(branch_from.base)
1069
if revision is not None:
1070
revision_id = revision.as_revision_id(branch_from)
1072
if tree_to is not None:
1073
view_info = _get_view_info_for_change_reporter(tree_to)
1074
change_reporter = delta._ChangeReporter(
1075
unversioned_filter=tree_to.is_ignored,
1076
view_info=view_info)
1077
result = tree_to.pull(
1078
branch_from, overwrite, revision_id, change_reporter,
1079
local=local, show_base=show_base)
1081
result = branch_to.pull(
1082
branch_from, overwrite, revision_id, local=local)
1084
result.report(self.outf)
1085
if verbose and result.old_revid != result.new_revid:
1086
log.show_branch_change(
1087
branch_to, self.outf, result.old_revno,
1089
if getattr(result, 'tag_conflicts', None):
1095
class cmd_push(Command):
1096
__doc__ = """Update a mirror of this branch.
1098
The target branch will not have its working tree populated because this
1099
is both expensive, and is not supported on remote file systems.
1101
Some smart servers or protocols *may* put the working tree in place in
1104
This command only works on branches that have not diverged. Branches are
1105
considered diverged if the destination branch's most recent commit is one
1106
that has not been merged (directly or indirectly) by the source branch.
1108
If branches have diverged, you can use 'bzr push --overwrite' to replace
1109
the other branch completely, discarding its unmerged changes.
1111
If you want to ensure you have the different changes in the other branch,
1112
do a merge (see bzr help merge) from the other branch, and commit that.
1113
After that you will be able to do a push without '--overwrite'.
1115
If there is no default push location set, the first push will set it (use
1116
--no-remember to avoid setting it). After that, you can omit the
1117
location to use the default. To change the default, use --remember. The
1118
value will only be saved if the remote location can be accessed.
1121
_see_also = ['pull', 'update', 'working-trees']
1122
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
1123
Option('create-prefix',
1124
help='Create the path leading up to the branch '
1125
'if it does not already exist.'),
1126
custom_help('directory',
1127
help='Branch to push from, '
1128
'rather than the one containing the working directory.'),
1129
Option('use-existing-dir',
1130
help='By default push will fail if the target'
1131
' directory exists, but does not already'
1132
' have a control directory. This flag will'
1133
' allow push to proceed.'),
1135
help='Create a stacked branch that references the public location '
1136
'of the parent branch.'),
1137
Option('stacked-on',
1138
help='Create a stacked branch that refers to another branch '
1139
'for the commit history. Only the work not present in the '
1140
'referenced branch is included in the branch created.',
1143
help='Refuse to push if there are uncommitted changes in'
1144
' the working tree, --no-strict disables the check.'),
1146
help="Don't populate the working tree, even for protocols"
1147
" that support it."),
1149
takes_args = ['location?']
1150
encoding_type = 'replace'
1152
def run(self, location=None, remember=None, overwrite=False,
1153
create_prefix=False, verbose=False, revision=None,
1154
use_existing_dir=False, directory=None, stacked_on=None,
1155
stacked=False, strict=None, no_tree=False):
1156
from bzrlib.push import _show_push_branch
1158
if directory is None:
1160
# Get the source branch
1162
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1163
# Get the tip's revision_id
1164
revision = _get_one_revision('push', revision)
1165
if revision is not None:
1166
revision_id = revision.in_history(br_from).rev_id
1169
if tree is not None and revision_id is None:
1170
tree.check_changed_or_out_of_date(
1171
strict, 'push_strict',
1172
more_error='Use --no-strict to force the push.',
1173
more_warning='Uncommitted changes will not be pushed.')
1174
# Get the stacked_on branch, if any
1175
if stacked_on is not None:
1176
stacked_on = urlutils.normalize_url(stacked_on)
1178
parent_url = br_from.get_parent()
1180
parent = Branch.open(parent_url)
1181
stacked_on = parent.get_public_branch()
1183
# I considered excluding non-http url's here, thus forcing
1184
# 'public' branches only, but that only works for some
1185
# users, so it's best to just depend on the user spotting an
1186
# error by the feedback given to them. RBC 20080227.
1187
stacked_on = parent_url
1189
raise errors.BzrCommandError(
1190
"Could not determine branch to refer to.")
1192
# Get the destination location
1193
if location is None:
1194
stored_loc = br_from.get_push_location()
1195
if stored_loc is None:
1196
raise errors.BzrCommandError(
1197
"No push location known or specified.")
1199
display_url = urlutils.unescape_for_display(stored_loc,
1201
note("Using saved push location: %s" % display_url)
1202
location = stored_loc
1204
_show_push_branch(br_from, revision_id, location, self.outf,
1205
verbose=verbose, overwrite=overwrite, remember=remember,
1206
stacked_on=stacked_on, create_prefix=create_prefix,
1207
use_existing_dir=use_existing_dir, no_tree=no_tree)
1210
class cmd_branch(Command):
1211
__doc__ = """Create a new branch that is a copy of an existing branch.
1213
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1214
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1215
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
1216
is derived from the FROM_LOCATION by stripping a leading scheme or drive
1217
identifier, if any. For example, "branch lp:foo-bar" will attempt to
1220
To retrieve the branch as of a particular revision, supply the --revision
1221
parameter, as in "branch foo/bar -r 5".
1223
The synonyms 'clone' and 'get' for this command are deprecated.
1226
_see_also = ['checkout']
1227
takes_args = ['from_location', 'to_location?']
1228
takes_options = ['revision',
1229
Option('hardlink', help='Hard-link working tree files where possible.'),
1230
Option('files-from', type=str,
1231
help="Get file contents from this tree."),
1233
help="Create a branch without a working-tree."),
1235
help="Switch the checkout in the current directory "
1236
"to the new branch."),
1238
help='Create a stacked branch referring to the source branch. '
1239
'The new branch will depend on the availability of the source '
1240
'branch for all operations.'),
1241
Option('standalone',
1242
help='Do not use a shared repository, even if available.'),
1243
Option('use-existing-dir',
1244
help='By default branch will fail if the target'
1245
' directory exists, but does not already'
1246
' have a control directory. This flag will'
1247
' allow branch to proceed.'),
1249
help="Bind new branch to from location."),
1251
aliases = ['get', 'clone']
1253
def run(self, from_location, to_location=None, revision=None,
1254
hardlink=False, stacked=False, standalone=False, no_tree=False,
1255
use_existing_dir=False, switch=False, bind=False,
1257
from bzrlib import switch as _mod_switch
1258
from bzrlib.tag import _merge_tags_if_possible
1259
if self.invoked_as in ['get', 'clone']:
1260
ui.ui_factory.show_user_warning(
1261
'deprecated_command',
1262
deprecated_name=self.invoked_as,
1263
recommended_name='branch',
1264
deprecated_in_version='2.4')
1265
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1267
if not (hardlink or files_from):
1268
# accelerator_tree is usually slower because you have to read N
1269
# files (no readahead, lots of seeks, etc), but allow the user to
1270
# explicitly request it
1271
accelerator_tree = None
1272
if files_from is not None and files_from != from_location:
1273
accelerator_tree = WorkingTree.open(files_from)
1274
revision = _get_one_revision('branch', revision)
1275
self.add_cleanup(br_from.lock_read().unlock)
1276
if revision is not None:
1277
revision_id = revision.as_revision_id(br_from)
1279
# FIXME - wt.last_revision, fallback to branch, fall back to
1280
# None or perhaps NULL_REVISION to mean copy nothing
1282
revision_id = br_from.last_revision()
1283
if to_location is None:
1284
to_location = urlutils.derive_to_location(from_location)
1285
to_transport = transport.get_transport(to_location)
1287
to_transport.mkdir('.')
1288
except errors.FileExists:
1289
if not use_existing_dir:
1290
raise errors.BzrCommandError('Target directory "%s" '
1291
'already exists.' % to_location)
1294
bzrdir.BzrDir.open_from_transport(to_transport)
1295
except errors.NotBranchError:
1298
raise errors.AlreadyBranchError(to_location)
1299
except errors.NoSuchFile:
1300
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1303
# preserve whatever source format we have.
1304
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1305
possible_transports=[to_transport],
1306
accelerator_tree=accelerator_tree,
1307
hardlink=hardlink, stacked=stacked,
1308
force_new_repo=standalone,
1309
create_tree_if_local=not no_tree,
1310
source_branch=br_from)
1311
branch = dir.open_branch()
1312
except errors.NoSuchRevision:
1313
to_transport.delete_tree('.')
1314
msg = "The branch %s has no revision %s." % (from_location,
1316
raise errors.BzrCommandError(msg)
1317
_merge_tags_if_possible(br_from, branch)
1318
# If the source branch is stacked, the new branch may
1319
# be stacked whether we asked for that explicitly or not.
1320
# We therefore need a try/except here and not just 'if stacked:'
1322
note('Created new stacked branch referring to %s.' %
1323
branch.get_stacked_on_url())
1324
except (errors.NotStacked, errors.UnstackableBranchFormat,
1325
errors.UnstackableRepositoryFormat), e:
1326
note('Branched %d revision(s).' % branch.revno())
1328
# Bind to the parent
1329
parent_branch = Branch.open(from_location)
1330
branch.bind(parent_branch)
1331
note('New branch bound to %s' % from_location)
1333
# Switch to the new branch
1334
wt, _ = WorkingTree.open_containing('.')
1335
_mod_switch.switch(wt.bzrdir, branch)
1336
note('Switched to branch: %s',
1337
urlutils.unescape_for_display(branch.base, 'utf-8'))
1340
class cmd_branches(Command):
1341
__doc__ = """List the branches available at the current location.
1343
This command will print the names of all the branches at the current location.
1346
takes_args = ['location?']
1348
def run(self, location="."):
1349
dir = bzrdir.BzrDir.open_containing(location)[0]
1350
for branch in dir.list_branches():
1351
if branch.name is None:
1352
self.outf.write(" (default)\n")
1354
self.outf.write(" %s\n" % branch.name.encode(self.outf.encoding))
1357
class cmd_checkout(Command):
1358
__doc__ = """Create a new checkout of an existing branch.
1360
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1361
the branch found in '.'. This is useful if you have removed the working tree
1362
or if it was never created - i.e. if you pushed the branch to its current
1363
location using SFTP.
1365
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1366
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1367
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1368
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
1369
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
1372
To retrieve the branch as of a particular revision, supply the --revision
1373
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
1374
out of date [so you cannot commit] but it may be useful (i.e. to examine old
1378
_see_also = ['checkouts', 'branch']
1379
takes_args = ['branch_location?', 'to_location?']
1380
takes_options = ['revision',
1381
Option('lightweight',
1382
help="Perform a lightweight checkout. Lightweight "
1383
"checkouts depend on access to the branch for "
1384
"every operation. Normal checkouts can perform "
1385
"common operations like diff and status without "
1386
"such access, and also support local commits."
1388
Option('files-from', type=str,
1389
help="Get file contents from this tree."),
1391
help='Hard-link working tree files where possible.'
1396
def run(self, branch_location=None, to_location=None, revision=None,
1397
lightweight=False, files_from=None, hardlink=False):
1398
if branch_location is None:
1399
branch_location = osutils.getcwd()
1400
to_location = branch_location
1401
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1403
if not (hardlink or files_from):
1404
# accelerator_tree is usually slower because you have to read N
1405
# files (no readahead, lots of seeks, etc), but allow the user to
1406
# explicitly request it
1407
accelerator_tree = None
1408
revision = _get_one_revision('checkout', revision)
1409
if files_from is not None and files_from != branch_location:
1410
accelerator_tree = WorkingTree.open(files_from)
1411
if revision is not None:
1412
revision_id = revision.as_revision_id(source)
1415
if to_location is None:
1416
to_location = urlutils.derive_to_location(branch_location)
1417
# if the source and to_location are the same,
1418
# and there is no working tree,
1419
# then reconstitute a branch
1420
if (osutils.abspath(to_location) ==
1421
osutils.abspath(branch_location)):
1423
source.bzrdir.open_workingtree()
1424
except errors.NoWorkingTree:
1425
source.bzrdir.create_workingtree(revision_id)
1427
source.create_checkout(to_location, revision_id, lightweight,
1428
accelerator_tree, hardlink)
1431
class cmd_renames(Command):
1432
__doc__ = """Show list of renamed files.
1434
# TODO: Option to show renames between two historical versions.
1436
# TODO: Only show renames under dir, rather than in the whole branch.
1437
_see_also = ['status']
1438
takes_args = ['dir?']
1441
def run(self, dir=u'.'):
1442
tree = WorkingTree.open_containing(dir)[0]
1443
self.add_cleanup(tree.lock_read().unlock)
1444
new_inv = tree.inventory
1445
old_tree = tree.basis_tree()
1446
self.add_cleanup(old_tree.lock_read().unlock)
1447
old_inv = old_tree.inventory
1449
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1450
for f, paths, c, v, p, n, k, e in iterator:
1451
if paths[0] == paths[1]:
1455
renames.append(paths)
1457
for old_name, new_name in renames:
1458
self.outf.write("%s => %s\n" % (old_name, new_name))
1461
class cmd_update(Command):
1462
__doc__ = """Update a tree to have the latest code committed to its branch.
1464
This will perform a merge into the working tree, and may generate
1465
conflicts. If you have any local changes, you will still
1466
need to commit them after the update for the update to be complete.
1468
If you want to discard your local changes, you can just do a
1469
'bzr revert' instead of 'bzr commit' after the update.
1471
If you want to restore a file that has been removed locally, use
1472
'bzr revert' instead of 'bzr update'.
1474
If the tree's branch is bound to a master branch, it will also update
1475
the branch from the master.
1478
_see_also = ['pull', 'working-trees', 'status-flags']
1479
takes_args = ['dir?']
1480
takes_options = ['revision',
1482
help="Show base revision text in conflicts."),
1486
def run(self, dir='.', revision=None, show_base=None):
1487
if revision is not None and len(revision) != 1:
1488
raise errors.BzrCommandError(
1489
"bzr update --revision takes exactly one revision")
1490
tree = WorkingTree.open_containing(dir)[0]
1491
branch = tree.branch
1492
possible_transports = []
1493
master = branch.get_master_branch(
1494
possible_transports=possible_transports)
1495
if master is not None:
1496
branch_location = master.base
1499
branch_location = tree.branch.base
1500
tree.lock_tree_write()
1501
self.add_cleanup(tree.unlock)
1502
# get rid of the final '/' and be ready for display
1503
branch_location = urlutils.unescape_for_display(
1504
branch_location.rstrip('/'),
1506
existing_pending_merges = tree.get_parent_ids()[1:]
1510
# may need to fetch data into a heavyweight checkout
1511
# XXX: this may take some time, maybe we should display a
1513
old_tip = branch.update(possible_transports)
1514
if revision is not None:
1515
revision_id = revision[0].as_revision_id(branch)
1517
revision_id = branch.last_revision()
1518
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1519
revno = branch.revision_id_to_dotted_revno(revision_id)
1520
note("Tree is up to date at revision %s of branch %s" %
1521
('.'.join(map(str, revno)), branch_location))
1523
view_info = _get_view_info_for_change_reporter(tree)
1524
change_reporter = delta._ChangeReporter(
1525
unversioned_filter=tree.is_ignored,
1526
view_info=view_info)
1528
conflicts = tree.update(
1530
possible_transports=possible_transports,
1531
revision=revision_id,
1533
show_base=show_base)
1534
except errors.NoSuchRevision, e:
1535
raise errors.BzrCommandError(
1536
"branch has no revision %s\n"
1537
"bzr update --revision only works"
1538
" for a revision in the branch history"
1540
revno = tree.branch.revision_id_to_dotted_revno(
1541
_mod_revision.ensure_null(tree.last_revision()))
1542
note('Updated to revision %s of branch %s' %
1543
('.'.join(map(str, revno)), branch_location))
1544
parent_ids = tree.get_parent_ids()
1545
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1546
note('Your local commits will now show as pending merges with '
1547
"'bzr status', and can be committed with 'bzr commit'.")
1554
class cmd_info(Command):
1555
__doc__ = """Show information about a working tree, branch or repository.
1557
This command will show all known locations and formats associated to the
1558
tree, branch or repository.
1560
In verbose mode, statistical information is included with each report.
1561
To see extended statistic information, use a verbosity level of 2 or
1562
higher by specifying the verbose option multiple times, e.g. -vv.
1564
Branches and working trees will also report any missing revisions.
1568
Display information on the format and related locations:
1572
Display the above together with extended format information and
1573
basic statistics (like the number of files in the working tree and
1574
number of revisions in the branch and repository):
1578
Display the above together with number of committers to the branch:
1582
_see_also = ['revno', 'working-trees', 'repositories']
1583
takes_args = ['location?']
1584
takes_options = ['verbose']
1585
encoding_type = 'replace'
1588
def run(self, location=None, verbose=False):
1590
noise_level = get_verbosity_level()
1593
from bzrlib.info import show_bzrdir_info
1594
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1595
verbose=noise_level, outfile=self.outf)
1598
class cmd_remove(Command):
1599
__doc__ = """Remove files or directories.
1601
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1602
delete them if they can easily be recovered using revert otherwise they
1603
will be backed up (adding an extention of the form .~#~). If no options or
1604
parameters are given Bazaar will scan for files that are being tracked by
1605
Bazaar but missing in your tree and stop tracking them for you.
1607
takes_args = ['file*']
1608
takes_options = ['verbose',
1609
Option('new', help='Only remove files that have never been committed.'),
1610
RegistryOption.from_kwargs('file-deletion-strategy',
1611
'The file deletion mode to be used.',
1612
title='Deletion Strategy', value_switches=True, enum_switch=False,
1613
safe='Backup changed files (default).',
1614
keep='Delete from bzr but leave the working copy.',
1615
no_backup='Don\'t backup changed files.',
1616
force='Delete all the specified files, even if they can not be '
1617
'recovered and even if they are non-empty directories. '
1618
'(deprecated, use no-backup)')]
1619
aliases = ['rm', 'del']
1620
encoding_type = 'replace'
1622
def run(self, file_list, verbose=False, new=False,
1623
file_deletion_strategy='safe'):
1624
if file_deletion_strategy == 'force':
1625
note("(The --force option is deprecated, rather use --no-backup "
1627
file_deletion_strategy = 'no-backup'
1629
tree, file_list = WorkingTree.open_containing_paths(file_list)
1631
if file_list is not None:
1632
file_list = [f for f in file_list]
1634
self.add_cleanup(tree.lock_write().unlock)
1635
# Heuristics should probably all move into tree.remove_smart or
1638
added = tree.changes_from(tree.basis_tree(),
1639
specific_files=file_list).added
1640
file_list = sorted([f[0] for f in added], reverse=True)
1641
if len(file_list) == 0:
1642
raise errors.BzrCommandError('No matching files.')
1643
elif file_list is None:
1644
# missing files show up in iter_changes(basis) as
1645
# versioned-with-no-kind.
1647
for change in tree.iter_changes(tree.basis_tree()):
1648
# Find paths in the working tree that have no kind:
1649
if change[1][1] is not None and change[6][1] is None:
1650
missing.append(change[1][1])
1651
file_list = sorted(missing, reverse=True)
1652
file_deletion_strategy = 'keep'
1653
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1654
keep_files=file_deletion_strategy=='keep',
1655
force=(file_deletion_strategy=='no-backup'))
1658
class cmd_file_id(Command):
1659
__doc__ = """Print file_id of a particular file or directory.
1661
The file_id is assigned when the file is first added and remains the
1662
same through all revisions where the file exists, even when it is
1667
_see_also = ['inventory', 'ls']
1668
takes_args = ['filename']
1671
def run(self, filename):
1672
tree, relpath = WorkingTree.open_containing(filename)
1673
i = tree.path2id(relpath)
1675
raise errors.NotVersionedError(filename)
1677
self.outf.write(i + '\n')
1680
class cmd_file_path(Command):
1681
__doc__ = """Print path of file_ids to a file or directory.
1683
This prints one line for each directory down to the target,
1684
starting at the branch root.
1688
takes_args = ['filename']
1691
def run(self, filename):
1692
tree, relpath = WorkingTree.open_containing(filename)
1693
fid = tree.path2id(relpath)
1695
raise errors.NotVersionedError(filename)
1696
segments = osutils.splitpath(relpath)
1697
for pos in range(1, len(segments) + 1):
1698
path = osutils.joinpath(segments[:pos])
1699
self.outf.write("%s\n" % tree.path2id(path))
1702
class cmd_reconcile(Command):
1703
__doc__ = """Reconcile bzr metadata in a branch.
1705
This can correct data mismatches that may have been caused by
1706
previous ghost operations or bzr upgrades. You should only
1707
need to run this command if 'bzr check' or a bzr developer
1708
advises you to run it.
1710
If a second branch is provided, cross-branch reconciliation is
1711
also attempted, which will check that data like the tree root
1712
id which was not present in very early bzr versions is represented
1713
correctly in both branches.
1715
At the same time it is run it may recompress data resulting in
1716
a potential saving in disk space or performance gain.
1718
The branch *MUST* be on a listable system such as local disk or sftp.
1721
_see_also = ['check']
1722
takes_args = ['branch?']
1724
Option('canonicalize-chks',
1725
help='Make sure CHKs are in canonical form (repairs '
1730
def run(self, branch=".", canonicalize_chks=False):
1731
from bzrlib.reconcile import reconcile
1732
dir = bzrdir.BzrDir.open(branch)
1733
reconcile(dir, canonicalize_chks=canonicalize_chks)
1736
class cmd_revision_history(Command):
1737
__doc__ = """Display the list of revision ids on a branch."""
1740
takes_args = ['location?']
1745
def run(self, location="."):
1746
branch = Branch.open_containing(location)[0]
1747
for revid in branch.revision_history():
1748
self.outf.write(revid)
1749
self.outf.write('\n')
1752
class cmd_ancestry(Command):
1753
__doc__ = """List all revisions merged into this branch."""
1755
_see_also = ['log', 'revision-history']
1756
takes_args = ['location?']
1761
def run(self, location="."):
1763
wt = WorkingTree.open_containing(location)[0]
1764
except errors.NoWorkingTree:
1765
b = Branch.open(location)
1766
last_revision = b.last_revision()
1769
last_revision = wt.last_revision()
1771
self.add_cleanup(b.repository.lock_read().unlock)
1772
graph = b.repository.get_graph()
1773
revisions = [revid for revid, parents in
1774
graph.iter_ancestry([last_revision])]
1775
for revision_id in reversed(revisions):
1776
if _mod_revision.is_null(revision_id):
1778
self.outf.write(revision_id + '\n')
1781
class cmd_init(Command):
1782
__doc__ = """Make a directory into a versioned branch.
1784
Use this to create an empty branch, or before importing an
1787
If there is a repository in a parent directory of the location, then
1788
the history of the branch will be stored in the repository. Otherwise
1789
init creates a standalone branch which carries its own history
1790
in the .bzr directory.
1792
If there is already a branch at the location but it has no working tree,
1793
the tree can be populated with 'bzr checkout'.
1795
Recipe for importing a tree of files::
1801
bzr commit -m "imported project"
1804
_see_also = ['init-repository', 'branch', 'checkout']
1805
takes_args = ['location?']
1807
Option('create-prefix',
1808
help='Create the path leading up to the branch '
1809
'if it does not already exist.'),
1810
RegistryOption('format',
1811
help='Specify a format for this branch. '
1812
'See "help formats".',
1813
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1814
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1815
value_switches=True,
1816
title="Branch format",
1818
Option('append-revisions-only',
1819
help='Never change revnos or the existing log.'
1820
' Append revisions to it only.'),
1822
'Create a branch without a working tree.')
1824
def run(self, location=None, format=None, append_revisions_only=False,
1825
create_prefix=False, no_tree=False):
1827
format = bzrdir.format_registry.make_bzrdir('default')
1828
if location is None:
1831
to_transport = transport.get_transport(location)
1833
# The path has to exist to initialize a
1834
# branch inside of it.
1835
# Just using os.mkdir, since I don't
1836
# believe that we want to create a bunch of
1837
# locations if the user supplies an extended path
1839
to_transport.ensure_base()
1840
except errors.NoSuchFile:
1841
if not create_prefix:
1842
raise errors.BzrCommandError("Parent directory of %s"
1844
"\nYou may supply --create-prefix to create all"
1845
" leading parent directories."
1847
to_transport.create_prefix()
1850
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1851
except errors.NotBranchError:
1852
# really a NotBzrDir error...
1853
create_branch = bzrdir.BzrDir.create_branch_convenience
1855
force_new_tree = False
1857
force_new_tree = None
1858
branch = create_branch(to_transport.base, format=format,
1859
possible_transports=[to_transport],
1860
force_new_tree=force_new_tree)
1861
a_bzrdir = branch.bzrdir
1863
from bzrlib.transport.local import LocalTransport
1864
if a_bzrdir.has_branch():
1865
if (isinstance(to_transport, LocalTransport)
1866
and not a_bzrdir.has_workingtree()):
1867
raise errors.BranchExistsWithoutWorkingTree(location)
1868
raise errors.AlreadyBranchError(location)
1869
branch = a_bzrdir.create_branch()
1871
a_bzrdir.create_workingtree()
1872
if append_revisions_only:
1874
branch.set_append_revisions_only(True)
1875
except errors.UpgradeRequired:
1876
raise errors.BzrCommandError('This branch format cannot be set'
1877
' to append-revisions-only. Try --default.')
1879
from bzrlib.info import describe_layout, describe_format
1881
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1882
except (errors.NoWorkingTree, errors.NotLocalUrl):
1884
repository = branch.repository
1885
layout = describe_layout(repository, branch, tree).lower()
1886
format = describe_format(a_bzrdir, repository, branch, tree)
1887
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1888
if repository.is_shared():
1889
#XXX: maybe this can be refactored into transport.path_or_url()
1890
url = repository.bzrdir.root_transport.external_url()
1892
url = urlutils.local_path_from_url(url)
1893
except errors.InvalidURL:
1895
self.outf.write("Using shared repository: %s\n" % url)
1898
class cmd_init_repository(Command):
1899
__doc__ = """Create a shared repository for branches to share storage space.
1901
New branches created under the repository directory will store their
1902
revisions in the repository, not in the branch directory. For branches
1903
with shared history, this reduces the amount of storage needed and
1904
speeds up the creation of new branches.
1906
If the --no-trees option is given then the branches in the repository
1907
will not have working trees by default. They will still exist as
1908
directories on disk, but they will not have separate copies of the
1909
files at a certain revision. This can be useful for repositories that
1910
store branches which are interacted with through checkouts or remote
1911
branches, such as on a server.
1914
Create a shared repository holding just branches::
1916
bzr init-repo --no-trees repo
1919
Make a lightweight checkout elsewhere::
1921
bzr checkout --lightweight repo/trunk trunk-checkout
1926
_see_also = ['init', 'branch', 'checkout', 'repositories']
1927
takes_args = ["location"]
1928
takes_options = [RegistryOption('format',
1929
help='Specify a format for this repository. See'
1930
' "bzr help formats" for details.',
1931
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1932
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1933
value_switches=True, title='Repository format'),
1935
help='Branches in the repository will default to'
1936
' not having a working tree.'),
1938
aliases = ["init-repo"]
1940
def run(self, location, format=None, no_trees=False):
1942
format = bzrdir.format_registry.make_bzrdir('default')
1944
if location is None:
1947
to_transport = transport.get_transport(location)
1948
to_transport.ensure_base()
1950
newdir = format.initialize_on_transport(to_transport)
1951
repo = newdir.create_repository(shared=True)
1952
repo.set_make_working_trees(not no_trees)
1954
from bzrlib.info import show_bzrdir_info
1955
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1958
class cmd_diff(Command):
1959
__doc__ = """Show differences in the working tree, between revisions or branches.
1961
If no arguments are given, all changes for the current tree are listed.
1962
If files are given, only the changes in those files are listed.
1963
Remote and multiple branches can be compared by using the --old and
1964
--new options. If not provided, the default for both is derived from
1965
the first argument, if any, or the current tree if no arguments are
1968
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1969
produces patches suitable for "patch -p1".
1971
Note that when using the -r argument with a range of revisions, the
1972
differences are computed between the two specified revisions. That
1973
is, the command does not show the changes introduced by the first
1974
revision in the range. This differs from the interpretation of
1975
revision ranges used by "bzr log" which includes the first revision
1980
2 - unrepresentable changes
1985
Shows the difference in the working tree versus the last commit::
1989
Difference between the working tree and revision 1::
1993
Difference between revision 3 and revision 1::
1997
Difference between revision 3 and revision 1 for branch xxx::
2001
The changes introduced by revision 2 (equivalent to -r1..2)::
2005
To see the changes introduced by revision X::
2009
Note that in the case of a merge, the -c option shows the changes
2010
compared to the left hand parent. To see the changes against
2011
another parent, use::
2013
bzr diff -r<chosen_parent>..X
2015
The changes between the current revision and the previous revision
2016
(equivalent to -c-1 and -r-2..-1)
2020
Show just the differences for file NEWS::
2024
Show the differences in working tree xxx for file NEWS::
2028
Show the differences from branch xxx to this working tree:
2032
Show the differences between two branches for file NEWS::
2034
bzr diff --old xxx --new yyy NEWS
2036
Same as 'bzr diff' but prefix paths with old/ and new/::
2038
bzr diff --prefix old/:new/
2040
Show the differences using a custom diff program with options::
2042
bzr diff --using /usr/bin/diff --diff-options -wu
2044
_see_also = ['status']
2045
takes_args = ['file*']
2047
Option('diff-options', type=str,
2048
help='Pass these options to the external diff program.'),
2049
Option('prefix', type=str,
2051
help='Set prefixes added to old and new filenames, as '
2052
'two values separated by a colon. (eg "old/:new/").'),
2054
help='Branch/tree to compare from.',
2058
help='Branch/tree to compare to.',
2064
help='Use this command to compare files.',
2067
RegistryOption('format',
2069
help='Diff format to use.',
2070
lazy_registry=('bzrlib.diff', 'format_registry'),
2071
title='Diff format'),
2073
aliases = ['di', 'dif']
2074
encoding_type = 'exact'
2077
def run(self, revision=None, file_list=None, diff_options=None,
2078
prefix=None, old=None, new=None, using=None, format=None):
2079
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2082
if (prefix is None) or (prefix == '0'):
2090
old_label, new_label = prefix.split(":")
2092
raise errors.BzrCommandError(
2093
'--prefix expects two values separated by a colon'
2094
' (eg "old/:new/")')
2096
if revision and len(revision) > 2:
2097
raise errors.BzrCommandError('bzr diff --revision takes exactly'
2098
' one or two revision specifiers')
2100
if using is not None and format is not None:
2101
raise errors.BzrCommandError('--using and --format are mutually '
2104
(old_tree, new_tree,
2105
old_branch, new_branch,
2106
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
2107
file_list, revision, old, new, self.add_cleanup, apply_view=True)
2108
# GNU diff on Windows uses ANSI encoding for filenames
2109
path_encoding = osutils.get_diff_header_encoding()
2110
return show_diff_trees(old_tree, new_tree, sys.stdout,
2111
specific_files=specific_files,
2112
external_diff_options=diff_options,
2113
old_label=old_label, new_label=new_label,
2114
extra_trees=extra_trees,
2115
path_encoding=path_encoding,
2120
class cmd_deleted(Command):
2121
__doc__ = """List files deleted in the working tree.
2123
# TODO: Show files deleted since a previous revision, or
2124
# between two revisions.
2125
# TODO: Much more efficient way to do this: read in new
2126
# directories with readdir, rather than stating each one. Same
2127
# level of effort but possibly much less IO. (Or possibly not,
2128
# if the directories are very large...)
2129
_see_also = ['status', 'ls']
2130
takes_options = ['directory', 'show-ids']
2133
def run(self, show_ids=False, directory=u'.'):
2134
tree = WorkingTree.open_containing(directory)[0]
2135
self.add_cleanup(tree.lock_read().unlock)
2136
old = tree.basis_tree()
2137
self.add_cleanup(old.lock_read().unlock)
2138
for path, ie in old.inventory.iter_entries():
2139
if not tree.has_id(ie.file_id):
2140
self.outf.write(path)
2142
self.outf.write(' ')
2143
self.outf.write(ie.file_id)
2144
self.outf.write('\n')
2147
class cmd_modified(Command):
2148
__doc__ = """List files modified in working tree.
2152
_see_also = ['status', 'ls']
2153
takes_options = ['directory', 'null']
2156
def run(self, null=False, directory=u'.'):
2157
tree = WorkingTree.open_containing(directory)[0]
2158
self.add_cleanup(tree.lock_read().unlock)
2159
td = tree.changes_from(tree.basis_tree())
2161
for path, id, kind, text_modified, meta_modified in td.modified:
2163
self.outf.write(path + '\0')
2165
self.outf.write(osutils.quotefn(path) + '\n')
2168
class cmd_added(Command):
2169
__doc__ = """List files added in working tree.
2173
_see_also = ['status', 'ls']
2174
takes_options = ['directory', 'null']
2177
def run(self, null=False, directory=u'.'):
2178
wt = WorkingTree.open_containing(directory)[0]
2179
self.add_cleanup(wt.lock_read().unlock)
2180
basis = wt.basis_tree()
2181
self.add_cleanup(basis.lock_read().unlock)
2182
basis_inv = basis.inventory
2185
if basis_inv.has_id(file_id):
2187
if inv.is_root(file_id) and len(basis_inv) == 0:
2189
path = inv.id2path(file_id)
2190
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2193
self.outf.write(path + '\0')
2195
self.outf.write(osutils.quotefn(path) + '\n')
2198
class cmd_root(Command):
2199
__doc__ = """Show the tree root directory.
2201
The root is the nearest enclosing directory with a .bzr control
2204
takes_args = ['filename?']
2206
def run(self, filename=None):
2207
"""Print the branch root."""
2208
tree = WorkingTree.open_containing(filename)[0]
2209
self.outf.write(tree.basedir + '\n')
2212
def _parse_limit(limitstring):
2214
return int(limitstring)
2216
msg = "The limit argument must be an integer."
2217
raise errors.BzrCommandError(msg)
2220
def _parse_levels(s):
2224
msg = "The levels argument must be an integer."
2225
raise errors.BzrCommandError(msg)
2228
class cmd_log(Command):
2229
__doc__ = """Show historical log for a branch or subset of a branch.
2231
log is bzr's default tool for exploring the history of a branch.
2232
The branch to use is taken from the first parameter. If no parameters
2233
are given, the branch containing the working directory is logged.
2234
Here are some simple examples::
2236
bzr log log the current branch
2237
bzr log foo.py log a file in its branch
2238
bzr log http://server/branch log a branch on a server
2240
The filtering, ordering and information shown for each revision can
2241
be controlled as explained below. By default, all revisions are
2242
shown sorted (topologically) so that newer revisions appear before
2243
older ones and descendants always appear before ancestors. If displayed,
2244
merged revisions are shown indented under the revision in which they
2249
The log format controls how information about each revision is
2250
displayed. The standard log formats are called ``long``, ``short``
2251
and ``line``. The default is long. See ``bzr help log-formats``
2252
for more details on log formats.
2254
The following options can be used to control what information is
2257
-l N display a maximum of N revisions
2258
-n N display N levels of revisions (0 for all, 1 for collapsed)
2259
-v display a status summary (delta) for each revision
2260
-p display a diff (patch) for each revision
2261
--show-ids display revision-ids (and file-ids), not just revnos
2263
Note that the default number of levels to display is a function of the
2264
log format. If the -n option is not used, the standard log formats show
2265
just the top level (mainline).
2267
Status summaries are shown using status flags like A, M, etc. To see
2268
the changes explained using words like ``added`` and ``modified``
2269
instead, use the -vv option.
2273
To display revisions from oldest to newest, use the --forward option.
2274
In most cases, using this option will have little impact on the total
2275
time taken to produce a log, though --forward does not incrementally
2276
display revisions like --reverse does when it can.
2278
:Revision filtering:
2280
The -r option can be used to specify what revision or range of revisions
2281
to filter against. The various forms are shown below::
2283
-rX display revision X
2284
-rX.. display revision X and later
2285
-r..Y display up to and including revision Y
2286
-rX..Y display from X to Y inclusive
2288
See ``bzr help revisionspec`` for details on how to specify X and Y.
2289
Some common examples are given below::
2291
-r-1 show just the tip
2292
-r-10.. show the last 10 mainline revisions
2293
-rsubmit:.. show what's new on this branch
2294
-rancestor:path.. show changes since the common ancestor of this
2295
branch and the one at location path
2296
-rdate:yesterday.. show changes since yesterday
2298
When logging a range of revisions using -rX..Y, log starts at
2299
revision Y and searches back in history through the primary
2300
("left-hand") parents until it finds X. When logging just the
2301
top level (using -n1), an error is reported if X is not found
2302
along the way. If multi-level logging is used (-n0), X may be
2303
a nested merge revision and the log will be truncated accordingly.
2307
If parameters are given and the first one is not a branch, the log
2308
will be filtered to show only those revisions that changed the
2309
nominated files or directories.
2311
Filenames are interpreted within their historical context. To log a
2312
deleted file, specify a revision range so that the file existed at
2313
the end or start of the range.
2315
Historical context is also important when interpreting pathnames of
2316
renamed files/directories. Consider the following example:
2318
* revision 1: add tutorial.txt
2319
* revision 2: modify tutorial.txt
2320
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2324
* ``bzr log guide.txt`` will log the file added in revision 1
2326
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2328
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2329
the original file in revision 2.
2331
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2332
was no file called guide.txt in revision 2.
2334
Renames are always followed by log. By design, there is no need to
2335
explicitly ask for this (and no way to stop logging a file back
2336
until it was last renamed).
2340
The --match option can be used for finding revisions that match a
2341
regular expression in a commit message, committer, author or bug.
2342
Specifying the option several times will match any of the supplied
2343
expressions. --match-author, --match-bugs, --match-committer and
2344
--match-message can be used to only match a specific field.
2348
GUI tools and IDEs are often better at exploring history than command
2349
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2350
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2351
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2352
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2354
You may find it useful to add the aliases below to ``bazaar.conf``::
2358
top = log -l10 --line
2361
``bzr tip`` will then show the latest revision while ``bzr top``
2362
will show the last 10 mainline revisions. To see the details of a
2363
particular revision X, ``bzr show -rX``.
2365
If you are interested in looking deeper into a particular merge X,
2366
use ``bzr log -n0 -rX``.
2368
``bzr log -v`` on a branch with lots of history is currently
2369
very slow. A fix for this issue is currently under development.
2370
With or without that fix, it is recommended that a revision range
2371
be given when using the -v option.
2373
bzr has a generic full-text matching plugin, bzr-search, that can be
2374
used to find revisions matching user names, commit messages, etc.
2375
Among other features, this plugin can find all revisions containing
2376
a list of words but not others.
2378
When exploring non-mainline history on large projects with deep
2379
history, the performance of log can be greatly improved by installing
2380
the historycache plugin. This plugin buffers historical information
2381
trading disk space for faster speed.
2383
takes_args = ['file*']
2384
_see_also = ['log-formats', 'revisionspec']
2387
help='Show from oldest to newest.'),
2389
custom_help('verbose',
2390
help='Show files changed in each revision.'),
2394
type=bzrlib.option._parse_revision_str,
2396
help='Show just the specified revision.'
2397
' See also "help revisionspec".'),
2399
RegistryOption('authors',
2400
'What names to list as authors - first, all or committer.',
2402
lazy_registry=('bzrlib.log', 'author_list_registry'),
2406
help='Number of levels to display - 0 for all, 1 for flat.',
2408
type=_parse_levels),
2410
help='Show revisions whose message matches this '
2411
'regular expression.',
2416
help='Limit the output to the first N revisions.',
2421
help='Show changes made in each revision as a patch.'),
2422
Option('include-merges',
2423
help='Show merged revisions like --levels 0 does.'),
2424
Option('exclude-common-ancestry',
2425
help='Display only the revisions that are not part'
2426
' of both ancestries (require -rX..Y)'
2428
Option('signatures',
2429
help='Show digital signature validity'),
2432
help='Show revisions whose properties match this '
2435
ListOption('match-message',
2436
help='Show revisions whose message matches this '
2439
ListOption('match-committer',
2440
help='Show revisions whose committer matches this '
2443
ListOption('match-author',
2444
help='Show revisions whose authors match this '
2447
ListOption('match-bugs',
2448
help='Show revisions whose bugs match this '
2452
encoding_type = 'replace'
2455
def run(self, file_list=None, timezone='original',
2466
include_merges=False,
2468
exclude_common_ancestry=False,
2472
match_committer=None,
2476
from bzrlib.log import (
2478
make_log_request_dict,
2479
_get_info_for_log_files,
2481
direction = (forward and 'forward') or 'reverse'
2482
if (exclude_common_ancestry
2483
and (revision is None or len(revision) != 2)):
2484
raise errors.BzrCommandError(
2485
'--exclude-common-ancestry requires -r with two revisions')
2490
raise errors.BzrCommandError(
2491
'--levels and --include-merges are mutually exclusive')
2493
if change is not None:
2495
raise errors.RangeInChangeOption()
2496
if revision is not None:
2497
raise errors.BzrCommandError(
2498
'--revision and --change are mutually exclusive')
2503
filter_by_dir = False
2505
# find the file ids to log and check for directory filtering
2506
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2507
revision, file_list, self.add_cleanup)
2508
for relpath, file_id, kind in file_info_list:
2510
raise errors.BzrCommandError(
2511
"Path unknown at end or start of revision range: %s" %
2513
# If the relpath is the top of the tree, we log everything
2518
file_ids.append(file_id)
2519
filter_by_dir = filter_by_dir or (
2520
kind in ['directory', 'tree-reference'])
2523
# FIXME ? log the current subdir only RBC 20060203
2524
if revision is not None \
2525
and len(revision) > 0 and revision[0].get_branch():
2526
location = revision[0].get_branch()
2529
dir, relpath = bzrdir.BzrDir.open_containing(location)
2530
b = dir.open_branch()
2531
self.add_cleanup(b.lock_read().unlock)
2532
rev1, rev2 = _get_revision_range(revision, b, self.name())
2534
if b.get_config().validate_signatures_in_log():
2538
if not gpg.GPGStrategy.verify_signatures_available():
2539
raise errors.GpgmeNotInstalled(None)
2541
# Decide on the type of delta & diff filtering to use
2542
# TODO: add an --all-files option to make this configurable & consistent
2550
diff_type = 'partial'
2554
# Build the log formatter
2555
if log_format is None:
2556
log_format = log.log_formatter_registry.get_default(b)
2557
# Make a non-encoding output to include the diffs - bug 328007
2558
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2559
lf = log_format(show_ids=show_ids, to_file=self.outf,
2560
to_exact_file=unencoded_output,
2561
show_timezone=timezone,
2562
delta_format=get_verbosity_level(),
2564
show_advice=levels is None,
2565
author_list_handler=authors)
2567
# Choose the algorithm for doing the logging. It's annoying
2568
# having multiple code paths like this but necessary until
2569
# the underlying repository format is faster at generating
2570
# deltas or can provide everything we need from the indices.
2571
# The default algorithm - match-using-deltas - works for
2572
# multiple files and directories and is faster for small
2573
# amounts of history (200 revisions say). However, it's too
2574
# slow for logging a single file in a repository with deep
2575
# history, i.e. > 10K revisions. In the spirit of "do no
2576
# evil when adding features", we continue to use the
2577
# original algorithm - per-file-graph - for the "single
2578
# file that isn't a directory without showing a delta" case.
2579
partial_history = revision and b.repository._format.supports_chks
2580
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2581
or delta_type or partial_history)
2585
match_dict[''] = match
2587
match_dict['message'] = match_message
2589
match_dict['committer'] = match_committer
2591
match_dict['author'] = match_author
2593
match_dict['bugs'] = match_bugs
2595
# Build the LogRequest and execute it
2596
if len(file_ids) == 0:
2598
rqst = make_log_request_dict(
2599
direction=direction, specific_fileids=file_ids,
2600
start_revision=rev1, end_revision=rev2, limit=limit,
2601
message_search=message, delta_type=delta_type,
2602
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2603
exclude_common_ancestry=exclude_common_ancestry, match=match_dict,
2604
signature=signatures
2606
Logger(b, rqst).show(lf)
2609
def _get_revision_range(revisionspec_list, branch, command_name):
2610
"""Take the input of a revision option and turn it into a revision range.
2612
It returns RevisionInfo objects which can be used to obtain the rev_id's
2613
of the desired revisions. It does some user input validations.
2615
if revisionspec_list is None:
2618
elif len(revisionspec_list) == 1:
2619
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2620
elif len(revisionspec_list) == 2:
2621
start_spec = revisionspec_list[0]
2622
end_spec = revisionspec_list[1]
2623
if end_spec.get_branch() != start_spec.get_branch():
2624
# b is taken from revision[0].get_branch(), and
2625
# show_log will use its revision_history. Having
2626
# different branches will lead to weird behaviors.
2627
raise errors.BzrCommandError(
2628
"bzr %s doesn't accept two revisions in different"
2629
" branches." % command_name)
2630
if start_spec.spec is None:
2631
# Avoid loading all the history.
2632
rev1 = RevisionInfo(branch, None, None)
2634
rev1 = start_spec.in_history(branch)
2635
# Avoid loading all of history when we know a missing
2636
# end of range means the last revision ...
2637
if end_spec.spec is None:
2638
last_revno, last_revision_id = branch.last_revision_info()
2639
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2641
rev2 = end_spec.in_history(branch)
2643
raise errors.BzrCommandError(
2644
'bzr %s --revision takes one or two values.' % command_name)
2648
def _revision_range_to_revid_range(revision_range):
2651
if revision_range[0] is not None:
2652
rev_id1 = revision_range[0].rev_id
2653
if revision_range[1] is not None:
2654
rev_id2 = revision_range[1].rev_id
2655
return rev_id1, rev_id2
2657
def get_log_format(long=False, short=False, line=False, default='long'):
2658
log_format = default
2662
log_format = 'short'
2668
class cmd_touching_revisions(Command):
2669
__doc__ = """Return revision-ids which affected a particular file.
2671
A more user-friendly interface is "bzr log FILE".
2675
takes_args = ["filename"]
2678
def run(self, filename):
2679
tree, relpath = WorkingTree.open_containing(filename)
2680
file_id = tree.path2id(relpath)
2682
self.add_cleanup(b.lock_read().unlock)
2683
touching_revs = log.find_touching_revisions(b, file_id)
2684
for revno, revision_id, what in touching_revs:
2685
self.outf.write("%6d %s\n" % (revno, what))
2688
class cmd_ls(Command):
2689
__doc__ = """List files in a tree.
2692
_see_also = ['status', 'cat']
2693
takes_args = ['path?']
2697
Option('recursive', short_name='R',
2698
help='Recurse into subdirectories.'),
2700
help='Print paths relative to the root of the branch.'),
2701
Option('unknown', short_name='u',
2702
help='Print unknown files.'),
2703
Option('versioned', help='Print versioned files.',
2705
Option('ignored', short_name='i',
2706
help='Print ignored files.'),
2707
Option('kind', short_name='k',
2708
help='List entries of a particular kind: file, directory, symlink.',
2715
def run(self, revision=None, verbose=False,
2716
recursive=False, from_root=False,
2717
unknown=False, versioned=False, ignored=False,
2718
null=False, kind=None, show_ids=False, path=None, directory=None):
2720
if kind and kind not in ('file', 'directory', 'symlink'):
2721
raise errors.BzrCommandError('invalid kind specified')
2723
if verbose and null:
2724
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2725
all = not (unknown or versioned or ignored)
2727
selection = {'I':ignored, '?':unknown, 'V':versioned}
2733
raise errors.BzrCommandError('cannot specify both --from-root'
2736
tree, branch, relpath = \
2737
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2739
# Calculate the prefix to use
2743
prefix = relpath + '/'
2744
elif fs_path != '.' and not fs_path.endswith('/'):
2745
prefix = fs_path + '/'
2747
if revision is not None or tree is None:
2748
tree = _get_one_revision_tree('ls', revision, branch=branch)
2751
if isinstance(tree, WorkingTree) and tree.supports_views():
2752
view_files = tree.views.lookup_view()
2755
view_str = views.view_display_str(view_files)
2756
note("Ignoring files outside view. View is %s" % view_str)
2758
self.add_cleanup(tree.lock_read().unlock)
2759
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2760
from_dir=relpath, recursive=recursive):
2761
# Apply additional masking
2762
if not all and not selection[fc]:
2764
if kind is not None and fkind != kind:
2769
fullpath = osutils.pathjoin(relpath, fp)
2772
views.check_path_in_view(tree, fullpath)
2773
except errors.FileOutsideView:
2778
fp = osutils.pathjoin(prefix, fp)
2779
kindch = entry.kind_character()
2780
outstring = fp + kindch
2781
ui.ui_factory.clear_term()
2783
outstring = '%-8s %s' % (fc, outstring)
2784
if show_ids and fid is not None:
2785
outstring = "%-50s %s" % (outstring, fid)
2786
self.outf.write(outstring + '\n')
2788
self.outf.write(fp + '\0')
2791
self.outf.write(fid)
2792
self.outf.write('\0')
2800
self.outf.write('%-50s %s\n' % (outstring, my_id))
2802
self.outf.write(outstring + '\n')
2805
class cmd_unknowns(Command):
2806
__doc__ = """List unknown files.
2811
takes_options = ['directory']
2814
def run(self, directory=u'.'):
2815
for f in WorkingTree.open_containing(directory)[0].unknowns():
2816
self.outf.write(osutils.quotefn(f) + '\n')
2819
class cmd_ignore(Command):
2820
__doc__ = """Ignore specified files or patterns.
2822
See ``bzr help patterns`` for details on the syntax of patterns.
2824
If a .bzrignore file does not exist, the ignore command
2825
will create one and add the specified files or patterns to the newly
2826
created file. The ignore command will also automatically add the
2827
.bzrignore file to be versioned. Creating a .bzrignore file without
2828
the use of the ignore command will require an explicit add command.
2830
To remove patterns from the ignore list, edit the .bzrignore file.
2831
After adding, editing or deleting that file either indirectly by
2832
using this command or directly by using an editor, be sure to commit
2835
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2836
the global ignore file can be found in the application data directory as
2837
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2838
Global ignores are not touched by this command. The global ignore file
2839
can be edited directly using an editor.
2841
Patterns prefixed with '!' are exceptions to ignore patterns and take
2842
precedence over regular ignores. Such exceptions are used to specify
2843
files that should be versioned which would otherwise be ignored.
2845
Patterns prefixed with '!!' act as regular ignore patterns, but have
2846
precedence over the '!' exception patterns.
2850
* Ignore patterns containing shell wildcards must be quoted from
2853
* Ignore patterns starting with "#" act as comments in the ignore file.
2854
To ignore patterns that begin with that character, use the "RE:" prefix.
2857
Ignore the top level Makefile::
2859
bzr ignore ./Makefile
2861
Ignore .class files in all directories...::
2863
bzr ignore "*.class"
2865
...but do not ignore "special.class"::
2867
bzr ignore "!special.class"
2869
Ignore files whose name begins with the "#" character::
2873
Ignore .o files under the lib directory::
2875
bzr ignore "lib/**/*.o"
2877
Ignore .o files under the lib directory::
2879
bzr ignore "RE:lib/.*\.o"
2881
Ignore everything but the "debian" toplevel directory::
2883
bzr ignore "RE:(?!debian/).*"
2885
Ignore everything except the "local" toplevel directory,
2886
but always ignore autosave files ending in ~, even under local/::
2889
bzr ignore "!./local"
2893
_see_also = ['status', 'ignored', 'patterns']
2894
takes_args = ['name_pattern*']
2895
takes_options = ['directory',
2896
Option('default-rules',
2897
help='Display the default ignore rules that bzr uses.')
2900
def run(self, name_pattern_list=None, default_rules=None,
2902
from bzrlib import ignores
2903
if default_rules is not None:
2904
# dump the default rules and exit
2905
for pattern in ignores.USER_DEFAULTS:
2906
self.outf.write("%s\n" % pattern)
2908
if not name_pattern_list:
2909
raise errors.BzrCommandError("ignore requires at least one "
2910
"NAME_PATTERN or --default-rules.")
2911
name_pattern_list = [globbing.normalize_pattern(p)
2912
for p in name_pattern_list]
2914
for p in name_pattern_list:
2915
if not globbing.Globster.is_pattern_valid(p):
2916
bad_patterns += ('\n %s' % p)
2918
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2919
ui.ui_factory.show_error(msg)
2920
raise errors.InvalidPattern('')
2921
for name_pattern in name_pattern_list:
2922
if (name_pattern[0] == '/' or
2923
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2924
raise errors.BzrCommandError(
2925
"NAME_PATTERN should not be an absolute path")
2926
tree, relpath = WorkingTree.open_containing(directory)
2927
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2928
ignored = globbing.Globster(name_pattern_list)
2930
self.add_cleanup(tree.lock_read().unlock)
2931
for entry in tree.list_files():
2935
if ignored.match(filename):
2936
matches.append(filename)
2937
if len(matches) > 0:
2938
self.outf.write("Warning: the following files are version controlled and"
2939
" match your ignore pattern:\n%s"
2940
"\nThese files will continue to be version controlled"
2941
" unless you 'bzr remove' them.\n" % ("\n".join(matches),))
2944
class cmd_ignored(Command):
2945
__doc__ = """List ignored files and the patterns that matched them.
2947
List all the ignored files and the ignore pattern that caused the file to
2950
Alternatively, to list just the files::
2955
encoding_type = 'replace'
2956
_see_also = ['ignore', 'ls']
2957
takes_options = ['directory']
2960
def run(self, directory=u'.'):
2961
tree = WorkingTree.open_containing(directory)[0]
2962
self.add_cleanup(tree.lock_read().unlock)
2963
for path, file_class, kind, file_id, entry in tree.list_files():
2964
if file_class != 'I':
2966
## XXX: Slightly inefficient since this was already calculated
2967
pat = tree.is_ignored(path)
2968
self.outf.write('%-50s %s\n' % (path, pat))
2971
class cmd_lookup_revision(Command):
2972
__doc__ = """Lookup the revision-id from a revision-number
2975
bzr lookup-revision 33
2978
takes_args = ['revno']
2979
takes_options = ['directory']
2982
def run(self, revno, directory=u'.'):
2986
raise errors.BzrCommandError("not a valid revision-number: %r"
2988
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2989
self.outf.write("%s\n" % revid)
2992
class cmd_export(Command):
2993
__doc__ = """Export current or past revision to a destination directory or archive.
2995
If no revision is specified this exports the last committed revision.
2997
Format may be an "exporter" name, such as tar, tgz, tbz2. If none is
2998
given, try to find the format with the extension. If no extension
2999
is found exports to a directory (equivalent to --format=dir).
3001
If root is supplied, it will be used as the root directory inside
3002
container formats (tar, zip, etc). If it is not supplied it will default
3003
to the exported filename. The root option has no effect for 'dir' format.
3005
If branch is omitted then the branch containing the current working
3006
directory will be used.
3008
Note: Export of tree with non-ASCII filenames to zip is not supported.
3010
================= =========================
3011
Supported formats Autodetected by extension
3012
================= =========================
3015
tbz2 .tar.bz2, .tbz2
3018
================= =========================
3021
takes_args = ['dest', 'branch_or_subdir?']
3022
takes_options = ['directory',
3024
help="Type of file to export to.",
3027
Option('filters', help='Apply content filters to export the '
3028
'convenient form.'),
3031
help="Name of the root directory inside the exported file."),
3032
Option('per-file-timestamps',
3033
help='Set modification time of files to that of the last '
3034
'revision in which it was changed.'),
3036
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3037
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
3038
from bzrlib.export import export
3040
if branch_or_subdir is None:
3041
tree = WorkingTree.open_containing(directory)[0]
3045
b, subdir = Branch.open_containing(branch_or_subdir)
3048
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3050
export(rev_tree, dest, format, root, subdir, filtered=filters,
3051
per_file_timestamps=per_file_timestamps)
3052
except errors.NoSuchExportFormat, e:
3053
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3056
class cmd_cat(Command):
3057
__doc__ = """Write the contents of a file as of a given revision to standard output.
3059
If no revision is nominated, the last revision is used.
3061
Note: Take care to redirect standard output when using this command on a
3066
takes_options = ['directory',
3067
Option('name-from-revision', help='The path name in the old tree.'),
3068
Option('filters', help='Apply content filters to display the '
3069
'convenience form.'),
3072
takes_args = ['filename']
3073
encoding_type = 'exact'
3076
def run(self, filename, revision=None, name_from_revision=False,
3077
filters=False, directory=None):
3078
if revision is not None and len(revision) != 1:
3079
raise errors.BzrCommandError("bzr cat --revision takes exactly"
3080
" one revision specifier")
3081
tree, branch, relpath = \
3082
_open_directory_or_containing_tree_or_branch(filename, directory)
3083
self.add_cleanup(branch.lock_read().unlock)
3084
return self._run(tree, branch, relpath, filename, revision,
3085
name_from_revision, filters)
3087
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3090
tree = b.basis_tree()
3091
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3092
self.add_cleanup(rev_tree.lock_read().unlock)
3094
old_file_id = rev_tree.path2id(relpath)
3096
# TODO: Split out this code to something that generically finds the
3097
# best id for a path across one or more trees; it's like
3098
# find_ids_across_trees but restricted to find just one. -- mbp
3100
if name_from_revision:
3101
# Try in revision if requested
3102
if old_file_id is None:
3103
raise errors.BzrCommandError(
3104
"%r is not present in revision %s" % (
3105
filename, rev_tree.get_revision_id()))
3107
actual_file_id = old_file_id
3109
cur_file_id = tree.path2id(relpath)
3110
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3111
actual_file_id = cur_file_id
3112
elif old_file_id is not None:
3113
actual_file_id = old_file_id
3115
raise errors.BzrCommandError(
3116
"%r is not present in revision %s" % (
3117
filename, rev_tree.get_revision_id()))
3119
from bzrlib.filter_tree import ContentFilterTree
3120
filter_tree = ContentFilterTree(rev_tree,
3121
rev_tree._content_filter_stack)
3122
content = filter_tree.get_file_text(actual_file_id)
3124
content = rev_tree.get_file_text(actual_file_id)
3126
self.outf.write(content)
3129
class cmd_local_time_offset(Command):
3130
__doc__ = """Show the offset in seconds from GMT to local time."""
3134
self.outf.write("%s\n" % osutils.local_time_offset())
3138
class cmd_commit(Command):
3139
__doc__ = """Commit changes into a new revision.
3141
An explanatory message needs to be given for each commit. This is
3142
often done by using the --message option (getting the message from the
3143
command line) or by using the --file option (getting the message from
3144
a file). If neither of these options is given, an editor is opened for
3145
the user to enter the message. To see the changed files in the
3146
boilerplate text loaded into the editor, use the --show-diff option.
3148
By default, the entire tree is committed and the person doing the
3149
commit is assumed to be the author. These defaults can be overridden
3154
If selected files are specified, only changes to those files are
3155
committed. If a directory is specified then the directory and
3156
everything within it is committed.
3158
When excludes are given, they take precedence over selected files.
3159
For example, to commit only changes within foo, but not changes
3162
bzr commit foo -x foo/bar
3164
A selective commit after a merge is not yet supported.
3168
If the author of the change is not the same person as the committer,
3169
you can specify the author's name using the --author option. The
3170
name should be in the same format as a committer-id, e.g.
3171
"John Doe <jdoe@example.com>". If there is more than one author of
3172
the change you can specify the option multiple times, once for each
3177
A common mistake is to forget to add a new file or directory before
3178
running the commit command. The --strict option checks for unknown
3179
files and aborts the commit if any are found. More advanced pre-commit
3180
checks can be implemented by defining hooks. See ``bzr help hooks``
3185
If you accidentially commit the wrong changes or make a spelling
3186
mistake in the commit message say, you can use the uncommit command
3187
to undo it. See ``bzr help uncommit`` for details.
3189
Hooks can also be configured to run after a commit. This allows you
3190
to trigger updates to external systems like bug trackers. The --fixes
3191
option can be used to record the association between a revision and
3192
one or more bugs. See ``bzr help bugs`` for details.
3195
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
3196
takes_args = ['selected*']
3198
ListOption('exclude', type=str, short_name='x',
3199
help="Do not consider changes made to a given path."),
3200
Option('message', type=unicode,
3202
help="Description of the new revision."),
3205
help='Commit even if nothing has changed.'),
3206
Option('file', type=str,
3209
help='Take commit message from this file.'),
3211
help="Refuse to commit if there are unknown "
3212
"files in the working tree."),
3213
Option('commit-time', type=str,
3214
help="Manually set a commit time using commit date "
3215
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3216
ListOption('fixes', type=str,
3217
help="Mark a bug as being fixed by this revision "
3218
"(see \"bzr help bugs\")."),
3219
ListOption('author', type=unicode,
3220
help="Set the author's name, if it's different "
3221
"from the committer."),
3223
help="Perform a local commit in a bound "
3224
"branch. Local commits are not pushed to "
3225
"the master branch until a normal commit "
3228
Option('show-diff', short_name='p',
3229
help='When no message is supplied, show the diff along'
3230
' with the status summary in the message editor.'),
3232
help='When committing to a foreign version control '
3233
'system do not push data that can not be natively '
3236
aliases = ['ci', 'checkin']
3238
def _iter_bug_fix_urls(self, fixes, branch):
3239
default_bugtracker = None
3240
# Configure the properties for bug fixing attributes.
3241
for fixed_bug in fixes:
3242
tokens = fixed_bug.split(':')
3243
if len(tokens) == 1:
3244
if default_bugtracker is None:
3245
branch_config = branch.get_config()
3246
default_bugtracker = branch_config.get_user_option(
3248
if default_bugtracker is None:
3249
raise errors.BzrCommandError(
3250
"No tracker specified for bug %s. Use the form "
3251
"'tracker:id' or specify a default bug tracker "
3252
"using the `bugtracker` option.\nSee "
3253
"\"bzr help bugs\" for more information on this "
3254
"feature. Commit refused." % fixed_bug)
3255
tag = default_bugtracker
3257
elif len(tokens) != 2:
3258
raise errors.BzrCommandError(
3259
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3260
"See \"bzr help bugs\" for more information on this "
3261
"feature.\nCommit refused." % fixed_bug)
3263
tag, bug_id = tokens
3265
yield bugtracker.get_bug_url(tag, branch, bug_id)
3266
except errors.UnknownBugTrackerAbbreviation:
3267
raise errors.BzrCommandError(
3268
'Unrecognized bug %s. Commit refused.' % fixed_bug)
3269
except errors.MalformedBugIdentifier, e:
3270
raise errors.BzrCommandError(
3271
"%s\nCommit refused." % (str(e),))
3273
def run(self, message=None, file=None, verbose=False, selected_list=None,
3274
unchanged=False, strict=False, local=False, fixes=None,
3275
author=None, show_diff=False, exclude=None, commit_time=None,
3277
from bzrlib.errors import (
3282
from bzrlib.msgeditor import (
3283
edit_commit_message_encoded,
3284
generate_commit_message_template,
3285
make_commit_message_template_encoded,
3289
commit_stamp = offset = None
3290
if commit_time is not None:
3292
commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3293
except ValueError, e:
3294
raise errors.BzrCommandError(
3295
"Could not parse --commit-time: " + str(e))
3299
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3300
if selected_list == ['']:
3301
# workaround - commit of root of tree should be exactly the same
3302
# as just default commit in that tree, and succeed even though
3303
# selected-file merge commit is not done yet
3308
bug_property = bugtracker.encode_fixes_bug_urls(
3309
self._iter_bug_fix_urls(fixes, tree.branch))
3311
properties['bugs'] = bug_property
3313
if local and not tree.branch.get_bound_location():
3314
raise errors.LocalRequiresBoundBranch()
3316
if message is not None:
3318
file_exists = osutils.lexists(message)
3319
except UnicodeError:
3320
# The commit message contains unicode characters that can't be
3321
# represented in the filesystem encoding, so that can't be a
3326
'The commit message is a file name: "%(f)s".\n'
3327
'(use --file "%(f)s" to take commit message from that file)'
3329
ui.ui_factory.show_warning(warning_msg)
3331
message = message.replace('\r\n', '\n')
3332
message = message.replace('\r', '\n')
3334
raise errors.BzrCommandError(
3335
"please specify either --message or --file")
3337
def get_message(commit_obj):
3338
"""Callback to get commit message"""
3342
my_message = f.read().decode(osutils.get_user_encoding())
3345
elif message is not None:
3346
my_message = message
3348
# No message supplied: make one up.
3349
# text is the status of the tree
3350
text = make_commit_message_template_encoded(tree,
3351
selected_list, diff=show_diff,
3352
output_encoding=osutils.get_user_encoding())
3353
# start_message is the template generated from hooks
3354
# XXX: Warning - looks like hooks return unicode,
3355
# make_commit_message_template_encoded returns user encoding.
3356
# We probably want to be using edit_commit_message instead to
3358
my_message = set_commit_message(commit_obj)
3359
if my_message is None:
3360
start_message = generate_commit_message_template(commit_obj)
3361
my_message = edit_commit_message_encoded(text,
3362
start_message=start_message)
3363
if my_message is None:
3364
raise errors.BzrCommandError("please specify a commit"
3365
" message with either --message or --file")
3366
if my_message == "":
3367
raise errors.BzrCommandError("Empty commit message specified."
3368
" Please specify a commit message with either"
3369
" --message or --file or leave a blank message"
3370
" with --message \"\".")
3373
# The API permits a commit with a filter of [] to mean 'select nothing'
3374
# but the command line should not do that.
3375
if not selected_list:
3376
selected_list = None
3378
tree.commit(message_callback=get_message,
3379
specific_files=selected_list,
3380
allow_pointless=unchanged, strict=strict, local=local,
3381
reporter=None, verbose=verbose, revprops=properties,
3382
authors=author, timestamp=commit_stamp,
3384
exclude=tree.safe_relpath_files(exclude),
3386
except PointlessCommit:
3387
raise errors.BzrCommandError("No changes to commit."
3388
" Please 'bzr add' the files you want to commit, or use"
3389
" --unchanged to force an empty commit.")
3390
except ConflictsInTree:
3391
raise errors.BzrCommandError('Conflicts detected in working '
3392
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3394
except StrictCommitFailed:
3395
raise errors.BzrCommandError("Commit refused because there are"
3396
" unknown files in the working tree.")
3397
except errors.BoundBranchOutOfDate, e:
3398
e.extra_help = ("\n"
3399
'To commit to master branch, run update and then commit.\n'
3400
'You can also pass --local to commit to continue working '
3405
class cmd_check(Command):
3406
__doc__ = """Validate working tree structure, branch consistency and repository history.
3408
This command checks various invariants about branch and repository storage
3409
to detect data corruption or bzr bugs.
3411
The working tree and branch checks will only give output if a problem is
3412
detected. The output fields of the repository check are:
3415
This is just the number of revisions checked. It doesn't
3419
This is just the number of versionedfiles checked. It
3420
doesn't indicate a problem.
3422
unreferenced ancestors
3423
Texts that are ancestors of other texts, but
3424
are not properly referenced by the revision ancestry. This is a
3425
subtle problem that Bazaar can work around.
3428
This is the total number of unique file contents
3429
seen in the checked revisions. It does not indicate a problem.
3432
This is the total number of repeated texts seen
3433
in the checked revisions. Texts can be repeated when their file
3434
entries are modified, but the file contents are not. It does not
3437
If no restrictions are specified, all Bazaar data that is found at the given
3438
location will be checked.
3442
Check the tree and branch at 'foo'::
3444
bzr check --tree --branch foo
3446
Check only the repository at 'bar'::
3448
bzr check --repo bar
3450
Check everything at 'baz'::
3455
_see_also = ['reconcile']
3456
takes_args = ['path?']
3457
takes_options = ['verbose',
3458
Option('branch', help="Check the branch related to the"
3459
" current directory."),
3460
Option('repo', help="Check the repository related to the"
3461
" current directory."),
3462
Option('tree', help="Check the working tree related to"
3463
" the current directory.")]
3465
def run(self, path=None, verbose=False, branch=False, repo=False,
3467
from bzrlib.check import check_dwim
3470
if not branch and not repo and not tree:
3471
branch = repo = tree = True
3472
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
3475
class cmd_upgrade(Command):
3476
__doc__ = """Upgrade a repository, branch or working tree to a newer format.
3478
When the default format has changed after a major new release of
3479
Bazaar, you may be informed during certain operations that you
3480
should upgrade. Upgrading to a newer format may improve performance
3481
or make new features available. It may however limit interoperability
3482
with older repositories or with older versions of Bazaar.
3484
If you wish to upgrade to a particular format rather than the
3485
current default, that can be specified using the --format option.
3486
As a consequence, you can use the upgrade command this way to
3487
"downgrade" to an earlier format, though some conversions are
3488
a one way process (e.g. changing from the 1.x default to the
3489
2.x default) so downgrading is not always possible.
3491
A backup.bzr.~#~ directory is created at the start of the conversion
3492
process (where # is a number). By default, this is left there on
3493
completion. If the conversion fails, delete the new .bzr directory
3494
and rename this one back in its place. Use the --clean option to ask
3495
for the backup.bzr directory to be removed on successful conversion.
3496
Alternatively, you can delete it by hand if everything looks good
3499
If the location given is a shared repository, dependent branches
3500
are also converted provided the repository converts successfully.
3501
If the conversion of a branch fails, remaining branches are still
3504
For more information on upgrades, see the Bazaar Upgrade Guide,
3505
http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
3508
_see_also = ['check', 'reconcile', 'formats']
3509
takes_args = ['url?']
3511
RegistryOption('format',
3512
help='Upgrade to a specific format. See "bzr help'
3513
' formats" for details.',
3514
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3515
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3516
value_switches=True, title='Branch format'),
3518
help='Remove the backup.bzr directory if successful.'),
3520
help="Show what would be done, but don't actually do anything."),
3523
def run(self, url='.', format=None, clean=False, dry_run=False):
3524
from bzrlib.upgrade import upgrade
3525
exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3527
if len(exceptions) == 1:
3528
# Compatibility with historical behavior
3534
class cmd_whoami(Command):
3535
__doc__ = """Show or set bzr user id.
3538
Show the email of the current user::
3542
Set the current user::
3544
bzr whoami "Frank Chu <fchu@example.com>"
3546
takes_options = [ 'directory',
3548
help='Display email address only.'),
3550
help='Set identity for the current branch instead of '
3553
takes_args = ['name?']
3554
encoding_type = 'replace'
3557
def run(self, email=False, branch=False, name=None, directory=None):
3559
if directory is None:
3560
# use branch if we're inside one; otherwise global config
3562
c = Branch.open_containing(u'.')[0].get_config()
3563
except errors.NotBranchError:
3564
c = _mod_config.GlobalConfig()
3566
c = Branch.open(directory).get_config()
3568
self.outf.write(c.user_email() + '\n')
3570
self.outf.write(c.username() + '\n')
3574
raise errors.BzrCommandError("--email can only be used to display existing "
3577
# display a warning if an email address isn't included in the given name.
3579
_mod_config.extract_email_address(name)
3580
except errors.NoEmailInUsername, e:
3581
warning('"%s" does not seem to contain an email address. '
3582
'This is allowed, but not recommended.', name)
3584
# use global config unless --branch given
3586
if directory is None:
3587
c = Branch.open_containing(u'.')[0].get_config()
3589
c = Branch.open(directory).get_config()
3591
c = _mod_config.GlobalConfig()
3592
c.set_user_option('email', name)
3595
class cmd_nick(Command):
3596
__doc__ = """Print or set the branch nickname.
3598
If unset, the tree root directory name is used as the nickname.
3599
To print the current nickname, execute with no argument.
3601
Bound branches use the nickname of its master branch unless it is set
3605
_see_also = ['info']
3606
takes_args = ['nickname?']
3607
takes_options = ['directory']
3608
def run(self, nickname=None, directory=u'.'):
3609
branch = Branch.open_containing(directory)[0]
3610
if nickname is None:
3611
self.printme(branch)
3613
branch.nick = nickname
3616
def printme(self, branch):
3617
self.outf.write('%s\n' % branch.nick)
3620
class cmd_alias(Command):
3621
__doc__ = """Set/unset and display aliases.
3624
Show the current aliases::
3628
Show the alias specified for 'll'::
3632
Set an alias for 'll'::
3634
bzr alias ll="log --line -r-10..-1"
3636
To remove an alias for 'll'::
3638
bzr alias --remove ll
3641
takes_args = ['name?']
3643
Option('remove', help='Remove the alias.'),
3646
def run(self, name=None, remove=False):
3648
self.remove_alias(name)
3650
self.print_aliases()
3652
equal_pos = name.find('=')
3654
self.print_alias(name)
3656
self.set_alias(name[:equal_pos], name[equal_pos+1:])
3658
def remove_alias(self, alias_name):
3659
if alias_name is None:
3660
raise errors.BzrCommandError(
3661
'bzr alias --remove expects an alias to remove.')
3662
# If alias is not found, print something like:
3663
# unalias: foo: not found
3664
c = _mod_config.GlobalConfig()
3665
c.unset_alias(alias_name)
3668
def print_aliases(self):
3669
"""Print out the defined aliases in a similar format to bash."""
3670
aliases = _mod_config.GlobalConfig().get_aliases()
3671
for key, value in sorted(aliases.iteritems()):
3672
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3675
def print_alias(self, alias_name):
3676
from bzrlib.commands import get_alias
3677
alias = get_alias(alias_name)
3679
self.outf.write("bzr alias: %s: not found\n" % alias_name)
3682
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3684
def set_alias(self, alias_name, alias_command):
3685
"""Save the alias in the global config."""
3686
c = _mod_config.GlobalConfig()
3687
c.set_alias(alias_name, alias_command)
3690
class cmd_selftest(Command):
3691
__doc__ = """Run internal test suite.
3693
If arguments are given, they are regular expressions that say which tests
3694
should run. Tests matching any expression are run, and other tests are
3697
Alternatively if --first is given, matching tests are run first and then
3698
all other tests are run. This is useful if you have been working in a
3699
particular area, but want to make sure nothing else was broken.
3701
If --exclude is given, tests that match that regular expression are
3702
excluded, regardless of whether they match --first or not.
3704
To help catch accidential dependencies between tests, the --randomize
3705
option is useful. In most cases, the argument used is the word 'now'.
3706
Note that the seed used for the random number generator is displayed
3707
when this option is used. The seed can be explicitly passed as the
3708
argument to this option if required. This enables reproduction of the
3709
actual ordering used if and when an order sensitive problem is encountered.
3711
If --list-only is given, the tests that would be run are listed. This is
3712
useful when combined with --first, --exclude and/or --randomize to
3713
understand their impact. The test harness reports "Listed nn tests in ..."
3714
instead of "Ran nn tests in ..." when list mode is enabled.
3716
If the global option '--no-plugins' is given, plugins are not loaded
3717
before running the selftests. This has two effects: features provided or
3718
modified by plugins will not be tested, and tests provided by plugins will
3721
Tests that need working space on disk use a common temporary directory,
3722
typically inside $TMPDIR or /tmp.
3724
If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3725
into a pdb postmortem session.
3727
The --coverage=DIRNAME global option produces a report with covered code
3731
Run only tests relating to 'ignore'::
3735
Disable plugins and list tests as they're run::
3737
bzr --no-plugins selftest -v
3739
# NB: this is used from the class without creating an instance, which is
3740
# why it does not have a self parameter.
3741
def get_transport_type(typestring):
3742
"""Parse and return a transport specifier."""
3743
if typestring == "sftp":
3744
from bzrlib.tests import stub_sftp
3745
return stub_sftp.SFTPAbsoluteServer
3746
elif typestring == "memory":
3747
from bzrlib.tests import test_server
3748
return memory.MemoryServer
3749
elif typestring == "fakenfs":
3750
from bzrlib.tests import test_server
3751
return test_server.FakeNFSServer
3752
msg = "No known transport type %s. Supported types are: sftp\n" %\
3754
raise errors.BzrCommandError(msg)
3757
takes_args = ['testspecs*']
3758
takes_options = ['verbose',
3760
help='Stop when one test fails.',
3764
help='Use a different transport by default '
3765
'throughout the test suite.',
3766
type=get_transport_type),
3768
help='Run the benchmarks rather than selftests.',
3770
Option('lsprof-timed',
3771
help='Generate lsprof output for benchmarked'
3772
' sections of code.'),
3773
Option('lsprof-tests',
3774
help='Generate lsprof output for each test.'),
3776
help='Run all tests, but run specified tests first.',
3780
help='List the tests instead of running them.'),
3781
RegistryOption('parallel',
3782
help="Run the test suite in parallel.",
3783
lazy_registry=('bzrlib.tests', 'parallel_registry'),
3784
value_switches=False,
3786
Option('randomize', type=str, argname="SEED",
3787
help='Randomize the order of tests using the given'
3788
' seed or "now" for the current time.'),
3789
ListOption('exclude', type=str, argname="PATTERN",
3791
help='Exclude tests that match this regular'
3794
help='Output test progress via subunit.'),
3795
Option('strict', help='Fail on missing dependencies or '
3797
Option('load-list', type=str, argname='TESTLISTFILE',
3798
help='Load a test id list from a text file.'),
3799
ListOption('debugflag', type=str, short_name='E',
3800
help='Turn on a selftest debug flag.'),
3801
ListOption('starting-with', type=str, argname='TESTID',
3802
param_name='starting_with', short_name='s',
3804
'Load only the tests starting with TESTID.'),
3806
help="By default we disable fsync and fdatasync"
3807
" while running the test suite.")
3809
encoding_type = 'replace'
3812
Command.__init__(self)
3813
self.additional_selftest_args = {}
3815
def run(self, testspecs_list=None, verbose=False, one=False,
3816
transport=None, benchmark=None,
3818
first=False, list_only=False,
3819
randomize=None, exclude=None, strict=False,
3820
load_list=None, debugflag=None, starting_with=None, subunit=False,
3821
parallel=None, lsprof_tests=False,
3823
from bzrlib import tests
3825
if testspecs_list is not None:
3826
pattern = '|'.join(testspecs_list)
3831
from bzrlib.tests import SubUnitBzrRunner
3833
raise errors.BzrCommandError("subunit not available. subunit "
3834
"needs to be installed to use --subunit.")
3835
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3836
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3837
# stdout, which would corrupt the subunit stream.
3838
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3839
# following code can be deleted when it's sufficiently deployed
3840
# -- vila/mgz 20100514
3841
if (sys.platform == "win32"
3842
and getattr(sys.stdout, 'fileno', None) is not None):
3844
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3846
self.additional_selftest_args.setdefault(
3847
'suite_decorators', []).append(parallel)
3849
raise errors.BzrCommandError(
3850
"--benchmark is no longer supported from bzr 2.2; "
3851
"use bzr-usertest instead")
3852
test_suite_factory = None
3854
exclude_pattern = None
3856
exclude_pattern = '(' + '|'.join(exclude) + ')'
3858
self._disable_fsync()
3859
selftest_kwargs = {"verbose": verbose,
3861
"stop_on_failure": one,
3862
"transport": transport,
3863
"test_suite_factory": test_suite_factory,
3864
"lsprof_timed": lsprof_timed,
3865
"lsprof_tests": lsprof_tests,
3866
"matching_tests_first": first,
3867
"list_only": list_only,
3868
"random_seed": randomize,
3869
"exclude_pattern": exclude_pattern,
3871
"load_list": load_list,
3872
"debug_flags": debugflag,
3873
"starting_with": starting_with
3875
selftest_kwargs.update(self.additional_selftest_args)
3877
# Make deprecation warnings visible, unless -Werror is set
3878
cleanup = symbol_versioning.activate_deprecation_warnings(
3881
result = tests.selftest(**selftest_kwargs)
3884
return int(not result)
3886
def _disable_fsync(self):
3887
"""Change the 'os' functionality to not synchronize."""
3888
self._orig_fsync = getattr(os, 'fsync', None)
3889
if self._orig_fsync is not None:
3890
os.fsync = lambda filedes: None
3891
self._orig_fdatasync = getattr(os, 'fdatasync', None)
3892
if self._orig_fdatasync is not None:
3893
os.fdatasync = lambda filedes: None
3896
class cmd_version(Command):
3897
__doc__ = """Show version of bzr."""
3899
encoding_type = 'replace'
3901
Option("short", help="Print just the version number."),
3905
def run(self, short=False):
3906
from bzrlib.version import show_version
3908
self.outf.write(bzrlib.version_string + '\n')
3910
show_version(to_file=self.outf)
3913
class cmd_rocks(Command):
3914
__doc__ = """Statement of optimism."""
3920
self.outf.write("It sure does!\n")
3923
class cmd_find_merge_base(Command):
3924
__doc__ = """Find and print a base revision for merging two branches."""
3925
# TODO: Options to specify revisions on either side, as if
3926
# merging only part of the history.
3927
takes_args = ['branch', 'other']
3931
def run(self, branch, other):
3932
from bzrlib.revision import ensure_null
3934
branch1 = Branch.open_containing(branch)[0]
3935
branch2 = Branch.open_containing(other)[0]
3936
self.add_cleanup(branch1.lock_read().unlock)
3937
self.add_cleanup(branch2.lock_read().unlock)
3938
last1 = ensure_null(branch1.last_revision())
3939
last2 = ensure_null(branch2.last_revision())
3941
graph = branch1.repository.get_graph(branch2.repository)
3942
base_rev_id = graph.find_unique_lca(last1, last2)
3944
self.outf.write('merge base is revision %s\n' % base_rev_id)
3947
class cmd_merge(Command):
3948
__doc__ = """Perform a three-way merge.
3950
The source of the merge can be specified either in the form of a branch,
3951
or in the form of a path to a file containing a merge directive generated
3952
with bzr send. If neither is specified, the default is the upstream branch
3953
or the branch most recently merged using --remember. The source of the
3954
merge may also be specified in the form of a path to a file in another
3955
branch: in this case, only the modifications to that file are merged into
3956
the current working tree.
3958
When merging from a branch, by default bzr will try to merge in all new
3959
work from the other branch, automatically determining an appropriate base
3960
revision. If this fails, you may need to give an explicit base.
3962
To pick a different ending revision, pass "--revision OTHER". bzr will
3963
try to merge in all new work up to and including revision OTHER.
3965
If you specify two values, "--revision BASE..OTHER", only revisions BASE
3966
through OTHER, excluding BASE but including OTHER, will be merged. If this
3967
causes some revisions to be skipped, i.e. if the destination branch does
3968
not already contain revision BASE, such a merge is commonly referred to as
3969
a "cherrypick". Unlike a normal merge, Bazaar does not currently track
3970
cherrypicks. The changes look like a normal commit, and the history of the
3971
changes from the other branch is not stored in the commit.
3973
Revision numbers are always relative to the source branch.
3975
Merge will do its best to combine the changes in two branches, but there
3976
are some kinds of problems only a human can fix. When it encounters those,
3977
it will mark a conflict. A conflict means that you need to fix something,
3978
before you should commit.
3980
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3982
If there is no default branch set, the first merge will set it (use
3983
--no-remember to avoid setting it). After that, you can omit the branch
3984
to use the default. To change the default, use --remember. The value will
3985
only be saved if the remote location can be accessed.
3987
The results of the merge are placed into the destination working
3988
directory, where they can be reviewed (with bzr diff), tested, and then
3989
committed to record the result of the merge.
3991
merge refuses to run if there are any uncommitted changes, unless
3992
--force is given. If --force is given, then the changes from the source
3993
will be merged with the current working tree, including any uncommitted
3994
changes in the tree. The --force option can also be used to create a
3995
merge revision which has more than two parents.
3997
If one would like to merge changes from the working tree of the other
3998
branch without merging any committed revisions, the --uncommitted option
4001
To select only some changes to merge, use "merge -i", which will prompt
4002
you to apply each diff hunk and file change, similar to "shelve".
4005
To merge all new revisions from bzr.dev::
4007
bzr merge ../bzr.dev
4009
To merge changes up to and including revision 82 from bzr.dev::
4011
bzr merge -r 82 ../bzr.dev
4013
To merge the changes introduced by 82, without previous changes::
4015
bzr merge -r 81..82 ../bzr.dev
4017
To apply a merge directive contained in /tmp/merge::
4019
bzr merge /tmp/merge
4021
To create a merge revision with three parents from two branches
4022
feature1a and feature1b:
4024
bzr merge ../feature1a
4025
bzr merge ../feature1b --force
4026
bzr commit -m 'revision with three parents'
4029
encoding_type = 'exact'
4030
_see_also = ['update', 'remerge', 'status-flags', 'send']
4031
takes_args = ['location?']
4036
help='Merge even if the destination tree has uncommitted changes.'),
4040
Option('show-base', help="Show base revision text in "
4042
Option('uncommitted', help='Apply uncommitted changes'
4043
' from a working copy, instead of branch changes.'),
4044
Option('pull', help='If the destination is already'
4045
' completely merged into the source, pull from the'
4046
' source rather than merging. When this happens,'
4047
' you do not need to commit the result.'),
4048
custom_help('directory',
4049
help='Branch to merge into, '
4050
'rather than the one containing the working directory.'),
4051
Option('preview', help='Instead of merging, show a diff of the'
4053
Option('interactive', help='Select changes interactively.',
4057
def run(self, location=None, revision=None, force=False,
4058
merge_type=None, show_base=False, reprocess=None, remember=None,
4059
uncommitted=False, pull=False,
4064
if merge_type is None:
4065
merge_type = _mod_merge.Merge3Merger
4067
if directory is None: directory = u'.'
4068
possible_transports = []
4070
allow_pending = True
4071
verified = 'inapplicable'
4073
tree = WorkingTree.open_containing(directory)[0]
4074
if tree.branch.revno() == 0:
4075
raise errors.BzrCommandError('Merging into empty branches not currently supported, '
4076
'https://bugs.launchpad.net/bzr/+bug/308562')
4079
basis_tree = tree.revision_tree(tree.last_revision())
4080
except errors.NoSuchRevision:
4081
basis_tree = tree.basis_tree()
4083
# die as quickly as possible if there are uncommitted changes
4085
if tree.has_changes():
4086
raise errors.UncommittedChanges(tree)
4088
view_info = _get_view_info_for_change_reporter(tree)
4089
change_reporter = delta._ChangeReporter(
4090
unversioned_filter=tree.is_ignored, view_info=view_info)
4091
pb = ui.ui_factory.nested_progress_bar()
4092
self.add_cleanup(pb.finished)
4093
self.add_cleanup(tree.lock_write().unlock)
4094
if location is not None:
4096
mergeable = bundle.read_mergeable_from_url(location,
4097
possible_transports=possible_transports)
4098
except errors.NotABundle:
4102
raise errors.BzrCommandError('Cannot use --uncommitted'
4103
' with bundles or merge directives.')
4105
if revision is not None:
4106
raise errors.BzrCommandError(
4107
'Cannot use -r with merge directives or bundles')
4108
merger, verified = _mod_merge.Merger.from_mergeable(tree,
4111
if merger is None and uncommitted:
4112
if revision is not None and len(revision) > 0:
4113
raise errors.BzrCommandError('Cannot use --uncommitted and'
4114
' --revision at the same time.')
4115
merger = self.get_merger_from_uncommitted(tree, location, None)
4116
allow_pending = False
4119
merger, allow_pending = self._get_merger_from_branch(tree,
4120
location, revision, remember, possible_transports, None)
4122
merger.merge_type = merge_type
4123
merger.reprocess = reprocess
4124
merger.show_base = show_base
4125
self.sanity_check_merger(merger)
4126
if (merger.base_rev_id == merger.other_rev_id and
4127
merger.other_rev_id is not None):
4128
# check if location is a nonexistent file (and not a branch) to
4129
# disambiguate the 'Nothing to do'
4130
if merger.interesting_files:
4131
if not merger.other_tree.has_filename(
4132
merger.interesting_files[0]):
4133
note("merger: " + str(merger))
4134
raise errors.PathsDoNotExist([location])
4135
note('Nothing to do.')
4137
if pull and not preview:
4138
if merger.interesting_files is not None:
4139
raise errors.BzrCommandError('Cannot pull individual files')
4140
if (merger.base_rev_id == tree.last_revision()):
4141
result = tree.pull(merger.other_branch, False,
4142
merger.other_rev_id)
4143
result.report(self.outf)
4145
if merger.this_basis is None:
4146
raise errors.BzrCommandError(
4147
"This branch has no commits."
4148
" (perhaps you would prefer 'bzr pull')")
4150
return self._do_preview(merger)
4152
return self._do_interactive(merger)
4154
return self._do_merge(merger, change_reporter, allow_pending,
4157
def _get_preview(self, merger):
4158
tree_merger = merger.make_merger()
4159
tt = tree_merger.make_preview_transform()
4160
self.add_cleanup(tt.finalize)
4161
result_tree = tt.get_preview_tree()
4164
def _do_preview(self, merger):
4165
from bzrlib.diff import show_diff_trees
4166
result_tree = self._get_preview(merger)
4167
path_encoding = osutils.get_diff_header_encoding()
4168
show_diff_trees(merger.this_tree, result_tree, self.outf,
4169
old_label='', new_label='',
4170
path_encoding=path_encoding)
4172
def _do_merge(self, merger, change_reporter, allow_pending, verified):
4173
merger.change_reporter = change_reporter
4174
conflict_count = merger.do_merge()
4176
merger.set_pending()
4177
if verified == 'failed':
4178
warning('Preview patch does not match changes')
4179
if conflict_count != 0:
4184
def _do_interactive(self, merger):
4185
"""Perform an interactive merge.
4187
This works by generating a preview tree of the merge, then using
4188
Shelver to selectively remove the differences between the working tree
4189
and the preview tree.
4191
from bzrlib import shelf_ui
4192
result_tree = self._get_preview(merger)
4193
writer = bzrlib.option.diff_writer_registry.get()
4194
shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
4195
reporter=shelf_ui.ApplyReporter(),
4196
diff_writer=writer(sys.stdout))
4202
def sanity_check_merger(self, merger):
4203
if (merger.show_base and
4204
not merger.merge_type is _mod_merge.Merge3Merger):
4205
raise errors.BzrCommandError("Show-base is not supported for this"
4206
" merge type. %s" % merger.merge_type)
4207
if merger.reprocess is None:
4208
if merger.show_base:
4209
merger.reprocess = False
4211
# Use reprocess if the merger supports it
4212
merger.reprocess = merger.merge_type.supports_reprocess
4213
if merger.reprocess and not merger.merge_type.supports_reprocess:
4214
raise errors.BzrCommandError("Conflict reduction is not supported"
4215
" for merge type %s." %
4217
if merger.reprocess and merger.show_base:
4218
raise errors.BzrCommandError("Cannot do conflict reduction and"
4221
def _get_merger_from_branch(self, tree, location, revision, remember,
4222
possible_transports, pb):
4223
"""Produce a merger from a location, assuming it refers to a branch."""
4224
from bzrlib.tag import _merge_tags_if_possible
4225
# find the branch locations
4226
other_loc, user_location = self._select_branch_location(tree, location,
4228
if revision is not None and len(revision) == 2:
4229
base_loc, _unused = self._select_branch_location(tree,
4230
location, revision, 0)
4232
base_loc = other_loc
4234
other_branch, other_path = Branch.open_containing(other_loc,
4235
possible_transports)
4236
if base_loc == other_loc:
4237
base_branch = other_branch
4239
base_branch, base_path = Branch.open_containing(base_loc,
4240
possible_transports)
4241
# Find the revision ids
4242
other_revision_id = None
4243
base_revision_id = None
4244
if revision is not None:
4245
if len(revision) >= 1:
4246
other_revision_id = revision[-1].as_revision_id(other_branch)
4247
if len(revision) == 2:
4248
base_revision_id = revision[0].as_revision_id(base_branch)
4249
if other_revision_id is None:
4250
other_revision_id = _mod_revision.ensure_null(
4251
other_branch.last_revision())
4252
# Remember where we merge from. We need to remember if:
4253
# - user specify a location (and we don't merge from the parent
4255
# - user ask to remember or there is no previous location set to merge
4256
# from and user didn't ask to *not* remember
4257
if (user_location is not None
4259
or (remember is None
4260
and tree.branch.get_submit_branch() is None)))):
4261
tree.branch.set_submit_branch(other_branch.base)
4262
# Merge tags (but don't set them in the master branch yet, the user
4263
# might revert this merge). Commit will propagate them.
4264
_merge_tags_if_possible(other_branch, tree.branch, ignore_master=True)
4265
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
4266
other_revision_id, base_revision_id, other_branch, base_branch)
4267
if other_path != '':
4268
allow_pending = False
4269
merger.interesting_files = [other_path]
4271
allow_pending = True
4272
return merger, allow_pending
4274
def get_merger_from_uncommitted(self, tree, location, pb):
4275
"""Get a merger for uncommitted changes.
4277
:param tree: The tree the merger should apply to.
4278
:param location: The location containing uncommitted changes.
4279
:param pb: The progress bar to use for showing progress.
4281
location = self._select_branch_location(tree, location)[0]
4282
other_tree, other_path = WorkingTree.open_containing(location)
4283
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree, pb)
4284
if other_path != '':
4285
merger.interesting_files = [other_path]
4288
def _select_branch_location(self, tree, user_location, revision=None,
4290
"""Select a branch location, according to possible inputs.
4292
If provided, branches from ``revision`` are preferred. (Both
4293
``revision`` and ``index`` must be supplied.)
4295
Otherwise, the ``location`` parameter is used. If it is None, then the
4296
``submit`` or ``parent`` location is used, and a note is printed.
4298
:param tree: The working tree to select a branch for merging into
4299
:param location: The location entered by the user
4300
:param revision: The revision parameter to the command
4301
:param index: The index to use for the revision parameter. Negative
4302
indices are permitted.
4303
:return: (selected_location, user_location). The default location
4304
will be the user-entered location.
4306
if (revision is not None and index is not None
4307
and revision[index] is not None):
4308
branch = revision[index].get_branch()
4309
if branch is not None:
4310
return branch, branch
4311
if user_location is None:
4312
location = self._get_remembered(tree, 'Merging from')
4314
location = user_location
4315
return location, user_location
4317
def _get_remembered(self, tree, verb_string):
4318
"""Use tree.branch's parent if none was supplied.
4320
Report if the remembered location was used.
4322
stored_location = tree.branch.get_submit_branch()
4323
stored_location_type = "submit"
4324
if stored_location is None:
4325
stored_location = tree.branch.get_parent()
4326
stored_location_type = "parent"
4327
mutter("%s", stored_location)
4328
if stored_location is None:
4329
raise errors.BzrCommandError("No location specified or remembered")
4330
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
4331
note(u"%s remembered %s location %s", verb_string,
4332
stored_location_type, display_url)
4333
return stored_location
4336
class cmd_remerge(Command):
4337
__doc__ = """Redo a merge.
4339
Use this if you want to try a different merge technique while resolving
4340
conflicts. Some merge techniques are better than others, and remerge
4341
lets you try different ones on different files.
4343
The options for remerge have the same meaning and defaults as the ones for
4344
merge. The difference is that remerge can (only) be run when there is a
4345
pending merge, and it lets you specify particular files.
4348
Re-do the merge of all conflicted files, and show the base text in
4349
conflict regions, in addition to the usual THIS and OTHER texts::
4351
bzr remerge --show-base
4353
Re-do the merge of "foobar", using the weave merge algorithm, with
4354
additional processing to reduce the size of conflict regions::
4356
bzr remerge --merge-type weave --reprocess foobar
4358
takes_args = ['file*']
4363
help="Show base revision text in conflicts."),
4366
def run(self, file_list=None, merge_type=None, show_base=False,
4368
from bzrlib.conflicts import restore
4369
if merge_type is None:
4370
merge_type = _mod_merge.Merge3Merger
4371
tree, file_list = WorkingTree.open_containing_paths(file_list)
4372
self.add_cleanup(tree.lock_write().unlock)
4373
parents = tree.get_parent_ids()
4374
if len(parents) != 2:
4375
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4376
" merges. Not cherrypicking or"
4378
repository = tree.branch.repository
4379
interesting_ids = None
4381
conflicts = tree.conflicts()
4382
if file_list is not None:
4383
interesting_ids = set()
4384
for filename in file_list:
4385
file_id = tree.path2id(filename)
4387
raise errors.NotVersionedError(filename)
4388
interesting_ids.add(file_id)
4389
if tree.kind(file_id) != "directory":
4392
for name, ie in tree.inventory.iter_entries(file_id):
4393
interesting_ids.add(ie.file_id)
4394
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4396
# Remerge only supports resolving contents conflicts
4397
allowed_conflicts = ('text conflict', 'contents conflict')
4398
restore_files = [c.path for c in conflicts
4399
if c.typestring in allowed_conflicts]
4400
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4401
tree.set_conflicts(ConflictList(new_conflicts))
4402
if file_list is not None:
4403
restore_files = file_list
4404
for filename in restore_files:
4406
restore(tree.abspath(filename))
4407
except errors.NotConflicted:
4409
# Disable pending merges, because the file texts we are remerging
4410
# have not had those merges performed. If we use the wrong parents
4411
# list, we imply that the working tree text has seen and rejected
4412
# all the changes from the other tree, when in fact those changes
4413
# have not yet been seen.
4414
tree.set_parent_ids(parents[:1])
4416
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4417
merger.interesting_ids = interesting_ids
4418
merger.merge_type = merge_type
4419
merger.show_base = show_base
4420
merger.reprocess = reprocess
4421
conflicts = merger.do_merge()
4423
tree.set_parent_ids(parents)
4430
class cmd_revert(Command):
4431
__doc__ = """Revert files to a previous revision.
4433
Giving a list of files will revert only those files. Otherwise, all files
4434
will be reverted. If the revision is not specified with '--revision', the
4435
last committed revision is used.
4437
To remove only some changes, without reverting to a prior version, use
4438
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4439
will remove the changes introduced by the second last commit (-2), without
4440
affecting the changes introduced by the last commit (-1). To remove
4441
certain changes on a hunk-by-hunk basis, see the shelve command.
4443
By default, any files that have been manually changed will be backed up
4444
first. (Files changed only by merge are not backed up.) Backup files have
4445
'.~#~' appended to their name, where # is a number.
4447
When you provide files, you can use their current pathname or the pathname
4448
from the target revision. So you can use revert to "undelete" a file by
4449
name. If you name a directory, all the contents of that directory will be
4452
If you have newly added files since the target revision, they will be
4453
removed. If the files to be removed have been changed, backups will be
4454
created as above. Directories containing unknown files will not be
4457
The working tree contains a list of revisions that have been merged but
4458
not yet committed. These revisions will be included as additional parents
4459
of the next commit. Normally, using revert clears that list as well as
4460
reverting the files. If any files are specified, revert leaves the list
4461
of uncommitted merges alone and reverts only the files. Use ``bzr revert
4462
.`` in the tree root to revert all files but keep the recorded merges,
4463
and ``bzr revert --forget-merges`` to clear the pending merge list without
4464
reverting any files.
4466
Using "bzr revert --forget-merges", it is possible to apply all of the
4467
changes from a branch in a single revision. To do this, perform the merge
4468
as desired. Then doing revert with the "--forget-merges" option will keep
4469
the content of the tree as it was, but it will clear the list of pending
4470
merges. The next commit will then contain all of the changes that are
4471
present in the other branch, but without any other parent revisions.
4472
Because this technique forgets where these changes originated, it may
4473
cause additional conflicts on later merges involving the same source and
4477
_see_also = ['cat', 'export', 'merge', 'shelve']
4480
Option('no-backup', "Do not save backups of reverted files."),
4481
Option('forget-merges',
4482
'Remove pending merge marker, without changing any files.'),
4484
takes_args = ['file*']
4486
def run(self, revision=None, no_backup=False, file_list=None,
4487
forget_merges=None):
4488
tree, file_list = WorkingTree.open_containing_paths(file_list)
4489
self.add_cleanup(tree.lock_tree_write().unlock)
4491
tree.set_parent_ids(tree.get_parent_ids()[:1])
4493
self._revert_tree_to_revision(tree, revision, file_list, no_backup)
4496
def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4497
rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4498
tree.revert(file_list, rev_tree, not no_backup, None,
4499
report_changes=True)
4502
class cmd_assert_fail(Command):
4503
__doc__ = """Test reporting of assertion failures"""
4504
# intended just for use in testing
4509
raise AssertionError("always fails")
4512
class cmd_help(Command):
4513
__doc__ = """Show help on a command or other topic.
4516
_see_also = ['topics']
4518
Option('long', 'Show help on all commands.'),
4520
takes_args = ['topic?']
4521
aliases = ['?', '--help', '-?', '-h']
4524
def run(self, topic=None, long=False):
4526
if topic is None and long:
4528
bzrlib.help.help(topic)
4531
class cmd_shell_complete(Command):
4532
__doc__ = """Show appropriate completions for context.
4534
For a list of all available commands, say 'bzr shell-complete'.
4536
takes_args = ['context?']
4541
def run(self, context=None):
4542
import shellcomplete
4543
shellcomplete.shellcomplete(context)
4546
class cmd_missing(Command):
4547
__doc__ = """Show unmerged/unpulled revisions between two branches.
4549
OTHER_BRANCH may be local or remote.
4551
To filter on a range of revisions, you can use the command -r begin..end
4552
-r revision requests a specific revision, -r ..end or -r begin.. are
4556
1 - some missing revisions
4557
0 - no missing revisions
4561
Determine the missing revisions between this and the branch at the
4562
remembered pull location::
4566
Determine the missing revisions between this and another branch::
4568
bzr missing http://server/branch
4570
Determine the missing revisions up to a specific revision on the other
4573
bzr missing -r ..-10
4575
Determine the missing revisions up to a specific revision on this
4578
bzr missing --my-revision ..-10
4581
_see_also = ['merge', 'pull']
4582
takes_args = ['other_branch?']
4585
Option('reverse', 'Reverse the order of revisions.'),
4587
'Display changes in the local branch only.'),
4588
Option('this' , 'Same as --mine-only.'),
4589
Option('theirs-only',
4590
'Display changes in the remote branch only.'),
4591
Option('other', 'Same as --theirs-only.'),
4595
custom_help('revision',
4596
help='Filter on other branch revisions (inclusive). '
4597
'See "help revisionspec" for details.'),
4598
Option('my-revision',
4599
type=_parse_revision_str,
4600
help='Filter on local branch revisions (inclusive). '
4601
'See "help revisionspec" for details.'),
4602
Option('include-merges',
4603
'Show all revisions in addition to the mainline ones.'),
4605
encoding_type = 'replace'
4608
def run(self, other_branch=None, reverse=False, mine_only=False,
4610
log_format=None, long=False, short=False, line=False,
4611
show_ids=False, verbose=False, this=False, other=False,
4612
include_merges=False, revision=None, my_revision=None,
4614
from bzrlib.missing import find_unmerged, iter_log_revisions
4623
# TODO: We should probably check that we don't have mine-only and
4624
# theirs-only set, but it gets complicated because we also have
4625
# this and other which could be used.
4632
local_branch = Branch.open_containing(directory)[0]
4633
self.add_cleanup(local_branch.lock_read().unlock)
4635
parent = local_branch.get_parent()
4636
if other_branch is None:
4637
other_branch = parent
4638
if other_branch is None:
4639
raise errors.BzrCommandError("No peer location known"
4641
display_url = urlutils.unescape_for_display(parent,
4643
message("Using saved parent location: "
4644
+ display_url + "\n")
4646
remote_branch = Branch.open(other_branch)
4647
if remote_branch.base == local_branch.base:
4648
remote_branch = local_branch
4650
self.add_cleanup(remote_branch.lock_read().unlock)
4652
local_revid_range = _revision_range_to_revid_range(
4653
_get_revision_range(my_revision, local_branch,
4656
remote_revid_range = _revision_range_to_revid_range(
4657
_get_revision_range(revision,
4658
remote_branch, self.name()))
4660
local_extra, remote_extra = find_unmerged(
4661
local_branch, remote_branch, restrict,
4662
backward=not reverse,
4663
include_merges=include_merges,
4664
local_revid_range=local_revid_range,
4665
remote_revid_range=remote_revid_range)
4667
if log_format is None:
4668
registry = log.log_formatter_registry
4669
log_format = registry.get_default(local_branch)
4670
lf = log_format(to_file=self.outf,
4672
show_timezone='original')
4675
if local_extra and not theirs_only:
4676
message("You have %d extra revision(s):\n" %
4678
for revision in iter_log_revisions(local_extra,
4679
local_branch.repository,
4681
lf.log_revision(revision)
4682
printed_local = True
4685
printed_local = False
4687
if remote_extra and not mine_only:
4688
if printed_local is True:
4690
message("You are missing %d revision(s):\n" %
4692
for revision in iter_log_revisions(remote_extra,
4693
remote_branch.repository,
4695
lf.log_revision(revision)
4698
if mine_only and not local_extra:
4699
# We checked local, and found nothing extra
4700
message('This branch has no new revisions.\n')
4701
elif theirs_only and not remote_extra:
4702
# We checked remote, and found nothing extra
4703
message('Other branch has no new revisions.\n')
4704
elif not (mine_only or theirs_only or local_extra or
4706
# We checked both branches, and neither one had extra
4708
message("Branches are up to date.\n")
4710
if not status_code and parent is None and other_branch is not None:
4711
self.add_cleanup(local_branch.lock_write().unlock)
4712
# handle race conditions - a parent might be set while we run.
4713
if local_branch.get_parent() is None:
4714
local_branch.set_parent(remote_branch.base)
4718
class cmd_pack(Command):
4719
__doc__ = """Compress the data within a repository.
4721
This operation compresses the data within a bazaar repository. As
4722
bazaar supports automatic packing of repository, this operation is
4723
normally not required to be done manually.
4725
During the pack operation, bazaar takes a backup of existing repository
4726
data, i.e. pack files. This backup is eventually removed by bazaar
4727
automatically when it is safe to do so. To save disk space by removing
4728
the backed up pack files, the --clean-obsolete-packs option may be
4731
Warning: If you use --clean-obsolete-packs and your machine crashes
4732
during or immediately after repacking, you may be left with a state
4733
where the deletion has been written to disk but the new packs have not
4734
been. In this case the repository may be unusable.
4737
_see_also = ['repositories']
4738
takes_args = ['branch_or_repo?']
4740
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4743
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4744
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4746
branch = dir.open_branch()
4747
repository = branch.repository
4748
except errors.NotBranchError:
4749
repository = dir.open_repository()
4750
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4753
class cmd_plugins(Command):
4754
__doc__ = """List the installed plugins.
4756
This command displays the list of installed plugins including
4757
version of plugin and a short description of each.
4759
--verbose shows the path where each plugin is located.
4761
A plugin is an external component for Bazaar that extends the
4762
revision control system, by adding or replacing code in Bazaar.
4763
Plugins can do a variety of things, including overriding commands,
4764
adding new commands, providing additional network transports and
4765
customizing log output.
4767
See the Bazaar Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/>
4768
for further information on plugins including where to find them and how to
4769
install them. Instructions are also provided there on how to write new
4770
plugins using the Python programming language.
4772
takes_options = ['verbose']
4775
def run(self, verbose=False):
4776
from bzrlib import plugin
4777
# Don't give writelines a generator as some codecs don't like that
4778
self.outf.writelines(
4779
list(plugin.describe_plugins(show_paths=verbose)))
4782
class cmd_testament(Command):
4783
__doc__ = """Show testament (signing-form) of a revision."""
4786
Option('long', help='Produce long-format testament.'),
4788
help='Produce a strict-format testament.')]
4789
takes_args = ['branch?']
4791
def run(self, branch=u'.', revision=None, long=False, strict=False):
4792
from bzrlib.testament import Testament, StrictTestament
4794
testament_class = StrictTestament
4796
testament_class = Testament
4798
b = Branch.open_containing(branch)[0]
4800
b = Branch.open(branch)
4801
self.add_cleanup(b.lock_read().unlock)
4802
if revision is None:
4803
rev_id = b.last_revision()
4805
rev_id = revision[0].as_revision_id(b)
4806
t = testament_class.from_revision(b.repository, rev_id)
4808
sys.stdout.writelines(t.as_text_lines())
4810
sys.stdout.write(t.as_short_text())
4813
class cmd_annotate(Command):
4814
__doc__ = """Show the origin of each line in a file.
4816
This prints out the given file with an annotation on the left side
4817
indicating which revision, author and date introduced the change.
4819
If the origin is the same for a run of consecutive lines, it is
4820
shown only at the top, unless the --all option is given.
4822
# TODO: annotate directories; showing when each file was last changed
4823
# TODO: if the working copy is modified, show annotations on that
4824
# with new uncommitted lines marked
4825
aliases = ['ann', 'blame', 'praise']
4826
takes_args = ['filename']
4827
takes_options = [Option('all', help='Show annotations on all lines.'),
4828
Option('long', help='Show commit date in annotations.'),
4833
encoding_type = 'exact'
4836
def run(self, filename, all=False, long=False, revision=None,
4837
show_ids=False, directory=None):
4838
from bzrlib.annotate import (
4841
wt, branch, relpath = \
4842
_open_directory_or_containing_tree_or_branch(filename, directory)
4844
self.add_cleanup(wt.lock_read().unlock)
4846
self.add_cleanup(branch.lock_read().unlock)
4847
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4848
self.add_cleanup(tree.lock_read().unlock)
4849
if wt is not None and revision is None:
4850
file_id = wt.path2id(relpath)
4852
file_id = tree.path2id(relpath)
4854
raise errors.NotVersionedError(filename)
4855
if wt is not None and revision is None:
4856
# If there is a tree and we're not annotating historical
4857
# versions, annotate the working tree's content.
4858
annotate_file_tree(wt, file_id, self.outf, long, all,
4861
annotate_file_tree(tree, file_id, self.outf, long, all,
4862
show_ids=show_ids, branch=branch)
4865
class cmd_re_sign(Command):
4866
__doc__ = """Create a digital signature for an existing revision."""
4867
# TODO be able to replace existing ones.
4869
hidden = True # is this right ?
4870
takes_args = ['revision_id*']
4871
takes_options = ['directory', 'revision']
4873
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4874
if revision_id_list is not None and revision is not None:
4875
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4876
if revision_id_list is None and revision is None:
4877
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4878
b = WorkingTree.open_containing(directory)[0].branch
4879
self.add_cleanup(b.lock_write().unlock)
4880
return self._run(b, revision_id_list, revision)
4882
def _run(self, b, revision_id_list, revision):
4883
import bzrlib.gpg as gpg
4884
gpg_strategy = gpg.GPGStrategy(b.get_config())
4885
if revision_id_list is not None:
4886
b.repository.start_write_group()
4888
for revision_id in revision_id_list:
4889
b.repository.sign_revision(revision_id, gpg_strategy)
4891
b.repository.abort_write_group()
4894
b.repository.commit_write_group()
4895
elif revision is not None:
4896
if len(revision) == 1:
4897
revno, rev_id = revision[0].in_history(b)
4898
b.repository.start_write_group()
4900
b.repository.sign_revision(rev_id, gpg_strategy)
4902
b.repository.abort_write_group()
4905
b.repository.commit_write_group()
4906
elif len(revision) == 2:
4907
# are they both on rh- if so we can walk between them
4908
# might be nice to have a range helper for arbitrary
4909
# revision paths. hmm.
4910
from_revno, from_revid = revision[0].in_history(b)
4911
to_revno, to_revid = revision[1].in_history(b)
4912
if to_revid is None:
4913
to_revno = b.revno()
4914
if from_revno is None or to_revno is None:
4915
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
4916
b.repository.start_write_group()
4918
for revno in range(from_revno, to_revno + 1):
4919
b.repository.sign_revision(b.get_rev_id(revno),
4922
b.repository.abort_write_group()
4925
b.repository.commit_write_group()
4927
raise errors.BzrCommandError('Please supply either one revision, or a range.')
4930
class cmd_bind(Command):
4931
__doc__ = """Convert the current branch into a checkout of the supplied branch.
4932
If no branch is supplied, rebind to the last bound location.
4934
Once converted into a checkout, commits must succeed on the master branch
4935
before they will be applied to the local branch.
4937
Bound branches use the nickname of its master branch unless it is set
4938
locally, in which case binding will update the local nickname to be
4942
_see_also = ['checkouts', 'unbind']
4943
takes_args = ['location?']
4944
takes_options = ['directory']
4946
def run(self, location=None, directory=u'.'):
4947
b, relpath = Branch.open_containing(directory)
4948
if location is None:
4950
location = b.get_old_bound_location()
4951
except errors.UpgradeRequired:
4952
raise errors.BzrCommandError('No location supplied. '
4953
'This format does not remember old locations.')
4955
if location is None:
4956
if b.get_bound_location() is not None:
4957
raise errors.BzrCommandError('Branch is already bound')
4959
raise errors.BzrCommandError('No location supplied '
4960
'and no previous location known')
4961
b_other = Branch.open(location)
4964
except errors.DivergedBranches:
4965
raise errors.BzrCommandError('These branches have diverged.'
4966
' Try merging, and then bind again.')
4967
if b.get_config().has_explicit_nickname():
4968
b.nick = b_other.nick
4971
class cmd_unbind(Command):
4972
__doc__ = """Convert the current checkout into a regular branch.
4974
After unbinding, the local branch is considered independent and subsequent
4975
commits will be local only.
4978
_see_also = ['checkouts', 'bind']
4980
takes_options = ['directory']
4982
def run(self, directory=u'.'):
4983
b, relpath = Branch.open_containing(directory)
4985
raise errors.BzrCommandError('Local branch is not bound')
4988
class cmd_uncommit(Command):
4989
__doc__ = """Remove the last committed revision.
4991
--verbose will print out what is being removed.
4992
--dry-run will go through all the motions, but not actually
4995
If --revision is specified, uncommit revisions to leave the branch at the
4996
specified revision. For example, "bzr uncommit -r 15" will leave the
4997
branch at revision 15.
4999
Uncommit leaves the working tree ready for a new commit. The only change
5000
it may make is to restore any pending merges that were present before
5004
# TODO: jam 20060108 Add an option to allow uncommit to remove
5005
# unreferenced information in 'branch-as-repository' branches.
5006
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
5007
# information in shared branches as well.
5008
_see_also = ['commit']
5009
takes_options = ['verbose', 'revision',
5010
Option('dry-run', help='Don\'t actually make changes.'),
5011
Option('force', help='Say yes to all questions.'),
5013
help='Keep tags that point to removed revisions.'),
5015
help="Only remove the commits from the local branch"
5016
" when in a checkout."
5019
takes_args = ['location?']
5021
encoding_type = 'replace'
5023
def run(self, location=None, dry_run=False, verbose=False,
5024
revision=None, force=False, local=False, keep_tags=False):
5025
if location is None:
5027
control, relpath = bzrdir.BzrDir.open_containing(location)
5029
tree = control.open_workingtree()
5031
except (errors.NoWorkingTree, errors.NotLocalUrl):
5033
b = control.open_branch()
5035
if tree is not None:
5036
self.add_cleanup(tree.lock_write().unlock)
5038
self.add_cleanup(b.lock_write().unlock)
5039
return self._run(b, tree, dry_run, verbose, revision, force,
5042
def _run(self, b, tree, dry_run, verbose, revision, force, local,
5044
from bzrlib.log import log_formatter, show_log
5045
from bzrlib.uncommit import uncommit
5047
last_revno, last_rev_id = b.last_revision_info()
5050
if revision is None:
5052
rev_id = last_rev_id
5054
# 'bzr uncommit -r 10' actually means uncommit
5055
# so that the final tree is at revno 10.
5056
# but bzrlib.uncommit.uncommit() actually uncommits
5057
# the revisions that are supplied.
5058
# So we need to offset it by one
5059
revno = revision[0].in_history(b).revno + 1
5060
if revno <= last_revno:
5061
rev_id = b.get_rev_id(revno)
5063
if rev_id is None or _mod_revision.is_null(rev_id):
5064
self.outf.write('No revisions to uncommit.\n')
5067
lf = log_formatter('short',
5069
show_timezone='original')
5074
direction='forward',
5075
start_revision=revno,
5076
end_revision=last_revno)
5079
self.outf.write('Dry-run, pretending to remove'
5080
' the above revisions.\n')
5082
self.outf.write('The above revision(s) will be removed.\n')
5085
if not ui.ui_factory.confirm_action(
5086
u'Uncommit these revisions',
5087
'bzrlib.builtins.uncommit',
5089
self.outf.write('Canceled\n')
5092
mutter('Uncommitting from {%s} to {%s}',
5093
last_rev_id, rev_id)
5094
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
5095
revno=revno, local=local, keep_tags=keep_tags)
5096
self.outf.write('You can restore the old tip by running:\n'
5097
' bzr pull . -r revid:%s\n' % last_rev_id)
5100
class cmd_break_lock(Command):
5101
__doc__ = """Break a dead lock.
5103
This command breaks a lock on a repository, branch, working directory or
5106
CAUTION: Locks should only be broken when you are sure that the process
5107
holding the lock has been stopped.
5109
You can get information on what locks are open via the 'bzr info
5110
[location]' command.
5114
bzr break-lock bzr+ssh://example.com/bzr/foo
5115
bzr break-lock --conf ~/.bazaar
5118
takes_args = ['location?']
5121
help='LOCATION is the directory where the config lock is.'),
5123
help='Do not ask for confirmation before breaking the lock.'),
5126
def run(self, location=None, config=False, force=False):
5127
if location is None:
5130
ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
5132
{'bzrlib.lockdir.break': True})
5134
conf = _mod_config.LockableConfig(file_name=location)
5137
control, relpath = bzrdir.BzrDir.open_containing(location)
5139
control.break_lock()
5140
except NotImplementedError:
5144
class cmd_wait_until_signalled(Command):
5145
__doc__ = """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
5147
This just prints a line to signal when it is ready, then blocks on stdin.
5153
sys.stdout.write("running\n")
5155
sys.stdin.readline()
5158
class cmd_serve(Command):
5159
__doc__ = """Run the bzr server."""
5161
aliases = ['server']
5165
help='Serve on stdin/out for use from inetd or sshd.'),
5166
RegistryOption('protocol',
5167
help="Protocol to serve.",
5168
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5169
value_switches=True),
5171
help='Listen for connections on nominated port of the form '
5172
'[hostname:]portnumber. Passing 0 as the port number will '
5173
'result in a dynamically allocated port. The default port '
5174
'depends on the protocol.',
5176
custom_help('directory',
5177
help='Serve contents of this directory.'),
5178
Option('allow-writes',
5179
help='By default the server is a readonly server. Supplying '
5180
'--allow-writes enables write access to the contents of '
5181
'the served directory and below. Note that ``bzr serve`` '
5182
'does not perform authentication, so unless some form of '
5183
'external authentication is arranged supplying this '
5184
'option leads to global uncontrolled write access to your '
5189
def get_host_and_port(self, port):
5190
"""Return the host and port to run the smart server on.
5192
If 'port' is None, None will be returned for the host and port.
5194
If 'port' has a colon in it, the string before the colon will be
5195
interpreted as the host.
5197
:param port: A string of the port to run the server on.
5198
:return: A tuple of (host, port), where 'host' is a host name or IP,
5199
and port is an integer TCP/IP port.
5202
if port is not None:
5204
host, port = port.split(':')
5208
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5210
from bzrlib import transport
5211
if directory is None:
5212
directory = os.getcwd()
5213
if protocol is None:
5214
protocol = transport.transport_server_registry.get()
5215
host, port = self.get_host_and_port(port)
5216
url = urlutils.local_path_to_url(directory)
5217
if not allow_writes:
5218
url = 'readonly+' + url
5219
t = transport.get_transport(url)
5220
protocol(t, host, port, inet)
5223
class cmd_join(Command):
5224
__doc__ = """Combine a tree into its containing tree.
5226
This command requires the target tree to be in a rich-root format.
5228
The TREE argument should be an independent tree, inside another tree, but
5229
not part of it. (Such trees can be produced by "bzr split", but also by
5230
running "bzr branch" with the target inside a tree.)
5232
The result is a combined tree, with the subtree no longer an independent
5233
part. This is marked as a merge of the subtree into the containing tree,
5234
and all history is preserved.
5237
_see_also = ['split']
5238
takes_args = ['tree']
5240
Option('reference', help='Join by reference.', hidden=True),
5243
def run(self, tree, reference=False):
5244
sub_tree = WorkingTree.open(tree)
5245
parent_dir = osutils.dirname(sub_tree.basedir)
5246
containing_tree = WorkingTree.open_containing(parent_dir)[0]
5247
repo = containing_tree.branch.repository
5248
if not repo.supports_rich_root():
5249
raise errors.BzrCommandError(
5250
"Can't join trees because %s doesn't support rich root data.\n"
5251
"You can use bzr upgrade on the repository."
5255
containing_tree.add_reference(sub_tree)
5256
except errors.BadReferenceTarget, e:
5257
# XXX: Would be better to just raise a nicely printable
5258
# exception from the real origin. Also below. mbp 20070306
5259
raise errors.BzrCommandError("Cannot join %s. %s" %
5263
containing_tree.subsume(sub_tree)
5264
except errors.BadSubsumeSource, e:
5265
raise errors.BzrCommandError("Cannot join %s. %s" %
5269
class cmd_split(Command):
5270
__doc__ = """Split a subdirectory of a tree into a separate tree.
5272
This command will produce a target tree in a format that supports
5273
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
5274
converted into earlier formats like 'dirstate-tags'.
5276
The TREE argument should be a subdirectory of a working tree. That
5277
subdirectory will be converted into an independent tree, with its own
5278
branch. Commits in the top-level tree will not apply to the new subtree.
5281
_see_also = ['join']
5282
takes_args = ['tree']
5284
def run(self, tree):
5285
containing_tree, subdir = WorkingTree.open_containing(tree)
5286
sub_id = containing_tree.path2id(subdir)
5288
raise errors.NotVersionedError(subdir)
5290
containing_tree.extract(sub_id)
5291
except errors.RootNotRich:
5292
raise errors.RichRootUpgradeRequired(containing_tree.branch.base)
5295
class cmd_merge_directive(Command):
5296
__doc__ = """Generate a merge directive for auto-merge tools.
5298
A directive requests a merge to be performed, and also provides all the
5299
information necessary to do so. This means it must either include a
5300
revision bundle, or the location of a branch containing the desired
5303
A submit branch (the location to merge into) must be supplied the first
5304
time the command is issued. After it has been supplied once, it will
5305
be remembered as the default.
5307
A public branch is optional if a revision bundle is supplied, but required
5308
if --diff or --plain is specified. It will be remembered as the default
5309
after the first use.
5312
takes_args = ['submit_branch?', 'public_branch?']
5316
_see_also = ['send']
5320
RegistryOption.from_kwargs('patch-type',
5321
'The type of patch to include in the directive.',
5323
value_switches=True,
5325
bundle='Bazaar revision bundle (default).',
5326
diff='Normal unified diff.',
5327
plain='No patch, just directive.'),
5328
Option('sign', help='GPG-sign the directive.'), 'revision',
5329
Option('mail-to', type=str,
5330
help='Instead of printing the directive, email to this address.'),
5331
Option('message', type=str, short_name='m',
5332
help='Message to use when committing this merge.')
5335
encoding_type = 'exact'
5337
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5338
sign=False, revision=None, mail_to=None, message=None,
5340
from bzrlib.revision import ensure_null, NULL_REVISION
5341
include_patch, include_bundle = {
5342
'plain': (False, False),
5343
'diff': (True, False),
5344
'bundle': (True, True),
5346
branch = Branch.open(directory)
5347
stored_submit_branch = branch.get_submit_branch()
5348
if submit_branch is None:
5349
submit_branch = stored_submit_branch
5351
if stored_submit_branch is None:
5352
branch.set_submit_branch(submit_branch)
5353
if submit_branch is None:
5354
submit_branch = branch.get_parent()
5355
if submit_branch is None:
5356
raise errors.BzrCommandError('No submit branch specified or known')
5358
stored_public_branch = branch.get_public_branch()
5359
if public_branch is None:
5360
public_branch = stored_public_branch
5361
elif stored_public_branch is None:
5362
branch.set_public_branch(public_branch)
5363
if not include_bundle and public_branch is None:
5364
raise errors.BzrCommandError('No public branch specified or'
5366
base_revision_id = None
5367
if revision is not None:
5368
if len(revision) > 2:
5369
raise errors.BzrCommandError('bzr merge-directive takes '
5370
'at most two one revision identifiers')
5371
revision_id = revision[-1].as_revision_id(branch)
5372
if len(revision) == 2:
5373
base_revision_id = revision[0].as_revision_id(branch)
5375
revision_id = branch.last_revision()
5376
revision_id = ensure_null(revision_id)
5377
if revision_id == NULL_REVISION:
5378
raise errors.BzrCommandError('No revisions to bundle.')
5379
directive = merge_directive.MergeDirective2.from_objects(
5380
branch.repository, revision_id, time.time(),
5381
osutils.local_time_offset(), submit_branch,
5382
public_branch=public_branch, include_patch=include_patch,
5383
include_bundle=include_bundle, message=message,
5384
base_revision_id=base_revision_id)
5387
self.outf.write(directive.to_signed(branch))
5389
self.outf.writelines(directive.to_lines())
5391
message = directive.to_email(mail_to, branch, sign)
5392
s = SMTPConnection(branch.get_config())
5393
s.send_email(message)
5396
class cmd_send(Command):
5397
__doc__ = """Mail or create a merge-directive for submitting changes.
5399
A merge directive provides many things needed for requesting merges:
5401
* A machine-readable description of the merge to perform
5403
* An optional patch that is a preview of the changes requested
5405
* An optional bundle of revision data, so that the changes can be applied
5406
directly from the merge directive, without retrieving data from a
5409
`bzr send` creates a compact data set that, when applied using bzr
5410
merge, has the same effect as merging from the source branch.
5412
By default the merge directive is self-contained and can be applied to any
5413
branch containing submit_branch in its ancestory without needing access to
5416
If --no-bundle is specified, then Bazaar doesn't send the contents of the
5417
revisions, but only a structured request to merge from the
5418
public_location. In that case the public_branch is needed and it must be
5419
up-to-date and accessible to the recipient. The public_branch is always
5420
included if known, so that people can check it later.
5422
The submit branch defaults to the parent of the source branch, but can be
5423
overridden. Both submit branch and public branch will be remembered in
5424
branch.conf the first time they are used for a particular branch. The
5425
source branch defaults to that containing the working directory, but can
5426
be changed using --from.
5428
Both the submit branch and the public branch follow the usual behavior with
5429
respect to --remember: If there is no default location set, the first send
5430
will set it (use --no-remember to avoid setting it). After that, you can
5431
omit the location to use the default. To change the default, use
5432
--remember. The value will only be saved if the location can be accessed.
5434
In order to calculate those changes, bzr must analyse the submit branch.
5435
Therefore it is most efficient for the submit branch to be a local mirror.
5436
If a public location is known for the submit_branch, that location is used
5437
in the merge directive.
5439
The default behaviour is to send the merge directive by mail, unless -o is
5440
given, in which case it is sent to a file.
5442
Mail is sent using your preferred mail program. This should be transparent
5443
on Windows (it uses MAPI). On Unix, it requires the xdg-email utility.
5444
If the preferred client can't be found (or used), your editor will be used.
5446
To use a specific mail program, set the mail_client configuration option.
5447
(For Thunderbird 1.5, this works around some bugs.) Supported values for
5448
specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5449
Mail.app), "mutt", and "thunderbird"; generic options are "default",
5450
"editor", "emacsclient", "mapi", and "xdg-email". Plugins may also add
5453
If mail is being sent, a to address is required. This can be supplied
5454
either on the commandline, by setting the submit_to configuration
5455
option in the branch itself or the child_submit_to configuration option
5456
in the submit branch.
5458
Two formats are currently supported: "4" uses revision bundle format 4 and
5459
merge directive format 2. It is significantly faster and smaller than
5460
older formats. It is compatible with Bazaar 0.19 and later. It is the
5461
default. "0.9" uses revision bundle format 0.9 and merge directive
5462
format 1. It is compatible with Bazaar 0.12 - 0.18.
5464
The merge directives created by bzr send may be applied using bzr merge or
5465
bzr pull by specifying a file containing a merge directive as the location.
5467
bzr send makes extensive use of public locations to map local locations into
5468
URLs that can be used by other people. See `bzr help configuration` to
5469
set them, and use `bzr info` to display them.
5472
encoding_type = 'exact'
5474
_see_also = ['merge', 'pull']
5476
takes_args = ['submit_branch?', 'public_branch?']
5480
help='Do not include a bundle in the merge directive.'),
5481
Option('no-patch', help='Do not include a preview patch in the merge'
5484
help='Remember submit and public branch.'),
5486
help='Branch to generate the submission from, '
5487
'rather than the one containing the working directory.',
5490
Option('output', short_name='o',
5491
help='Write merge directive to this file or directory; '
5492
'use - for stdout.',
5495
help='Refuse to send if there are uncommitted changes in'
5496
' the working tree, --no-strict disables the check.'),
5497
Option('mail-to', help='Mail the request to this address.',
5501
Option('body', help='Body for the email.', type=unicode),
5502
RegistryOption('format',
5503
help='Use the specified output format.',
5504
lazy_registry=('bzrlib.send', 'format_registry')),
5507
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5508
no_patch=False, revision=None, remember=None, output=None,
5509
format=None, mail_to=None, message=None, body=None,
5510
strict=None, **kwargs):
5511
from bzrlib.send import send
5512
return send(submit_branch, revision, public_branch, remember,
5513
format, no_bundle, no_patch, output,
5514
kwargs.get('from', '.'), mail_to, message, body,
5519
class cmd_bundle_revisions(cmd_send):
5520
__doc__ = """Create a merge-directive for submitting changes.
5522
A merge directive provides many things needed for requesting merges:
5524
* A machine-readable description of the merge to perform
5526
* An optional patch that is a preview of the changes requested
5528
* An optional bundle of revision data, so that the changes can be applied
5529
directly from the merge directive, without retrieving data from a
5532
If --no-bundle is specified, then public_branch is needed (and must be
5533
up-to-date), so that the receiver can perform the merge using the
5534
public_branch. The public_branch is always included if known, so that
5535
people can check it later.
5537
The submit branch defaults to the parent, but can be overridden. Both
5538
submit branch and public branch will be remembered if supplied.
5540
If a public_branch is known for the submit_branch, that public submit
5541
branch is used in the merge instructions. This means that a local mirror
5542
can be used as your actual submit branch, once you have set public_branch
5545
Two formats are currently supported: "4" uses revision bundle format 4 and
5546
merge directive format 2. It is significantly faster and smaller than
5547
older formats. It is compatible with Bazaar 0.19 and later. It is the
5548
default. "0.9" uses revision bundle format 0.9 and merge directive
5549
format 1. It is compatible with Bazaar 0.12 - 0.18.
5554
help='Do not include a bundle in the merge directive.'),
5555
Option('no-patch', help='Do not include a preview patch in the merge'
5558
help='Remember submit and public branch.'),
5560
help='Branch to generate the submission from, '
5561
'rather than the one containing the working directory.',
5564
Option('output', short_name='o', help='Write directive to this file.',
5567
help='Refuse to bundle revisions if there are uncommitted'
5568
' changes in the working tree, --no-strict disables the check.'),
5570
RegistryOption('format',
5571
help='Use the specified output format.',
5572
lazy_registry=('bzrlib.send', 'format_registry')),
5574
aliases = ['bundle']
5576
_see_also = ['send', 'merge']
5580
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5581
no_patch=False, revision=None, remember=False, output=None,
5582
format=None, strict=None, **kwargs):
5585
from bzrlib.send import send
5586
return send(submit_branch, revision, public_branch, remember,
5587
format, no_bundle, no_patch, output,
5588
kwargs.get('from', '.'), None, None, None,
5589
self.outf, strict=strict)
5592
class cmd_tag(Command):
5593
__doc__ = """Create, remove or modify a tag naming a revision.
5595
Tags give human-meaningful names to revisions. Commands that take a -r
5596
(--revision) option can be given -rtag:X, where X is any previously
5599
Tags are stored in the branch. Tags are copied from one branch to another
5600
along when you branch, push, pull or merge.
5602
It is an error to give a tag name that already exists unless you pass
5603
--force, in which case the tag is moved to point to the new revision.
5605
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5606
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5608
If no tag name is specified it will be determined through the
5609
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5610
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5614
_see_also = ['commit', 'tags']
5615
takes_args = ['tag_name?']
5618
help='Delete this tag rather than placing it.',
5620
custom_help('directory',
5621
help='Branch in which to place the tag.'),
5623
help='Replace existing tags.',
5628
def run(self, tag_name=None,
5634
branch, relpath = Branch.open_containing(directory)
5635
self.add_cleanup(branch.lock_write().unlock)
5637
if tag_name is None:
5638
raise errors.BzrCommandError("No tag specified to delete.")
5639
branch.tags.delete_tag(tag_name)
5640
note('Deleted tag %s.' % tag_name)
5643
if len(revision) != 1:
5644
raise errors.BzrCommandError(
5645
"Tags can only be placed on a single revision, "
5647
revision_id = revision[0].as_revision_id(branch)
5649
revision_id = branch.last_revision()
5650
if tag_name is None:
5651
tag_name = branch.automatic_tag_name(revision_id)
5652
if tag_name is None:
5653
raise errors.BzrCommandError(
5654
"Please specify a tag name.")
5656
existing_target = branch.tags.lookup_tag(tag_name)
5657
except errors.NoSuchTag:
5658
existing_target = None
5659
if not force and existing_target not in (None, revision_id):
5660
raise errors.TagAlreadyExists(tag_name)
5661
if existing_target == revision_id:
5662
note('Tag %s already exists for that revision.' % tag_name)
5664
branch.tags.set_tag(tag_name, revision_id)
5665
if existing_target is None:
5666
note('Created tag %s.' % tag_name)
5668
note('Updated tag %s.' % tag_name)
5671
class cmd_tags(Command):
5672
__doc__ = """List tags.
5674
This command shows a table of tag names and the revisions they reference.
5679
custom_help('directory',
5680
help='Branch whose tags should be displayed.'),
5681
RegistryOption('sort',
5682
'Sort tags by different criteria.', title='Sorting',
5683
lazy_registry=('bzrlib.tag', 'tag_sort_methods')
5690
def run(self, directory='.', sort=None, show_ids=False, revision=None):
5691
from bzrlib.tag import tag_sort_methods
5692
branch, relpath = Branch.open_containing(directory)
5694
tags = branch.tags.get_tag_dict().items()
5698
self.add_cleanup(branch.lock_read().unlock)
5700
graph = branch.repository.get_graph()
5701
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5702
revid1, revid2 = rev1.rev_id, rev2.rev_id
5703
# only show revisions between revid1 and revid2 (inclusive)
5704
tags = [(tag, revid) for tag, revid in tags if
5705
graph.is_between(revid, revid1, revid2)]
5707
sort = tag_sort_methods.get()
5710
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5711
for index, (tag, revid) in enumerate(tags):
5713
revno = branch.revision_id_to_dotted_revno(revid)
5714
if isinstance(revno, tuple):
5715
revno = '.'.join(map(str, revno))
5716
except (errors.NoSuchRevision, errors.GhostRevisionsHaveNoRevno):
5717
# Bad tag data/merges can lead to tagged revisions
5718
# which are not in this branch. Fail gracefully ...
5720
tags[index] = (tag, revno)
5722
for tag, revspec in tags:
5723
self.outf.write('%-20s %s\n' % (tag, revspec))
5726
class cmd_reconfigure(Command):
5727
__doc__ = """Reconfigure the type of a bzr directory.
5729
A target configuration must be specified.
5731
For checkouts, the bind-to location will be auto-detected if not specified.
5732
The order of preference is
5733
1. For a lightweight checkout, the current bound location.
5734
2. For branches that used to be checkouts, the previously-bound location.
5735
3. The push location.
5736
4. The parent location.
5737
If none of these is available, --bind-to must be specified.
5740
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5741
takes_args = ['location?']
5743
RegistryOption.from_kwargs(
5746
help='The relation between branch and tree.',
5747
value_switches=True, enum_switch=False,
5748
branch='Reconfigure to be an unbound branch with no working tree.',
5749
tree='Reconfigure to be an unbound branch with a working tree.',
5750
checkout='Reconfigure to be a bound branch with a working tree.',
5751
lightweight_checkout='Reconfigure to be a lightweight'
5752
' checkout (with no local history).',
5754
RegistryOption.from_kwargs(
5756
title='Repository type',
5757
help='Location fo the repository.',
5758
value_switches=True, enum_switch=False,
5759
standalone='Reconfigure to be a standalone branch '
5760
'(i.e. stop using shared repository).',
5761
use_shared='Reconfigure to use a shared repository.',
5763
RegistryOption.from_kwargs(
5765
title='Trees in Repository',
5766
help='Whether new branches in the repository have trees.',
5767
value_switches=True, enum_switch=False,
5768
with_trees='Reconfigure repository to create '
5769
'working trees on branches by default.',
5770
with_no_trees='Reconfigure repository to not create '
5771
'working trees on branches by default.'
5773
Option('bind-to', help='Branch to bind checkout to.', type=str),
5775
help='Perform reconfiguration even if local changes'
5777
Option('stacked-on',
5778
help='Reconfigure a branch to be stacked on another branch.',
5782
help='Reconfigure a branch to be unstacked. This '
5783
'may require copying substantial data into it.',
5787
def run(self, location=None, bind_to=None, force=False,
5788
tree_type=None, repository_type=None, repository_trees=None,
5789
stacked_on=None, unstacked=None):
5790
directory = bzrdir.BzrDir.open(location)
5791
if stacked_on and unstacked:
5792
raise errors.BzrCommandError("Can't use both --stacked-on and --unstacked")
5793
elif stacked_on is not None:
5794
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5796
reconfigure.ReconfigureUnstacked().apply(directory)
5797
# At the moment you can use --stacked-on and a different
5798
# reconfiguration shape at the same time; there seems no good reason
5800
if (tree_type is None and
5801
repository_type is None and
5802
repository_trees is None):
5803
if stacked_on or unstacked:
5806
raise errors.BzrCommandError('No target configuration '
5808
reconfiguration = None
5809
if tree_type == 'branch':
5810
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5811
elif tree_type == 'tree':
5812
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5813
elif tree_type == 'checkout':
5814
reconfiguration = reconfigure.Reconfigure.to_checkout(
5816
elif tree_type == 'lightweight-checkout':
5817
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5820
reconfiguration.apply(force)
5821
reconfiguration = None
5822
if repository_type == 'use-shared':
5823
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5824
elif repository_type == 'standalone':
5825
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5827
reconfiguration.apply(force)
5828
reconfiguration = None
5829
if repository_trees == 'with-trees':
5830
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5832
elif repository_trees == 'with-no-trees':
5833
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5836
reconfiguration.apply(force)
5837
reconfiguration = None
5840
class cmd_switch(Command):
5841
__doc__ = """Set the branch of a checkout and update.
5843
For lightweight checkouts, this changes the branch being referenced.
5844
For heavyweight checkouts, this checks that there are no local commits
5845
versus the current bound branch, then it makes the local branch a mirror
5846
of the new location and binds to it.
5848
In both cases, the working tree is updated and uncommitted changes
5849
are merged. The user can commit or revert these as they desire.
5851
Pending merges need to be committed or reverted before using switch.
5853
The path to the branch to switch to can be specified relative to the parent
5854
directory of the current branch. For example, if you are currently in a
5855
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5858
Bound branches use the nickname of its master branch unless it is set
5859
locally, in which case switching will update the local nickname to be
5863
takes_args = ['to_location?']
5864
takes_options = ['directory',
5866
help='Switch even if local commits will be lost.'),
5868
Option('create-branch', short_name='b',
5869
help='Create the target branch from this one before'
5870
' switching to it.'),
5873
def run(self, to_location=None, force=False, create_branch=False,
5874
revision=None, directory=u'.'):
5875
from bzrlib import switch
5876
tree_location = directory
5877
revision = _get_one_revision('switch', revision)
5878
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5879
if to_location is None:
5880
if revision is None:
5881
raise errors.BzrCommandError('You must supply either a'
5882
' revision or a location')
5883
to_location = tree_location
5885
branch = control_dir.open_branch()
5886
had_explicit_nick = branch.get_config().has_explicit_nickname()
5887
except errors.NotBranchError:
5889
had_explicit_nick = False
5892
raise errors.BzrCommandError('cannot create branch without'
5894
to_location = directory_service.directories.dereference(
5896
if '/' not in to_location and '\\' not in to_location:
5897
# This path is meant to be relative to the existing branch
5898
this_url = self._get_branch_location(control_dir)
5899
to_location = urlutils.join(this_url, '..', to_location)
5900
to_branch = branch.bzrdir.sprout(to_location,
5901
possible_transports=[branch.bzrdir.root_transport],
5902
source_branch=branch).open_branch()
5905
to_branch = Branch.open(to_location)
5906
except errors.NotBranchError:
5907
this_url = self._get_branch_location(control_dir)
5908
to_branch = Branch.open(
5909
urlutils.join(this_url, '..', to_location))
5910
if revision is not None:
5911
revision = revision.as_revision_id(to_branch)
5912
switch.switch(control_dir, to_branch, force, revision_id=revision)
5913
if had_explicit_nick:
5914
branch = control_dir.open_branch() #get the new branch!
5915
branch.nick = to_branch.nick
5916
note('Switched to branch: %s',
5917
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5919
def _get_branch_location(self, control_dir):
5920
"""Return location of branch for this control dir."""
5922
this_branch = control_dir.open_branch()
5923
# This may be a heavy checkout, where we want the master branch
5924
master_location = this_branch.get_bound_location()
5925
if master_location is not None:
5926
return master_location
5927
# If not, use a local sibling
5928
return this_branch.base
5929
except errors.NotBranchError:
5930
format = control_dir.find_branch_format()
5931
if getattr(format, 'get_reference', None) is not None:
5932
return format.get_reference(control_dir)
5934
return control_dir.root_transport.base
5937
class cmd_view(Command):
5938
__doc__ = """Manage filtered views.
5940
Views provide a mask over the tree so that users can focus on
5941
a subset of a tree when doing their work. After creating a view,
5942
commands that support a list of files - status, diff, commit, etc -
5943
effectively have that list of files implicitly given each time.
5944
An explicit list of files can still be given but those files
5945
must be within the current view.
5947
In most cases, a view has a short life-span: it is created to make
5948
a selected change and is deleted once that change is committed.
5949
At other times, you may wish to create one or more named views
5950
and switch between them.
5952
To disable the current view without deleting it, you can switch to
5953
the pseudo view called ``off``. This can be useful when you need
5954
to see the whole tree for an operation or two (e.g. merge) but
5955
want to switch back to your view after that.
5958
To define the current view::
5960
bzr view file1 dir1 ...
5962
To list the current view::
5966
To delete the current view::
5970
To disable the current view without deleting it::
5972
bzr view --switch off
5974
To define a named view and switch to it::
5976
bzr view --name view-name file1 dir1 ...
5978
To list a named view::
5980
bzr view --name view-name
5982
To delete a named view::
5984
bzr view --name view-name --delete
5986
To switch to a named view::
5988
bzr view --switch view-name
5990
To list all views defined::
5994
To delete all views::
5996
bzr view --delete --all
6000
takes_args = ['file*']
6003
help='Apply list or delete action to all views.',
6006
help='Delete the view.',
6009
help='Name of the view to define, list or delete.',
6013
help='Name of the view to switch to.',
6018
def run(self, file_list,
6024
tree, file_list = WorkingTree.open_containing_paths(file_list,
6026
current_view, view_dict = tree.views.get_view_info()
6031
raise errors.BzrCommandError(
6032
"Both --delete and a file list specified")
6034
raise errors.BzrCommandError(
6035
"Both --delete and --switch specified")
6037
tree.views.set_view_info(None, {})
6038
self.outf.write("Deleted all views.\n")
6040
raise errors.BzrCommandError("No current view to delete")
6042
tree.views.delete_view(name)
6043
self.outf.write("Deleted '%s' view.\n" % name)
6046
raise errors.BzrCommandError(
6047
"Both --switch and a file list specified")
6049
raise errors.BzrCommandError(
6050
"Both --switch and --all specified")
6051
elif switch == 'off':
6052
if current_view is None:
6053
raise errors.BzrCommandError("No current view to disable")
6054
tree.views.set_view_info(None, view_dict)
6055
self.outf.write("Disabled '%s' view.\n" % (current_view))
6057
tree.views.set_view_info(switch, view_dict)
6058
view_str = views.view_display_str(tree.views.lookup_view())
6059
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
6062
self.outf.write('Views defined:\n')
6063
for view in sorted(view_dict):
6064
if view == current_view:
6068
view_str = views.view_display_str(view_dict[view])
6069
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
6071
self.outf.write('No views defined.\n')
6074
# No name given and no current view set
6077
raise errors.BzrCommandError(
6078
"Cannot change the 'off' pseudo view")
6079
tree.views.set_view(name, sorted(file_list))
6080
view_str = views.view_display_str(tree.views.lookup_view())
6081
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
6085
# No name given and no current view set
6086
self.outf.write('No current view.\n')
6088
view_str = views.view_display_str(tree.views.lookup_view(name))
6089
self.outf.write("'%s' view is: %s\n" % (name, view_str))
6092
class cmd_hooks(Command):
6093
__doc__ = """Show hooks."""
6098
for hook_key in sorted(hooks.known_hooks.keys()):
6099
some_hooks = hooks.known_hooks_key_to_object(hook_key)
6100
self.outf.write("%s:\n" % type(some_hooks).__name__)
6101
for hook_name, hook_point in sorted(some_hooks.items()):
6102
self.outf.write(" %s:\n" % (hook_name,))
6103
found_hooks = list(hook_point)
6105
for hook in found_hooks:
6106
self.outf.write(" %s\n" %
6107
(some_hooks.get_hook_name(hook),))
6109
self.outf.write(" <no hooks installed>\n")
6112
class cmd_remove_branch(Command):
6113
__doc__ = """Remove a branch.
6115
This will remove the branch from the specified location but
6116
will keep any working tree or repository in place.
6120
Remove the branch at repo/trunk::
6122
bzr remove-branch repo/trunk
6126
takes_args = ["location?"]
6128
aliases = ["rmbranch"]
6130
def run(self, location=None):
6131
if location is None:
6133
branch = Branch.open_containing(location)[0]
6134
branch.bzrdir.destroy_branch()
6137
class cmd_shelve(Command):
6138
__doc__ = """Temporarily set aside some changes from the current tree.
6140
Shelve allows you to temporarily put changes you've made "on the shelf",
6141
ie. out of the way, until a later time when you can bring them back from
6142
the shelf with the 'unshelve' command. The changes are stored alongside
6143
your working tree, and so they aren't propagated along with your branch nor
6144
will they survive its deletion.
6146
If shelve --list is specified, previously-shelved changes are listed.
6148
Shelve is intended to help separate several sets of changes that have
6149
been inappropriately mingled. If you just want to get rid of all changes
6150
and you don't need to restore them later, use revert. If you want to
6151
shelve all text changes at once, use shelve --all.
6153
If filenames are specified, only the changes to those files will be
6154
shelved. Other files will be left untouched.
6156
If a revision is specified, changes since that revision will be shelved.
6158
You can put multiple items on the shelf, and by default, 'unshelve' will
6159
restore the most recently shelved changes.
6161
For complicated changes, it is possible to edit the changes in a separate
6162
editor program to decide what the file remaining in the working copy
6163
should look like. To do this, add the configuration option
6165
change_editor = PROGRAM @new_path @old_path
6167
where @new_path is replaced with the path of the new version of the
6168
file and @old_path is replaced with the path of the old version of
6169
the file. The PROGRAM should save the new file with the desired
6170
contents of the file in the working tree.
6174
takes_args = ['file*']
6179
Option('all', help='Shelve all changes.'),
6181
RegistryOption('writer', 'Method to use for writing diffs.',
6182
bzrlib.option.diff_writer_registry,
6183
value_switches=True, enum_switch=False),
6185
Option('list', help='List shelved changes.'),
6187
help='Destroy removed changes instead of shelving them.'),
6189
_see_also = ['unshelve', 'configuration']
6191
def run(self, revision=None, all=False, file_list=None, message=None,
6192
writer=None, list=False, destroy=False, directory=None):
6194
return self.run_for_list(directory=directory)
6195
from bzrlib.shelf_ui import Shelver
6197
writer = bzrlib.option.diff_writer_registry.get()
6199
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
6200
file_list, message, destroy=destroy, directory=directory)
6205
except errors.UserAbort:
6208
def run_for_list(self, directory=None):
6209
if directory is None:
6211
tree = WorkingTree.open_containing(directory)[0]
6212
self.add_cleanup(tree.lock_read().unlock)
6213
manager = tree.get_shelf_manager()
6214
shelves = manager.active_shelves()
6215
if len(shelves) == 0:
6216
note('No shelved changes.')
6218
for shelf_id in reversed(shelves):
6219
message = manager.get_metadata(shelf_id).get('message')
6221
message = '<no message>'
6222
self.outf.write('%3d: %s\n' % (shelf_id, message))
6226
class cmd_unshelve(Command):
6227
__doc__ = """Restore shelved changes.
6229
By default, the most recently shelved changes are restored. However if you
6230
specify a shelf by id those changes will be restored instead. This works
6231
best when the changes don't depend on each other.
6234
takes_args = ['shelf_id?']
6237
RegistryOption.from_kwargs(
6238
'action', help="The action to perform.",
6239
enum_switch=False, value_switches=True,
6240
apply="Apply changes and remove from the shelf.",
6241
dry_run="Show changes, but do not apply or remove them.",
6242
preview="Instead of unshelving the changes, show the diff that "
6243
"would result from unshelving.",
6244
delete_only="Delete changes without applying them.",
6245
keep="Apply changes but don't delete them.",
6248
_see_also = ['shelve']
6250
def run(self, shelf_id=None, action='apply', directory=u'.'):
6251
from bzrlib.shelf_ui import Unshelver
6252
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
6256
unshelver.tree.unlock()
6259
class cmd_clean_tree(Command):
6260
__doc__ = """Remove unwanted files from working tree.
6262
By default, only unknown files, not ignored files, are deleted. Versioned
6263
files are never deleted.
6265
Another class is 'detritus', which includes files emitted by bzr during
6266
normal operations and selftests. (The value of these files decreases with
6269
If no options are specified, unknown files are deleted. Otherwise, option
6270
flags are respected, and may be combined.
6272
To check what clean-tree will do, use --dry-run.
6274
takes_options = ['directory',
6275
Option('ignored', help='Delete all ignored files.'),
6276
Option('detritus', help='Delete conflict files, merge and revert'
6277
' backups, and failed selftest dirs.'),
6279
help='Delete files unknown to bzr (default).'),
6280
Option('dry-run', help='Show files to delete instead of'
6282
Option('force', help='Do not prompt before deleting.')]
6283
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6284
force=False, directory=u'.'):
6285
from bzrlib.clean_tree import clean_tree
6286
if not (unknown or ignored or detritus):
6290
clean_tree(directory, unknown=unknown, ignored=ignored,
6291
detritus=detritus, dry_run=dry_run, no_prompt=force)
6294
class cmd_reference(Command):
6295
__doc__ = """list, view and set branch locations for nested trees.
6297
If no arguments are provided, lists the branch locations for nested trees.
6298
If one argument is provided, display the branch location for that tree.
6299
If two arguments are provided, set the branch location for that tree.
6304
takes_args = ['path?', 'location?']
6306
def run(self, path=None, location=None):
6308
if path is not None:
6310
tree, branch, relpath =(
6311
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
6312
if path is not None:
6315
tree = branch.basis_tree()
6317
info = branch._get_all_reference_info().iteritems()
6318
self._display_reference_info(tree, branch, info)
6320
file_id = tree.path2id(path)
6322
raise errors.NotVersionedError(path)
6323
if location is None:
6324
info = [(file_id, branch.get_reference_info(file_id))]
6325
self._display_reference_info(tree, branch, info)
6327
branch.set_reference_info(file_id, path, location)
6329
def _display_reference_info(self, tree, branch, info):
6331
for file_id, (path, location) in info:
6333
path = tree.id2path(file_id)
6334
except errors.NoSuchId:
6336
ref_list.append((path, location))
6337
for path, location in sorted(ref_list):
6338
self.outf.write('%s %s\n' % (path, location))
6341
class cmd_export_pot(Command):
6342
__doc__ = """Export command helps and error messages in po format."""
6347
from bzrlib.export_pot import export_pot
6348
export_pot(self.outf)
6351
def _register_lazy_builtins():
6352
# register lazy builtins from other modules; called at startup and should
6353
# be only called once.
6354
for (name, aliases, module_name) in [
6355
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6356
('cmd_config', [], 'bzrlib.config'),
6357
('cmd_dpush', [], 'bzrlib.foreign'),
6358
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6359
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6360
('cmd_conflicts', [], 'bzrlib.conflicts'),
6361
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6362
('cmd_verify_signatures', [],
6363
'bzrlib.commit_signature_commands'),
6364
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6366
builtin_command_registry.register_lazy(name, aliases, module_name)