28
29
from bzrlib import (
35
config as _mod_config,
40
39
merge as _mod_merge,
45
43
revision as _mod_revision,
54
50
from bzrlib.branch import Branch
55
51
from bzrlib.conflicts import ConflictList
56
from bzrlib.transport import memory
57
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
52
from bzrlib.revisionspec import RevisionSpec
58
53
from bzrlib.smtp_connection import SMTPConnection
59
54
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)
57
from bzrlib.commands import Command, display_command
58
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
from bzrlib.trace import mutter, note, warning, is_quiet, info
62
def tree_files(file_list, default_branch=u'.'):
64
return internal_tree_files(file_list, default_branch)
65
except errors.FileInWrongBranch, e:
66
raise errors.BzrCommandError("%s is not in the same branch as %s" %
67
(e.path, file_list[0]))
152
70
# XXX: Bad function name; should possibly also be a class method of
153
71
# 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,
72
def internal_tree_files(file_list, default_branch=u'.'):
157
73
"""Convert command-line paths to a WorkingTree and relative paths.
159
Deprecated: use WorkingTree.open_containing_paths instead.
161
75
This is typically used for command-line processors that take one or
162
76
more filenames, and infer the workingtree that contains them.
164
78
The filenames given are not required to exist.
166
:param file_list: Filenames to convert.
80
:param file_list: Filenames to convert.
168
82
: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
85
: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)
87
if file_list is None or len(file_list) == 0:
88
return WorkingTree.open_containing(default_branch)[0], file_list
89
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
90
return tree, safe_relpath_files(tree, file_list)
93
def safe_relpath_files(tree, file_list):
94
"""Convert file_list into a list of relpaths in tree.
96
:param tree: A tree to operate on.
97
:param file_list: A list of user provided paths or None.
98
:return: A list of relative paths.
99
:raises errors.PathNotChild: When a provided path is in a different tree
102
if file_list is None:
105
for filename in file_list:
107
new_list.append(tree.relpath(osutils.dereference_path(filename)))
108
except errors.PathNotChild:
109
raise errors.FileInWrongBranch(tree.branch, filename)
202
113
# TODO: Make sure no commands unconditionally use the working directory as a
249
155
files or directories is reported. If a directory is given, status
250
156
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'.
158
If a revision argument is given, the status is calculated against
159
that revision, or between two revisions if two are provided.
265
162
# TODO: --no-recurse, --recurse options
267
164
takes_args = ['file*']
268
takes_options = ['show-ids', 'revision', 'change', 'verbose',
165
takes_options = ['show-ids', 'revision', 'change',
269
166
Option('short', help='Use short status indicators.',
271
168
Option('versioned', help='Only show versioned files.',
273
170
Option('no-pending', help='Don\'t show pending merges.',
275
Option('no-classify',
276
help='Do not mark object type using indicator.',
279
173
aliases = ['st', 'stat']
281
175
encoding_type = 'replace'
282
176
_see_also = ['diff', 'revert', 'status-flags']
285
179
def run(self, show_ids=False, file_list=None, revision=None, short=False,
286
versioned=False, no_pending=False, verbose=False,
180
versioned=False, no_pending=False):
288
181
from bzrlib.status import show_tree_status
290
183
if revision and len(revision) > 2:
291
184
raise errors.BzrCommandError('bzr status --revision takes exactly'
292
185
' 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:
187
tree, file_list = tree_files(file_list)
304
189
show_tree_status(tree, show_ids=show_ids,
305
specific_files=relfile_list, revision=revision,
190
specific_files=file_list, revision=revision,
306
191
to_file=self.outf, short=short, versioned=versioned,
307
show_pending=(not no_pending), verbose=verbose,
308
classify=not no_classify)
192
show_pending=not no_pending)
311
195
class cmd_cat_revision(Command):
312
__doc__ = """Write out metadata for a revision.
196
"""Write out metadata for a revision.
314
198
The revision to print can either be specified by a specific
315
199
revision identifier, or you can use --revision.
319
203
takes_args = ['revision_id?']
320
takes_options = ['directory', 'revision']
204
takes_options = ['revision']
321
205
# cat-revision is more for frontends so should be exact
322
206
encoding = 'strict'
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'.'):
209
def run(self, revision_id=None, revision=None):
334
210
if revision_id is not None and revision is not None:
335
211
raise errors.BzrCommandError('You can only supply one of'
336
212
' revision_id or --revision')
337
213
if revision_id is None and revision is None:
338
214
raise errors.BzrCommandError('You must supply either'
339
215
' --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,))
216
b = WorkingTree.open_containing(u'.')[0].branch
218
# TODO: jam 20060112 should cat-revision always output utf-8?
219
if revision_id is not None:
220
revision_id = osutils.safe_revision_id(revision_id, warn=False)
221
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
222
elif revision is not None:
225
raise errors.BzrCommandError('You cannot specify a NULL'
227
rev_id = rev.as_revision_id(b)
228
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
454
231
class cmd_remove_tree(Command):
455
__doc__ = """Remove the working tree from a given branch/checkout.
232
"""Remove the working tree from a given branch/checkout.
457
234
Since a lightweight checkout is little more than a working tree
458
235
this will refuse to run against one.
460
237
To re-create the working tree, use "bzr checkout".
462
239
_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]
241
takes_args = ['location?']
243
def run(self, location='.'):
244
d = bzrdir.BzrDir.open(location)
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'
247
working = d.open_workingtree()
248
except errors.NoWorkingTree:
249
raise errors.BzrCommandError("No working tree to remove")
250
except errors.NotLocalUrl:
251
raise errors.BzrCommandError("You cannot remove the working tree of a "
254
working_path = working.bzrdir.root_transport.base
255
branch_path = working.branch.bzrdir.root_transport.base
256
if working_path != branch_path:
257
raise errors.BzrCommandError("You cannot remove the working tree from "
258
"a lightweight checkout")
260
d.destroy_workingtree()
550
263
class cmd_revno(Command):
551
__doc__ = """Show current revision number.
264
"""Show current revision number.
553
266
This is equal to the number of revisions on this branch.
556
269
_see_also = ['info']
557
270
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')
273
def run(self, location=u'.'):
274
self.outf.write(str(Branch.open_containing(location)[0].revno()))
275
self.outf.write('\n')
584
278
class cmd_revision_info(Command):
585
__doc__ = """Show revision number and revision id for a given revision identifier.
279
"""Show revision number and revision id for a given revision identifier.
588
282
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'),
283
takes_options = ['revision']
598
def run(self, revision=None, directory=u'.', tree=False,
599
revision_info_list=[]):
286
def run(self, revision=None, 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
289
if revision is not None:
611
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
290
revs.extend(revision)
612
291
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:
292
for rev in revision_info_list:
293
revs.append(RevisionSpec.from_string(rev))
295
b = Branch.open_containing(u'.')[0]
298
revs.append(RevisionSpec.from_string('-1'))
301
revision_id = rev.as_revision_id(b)
629
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
630
revno = '.'.join(str(i) for i in dotted_revno)
303
revno = '%4d' % (b.revision_id_to_revno(revision_id))
631
304
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]))
305
dotted_map = b.get_revision_id_to_revno_map()
306
revno = '.'.join(str(i) for i in dotted_map[revision_id])
307
print '%s %s' % (revno, revision_id)
641
310
class cmd_add(Command):
642
__doc__ = """Add specified files or directories.
311
"""Add specified files or directories.
644
313
In non-recursive mode, all the named items are added, regardless
645
314
of whether they were previously ignored. A warning is given if
892
556
into_existing = False
894
558
inv = tree.inventory
895
# 'fix' the case of a potential 'from'
896
from_id = tree.path2id(
897
tree.get_canonical_inventory_path(rel_names[0]))
559
from_id = tree.path2id(rel_names[0])
898
560
if (not osutils.lexists(names_list[0]) and
899
561
from_id and inv.get_file_kind(from_id) == "directory"):
900
562
into_existing = False
902
564
if into_existing:
903
565
# 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))
566
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
567
self.outf.write("%s => %s\n" % pair)
911
569
if len(names_list) != 2:
912
570
raise errors.BzrCommandError('to mv multiple files the'
913
571
' 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))
573
tree.rename_one(rel_names[0], rel_names[1], after=after)
574
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
963
577
class cmd_pull(Command):
964
__doc__ = """Turn this branch into a mirror of another branch.
578
"""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
580
This command only works on branches that have not diverged. Branches are
581
considered diverged if the destination branch's most recent commit is one
582
that has not been merged (directly or indirectly) into the parent.
971
584
If branches have diverged, you can use 'bzr merge' to integrate the changes
972
585
from one into the other. Once one branch has merged, the other should
973
586
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.
588
If you want to forget your local changes and just update your branch to
589
match the remote one, use pull --overwrite.
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.
591
If there is no default location set, the first pull will set it. After
592
that, you can omit the location to use the default. To change the
593
default, use --remember. The value will only be saved if the remote
594
location can be accessed.
984
596
Note: The location can be specified either in the form of a branch,
985
597
or in the form of a path to a file containing a merge directive generated
989
_see_also = ['push', 'update', 'status-flags', 'send']
601
_see_also = ['push', 'update', 'status-flags']
990
602
takes_options = ['remember', 'overwrite', 'revision',
991
603
custom_help('verbose',
992
604
help='Show logs of pulled revisions.'),
993
custom_help('directory',
994
606
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 "
607
'rather than the one containing the working directory.',
1002
help="Show base revision text in conflicts.")
1004
612
takes_args = ['location?']
1005
613
encoding_type = 'replace'
1007
def run(self, location=None, remember=None, overwrite=False,
615
def run(self, location=None, remember=False, overwrite=False,
1008
616
revision=None, verbose=False,
1009
directory=None, local=False,
1011
618
# FIXME: too much stuff is in the command class
1012
619
revision_id = None
1013
620
mergeable = None
1220
815
To retrieve the branch as of a particular revision, supply the --revision
1221
816
parameter, as in "branch foo/bar -r 5".
1223
The synonyms 'clone' and 'get' for this command are deprecated.
1226
819
_see_also = ['checkout']
1227
820
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."),
821
takes_options = ['revision', Option('hardlink',
822
help='Hard-link working tree files where possible.'),
1237
823
Option('stacked',
1238
824
help='Create a stacked branch referring to the source branch. '
1239
825
'The new branch will depend on the availability of the source '
1240
826
'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
828
aliases = ['get', 'clone']
1253
830
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
831
hardlink=False, stacked=False):
1258
832
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')
835
elif len(revision) > 1:
836
raise errors.BzrCommandError(
837
'bzr branch --revision takes exactly 1 revision value')
1265
839
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))
843
if len(revision) == 1 and revision[0] is not None:
844
revision_id = revision[0].as_revision_id(br_from)
846
# FIXME - wt.last_revision, fallback to branch, fall back to
847
# None or perhaps NULL_REVISION to mean copy nothing
849
revision_id = br_from.last_revision()
850
if to_location is None:
851
to_location = urlutils.derive_to_location(from_location)
852
to_transport = transport.get_transport(to_location)
854
to_transport.mkdir('.')
855
except errors.FileExists:
856
raise errors.BzrCommandError('Target directory "%s" already'
857
' exists.' % to_location)
858
except errors.NoSuchFile:
859
raise errors.BzrCommandError('Parent of "%s" does not exist.'
862
# preserve whatever source format we have.
863
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
864
possible_transports=[to_transport],
865
accelerator_tree=accelerator_tree,
866
hardlink=hardlink, stacked=stacked)
867
branch = dir.open_branch()
868
except errors.NoSuchRevision:
869
to_transport.delete_tree('.')
870
msg = "The branch %s has no revision %s." % (from_location,
872
raise errors.BzrCommandError(msg)
873
_merge_tags_if_possible(br_from, branch)
874
# If the source branch is stacked, the new branch may
875
# be stacked whether we asked for that explicitly or not.
876
# We therefore need a try/except here and not just 'if stacked:'
878
note('Created new stacked branch referring to %s.' %
879
branch.get_stacked_on_url())
880
except (errors.NotStacked, errors.UnstackableBranchFormat,
881
errors.UnstackableRepositoryFormat), e:
882
note('Branched %d revision(s).' % branch.revno())
1357
887
class cmd_checkout(Command):
1358
__doc__ = """Create a new checkout of an existing branch.
888
"""Create a new checkout of an existing branch.
1360
890
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1361
891
the branch found in '.'. This is useful if you have removed the working tree
1362
892
or if it was never created - i.e. if you pushed the branch to its current
1363
893
location using SFTP.
1365
895
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1366
896
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1367
897
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1440
969
@display_command
1441
970
def run(self, dir=u'.'):
1442
971
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))
974
new_inv = tree.inventory
975
old_tree = tree.basis_tree()
978
old_inv = old_tree.inventory
979
renames = list(_mod_tree.find_renames(old_inv, new_inv))
981
for old_name, new_name in renames:
982
self.outf.write("%s => %s\n" % (old_name, new_name))
1461
989
class cmd_update(Command):
1462
__doc__ = """Update a tree to have the latest code committed to its branch.
990
"""Update a tree to have the latest code committed to its branch.
1464
992
This will perform a merge into the working tree, and may generate
1465
conflicts. If you have any local changes, you will still
993
conflicts. If you have any local changes, you will still
1466
994
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
996
If you want to discard your local changes, you can just do a
1469
997
'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
1000
_see_also = ['pull', 'working-trees', 'status-flags']
1479
1001
takes_args = ['dir?']
1480
takes_options = ['revision',
1482
help="Show base revision text in conflicts."),
1484
1002
aliases = ['up']
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")
1004
def run(self, dir='.'):
1490
1005
tree = WorkingTree.open_containing(dir)[0]
1491
branch = tree.branch
1492
1006
possible_transports = []
1493
master = branch.get_master_branch(
1007
master = tree.branch.get_master_branch(
1494
1008
possible_transports=possible_transports)
1495
1009
if master is not None:
1496
branch_location = master.base
1497
1010
tree.lock_write()
1499
branch_location = tree.branch.base
1500
1012
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)
1014
existing_pending_merges = tree.get_parent_ids()[1:]
1015
last_rev = _mod_revision.ensure_null(tree.last_revision())
1016
if last_rev == _mod_revision.ensure_null(
1017
tree.branch.last_revision()):
1018
# may be up to date, check master too.
1019
if master is None or last_rev == _mod_revision.ensure_null(
1020
master.last_revision()):
1021
revno = tree.branch.revision_id_to_revno(last_rev)
1022
note("Tree is up to date at revision %d." % (revno,))
1528
1024
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'.")
1025
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1026
possible_transports=possible_transports)
1027
revno = tree.branch.revision_id_to_revno(
1028
_mod_revision.ensure_null(tree.last_revision()))
1029
note('Updated to revision %d.' % (revno,))
1030
if tree.get_parent_ids()[1:] != existing_pending_merges:
1031
note('Your local commits will now show as pending merges with '
1032
"'bzr status', and can be committed with 'bzr commit'.")
1554
1041
class cmd_info(Command):
1555
__doc__ = """Show information about a working tree, branch or repository.
1042
"""Show information about a working tree, branch or repository.
1557
1044
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.
1045
tree, branch or repository. Statistical information is included with
1564
1048
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
1050
_see_also = ['revno', 'working-trees', 'repositories']
1583
1051
takes_args = ['location?']
1610
1077
RegistryOption.from_kwargs('file-deletion-strategy',
1611
1078
'The file deletion mode to be used.',
1612
1079
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.',
1080
safe='Only delete files if they can be'
1081
' safely recovered (default).',
1082
keep="Don't delete any files.",
1616
1083
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)')]
1084
'recovered and even if they are non-empty directories.')]
1619
1085
aliases = ['rm', 'del']
1620
1086
encoding_type = 'replace'
1622
1088
def run(self, file_list, verbose=False, new=False,
1623
1089
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)
1090
tree, file_list = tree_files(file_list)
1631
1092
if file_list is not None:
1632
1093
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'))
1097
# Heuristics should probably all move into tree.remove_smart or
1100
added = tree.changes_from(tree.basis_tree(),
1101
specific_files=file_list).added
1102
file_list = sorted([f[0] for f in added], reverse=True)
1103
if len(file_list) == 0:
1104
raise errors.BzrCommandError('No matching files.')
1105
elif file_list is None:
1106
# missing files show up in iter_changes(basis) as
1107
# versioned-with-no-kind.
1109
for change in tree.iter_changes(tree.basis_tree()):
1110
# Find paths in the working tree that have no kind:
1111
if change[1][1] is not None and change[6][1] is None:
1112
missing.append(change[1][1])
1113
file_list = sorted(missing, reverse=True)
1114
file_deletion_strategy = 'keep'
1115
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1116
keep_files=file_deletion_strategy=='keep',
1117
force=file_deletion_strategy=='force')
1658
1122
class cmd_file_id(Command):
1659
__doc__ = """Print file_id of a particular file or directory.
1123
"""Print file_id of a particular file or directory.
1661
1125
The file_id is assigned when the file is first added and remains the
1662
1126
same through all revisions where the file exists, even when it is
2217
1615
raise errors.BzrCommandError(msg)
2220
def _parse_levels(s):
2224
msg = "The levels argument must be an integer."
2225
raise errors.BzrCommandError(msg)
2228
1618
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.
1619
"""Show log of a branch, file, or directory.
1621
By default show the log of the branch containing the working directory.
1623
To request a range of logs, you can use the command -r begin..end
1624
-r revision requests a specific revision, -r ..end or -r begin.. are
1628
Log the current branch::
1636
Log the last 10 revisions of a branch::
1638
bzr log -r -10.. http://server/branch
2383
takes_args = ['file*']
2384
_see_also = ['log-formats', 'revisionspec']
1641
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1643
takes_args = ['location?']
2385
1644
takes_options = [
2386
1645
Option('forward',
2387
1646
help='Show from oldest to newest.'),
1649
help='Display timezone as local, original, or utc.'),
2389
1650
custom_help('verbose',
2390
1651
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),
2409
1655
Option('message',
2410
1657
help='Show revisions whose message matches this '
2411
1658
'regular expression.',
2414
1660
Option('limit',
2415
1661
short_name='l',
2416
1662
help='Limit the output to the first N revisions.',
2418
1664
type=_parse_limit),
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
1666
encoding_type = 'replace'
2454
1668
@display_command
2455
def run(self, file_list=None, timezone='original',
1669
def run(self, location=None, timezone='original',
2457
1671
show_ids=False,
2461
1674
log_format=None,
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,
1677
from bzrlib.log import show_log
2481
1678
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:
1683
# find the file id to log:
1685
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1689
tree = b.basis_tree()
1690
file_id = tree.path2id(fp)
2509
1691
if file_id is None:
2510
1692
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'])
1693
"Path does not have any revision history: %s" %
2523
# FIXME ? log the current subdir only RBC 20060203
1697
# FIXME ? log the current subdir only RBC 20060203
2524
1698
if revision is not None \
2525
1699
and len(revision) > 0 and revision[0].get_branch():
2526
1700
location = revision[0].get_branch()
2529
1703
dir, relpath = bzrdir.BzrDir.open_containing(location)
2530
1704
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
1708
if revision is None:
1711
elif len(revision) == 1:
1712
rev1 = rev2 = revision[0].in_history(b)
1713
elif len(revision) == 2:
1714
if revision[1].get_branch() != revision[0].get_branch():
1715
# b is taken from revision[0].get_branch(), and
1716
# show_log will use its revision_history. Having
1717
# different branches will lead to weird behaviors.
1718
raise errors.BzrCommandError(
1719
"Log doesn't accept two revisions in different"
1721
rev1 = revision[0].in_history(b)
1722
rev2 = revision[1].in_history(b)
1724
raise errors.BzrCommandError(
1725
'bzr log --revision takes one or two values.')
1727
if log_format is None:
1728
log_format = log.log_formatter_registry.get_default(b)
1730
lf = log_format(show_ids=show_ids, to_file=self.outf,
1731
show_timezone=timezone)
1737
direction=direction,
1738
start_revision=rev1,
2657
1746
def get_log_format(long=False, short=False, line=False, default='long'):
2658
1747
log_format = default
2729
1816
if path is None:
2733
1821
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
1825
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
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')
1831
if revision is not None:
1832
tree = branch.repository.revision_tree(
1833
revision[0].as_revision_id(branch))
1835
tree = branch.basis_tree()
1839
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1840
if fp.startswith(relpath):
1841
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1842
if non_recursive and '/' in fp:
1844
if not all and not selection[fc]:
1846
if kind is not None and fkind != kind:
1849
kindch = entry.kind_character()
1850
outstring = '%-8s %s%s' % (fc, fp, kindch)
1851
if show_ids and fid is not None:
1852
outstring = "%-50s %s" % (outstring, fid)
1853
self.outf.write(outstring + '\n')
1855
self.outf.write(fp + '\0')
1858
self.outf.write(fid)
1859
self.outf.write('\0')
1867
self.outf.write('%-50s %s\n' % (fp, my_id))
1869
self.outf.write(fp + '\n')
2805
1874
class cmd_unknowns(Command):
2806
__doc__ = """List unknown files.
1875
"""List unknown files.
2810
1879
_see_also = ['ls']
2811
takes_options = ['directory']
2813
1881
@display_command
2814
def run(self, directory=u'.'):
2815
for f in WorkingTree.open_containing(directory)[0].unknowns():
1883
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2816
1884
self.outf.write(osutils.quotefn(f) + '\n')
2819
1887
class cmd_ignore(Command):
2820
__doc__ = """Ignore specified files or patterns.
1888
"""Ignore specified files or patterns.
2822
1890
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
1892
To remove patterns from the ignore list, edit the .bzrignore file.
2831
1893
After adding, editing or deleting that file either indirectly by
2832
1894
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.
1897
Note: ignore patterns containing shell wildcards must be quoted from
2857
1901
Ignore the top level Makefile::
2859
1903
bzr ignore ./Makefile
2861
Ignore .class files in all directories...::
1905
Ignore class files in all directories::
2863
1907
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
1909
Ignore .o files under the lib directory::
2875
1911
bzr ignore "lib/**/*.o"
3018
2037
================= =========================
3021
2039
takes_args = ['dest', 'branch_or_subdir?']
3022
takes_options = ['directory',
3023
2041
Option('format',
3024
2042
help="Type of file to export to.",
3027
Option('filters', help='Apply content filters to export the '
3028
'convenient form.'),
3031
2047
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
2049
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3037
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
3038
2051
from bzrlib.export import export
3040
2053
if branch_or_subdir is None:
3041
tree = WorkingTree.open_containing(directory)[0]
2054
tree = WorkingTree.open_containing(u'.')[0]
3042
2055
b = tree.branch
3045
2058
b, subdir = Branch.open_containing(branch_or_subdir)
3048
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2060
if revision is None:
2061
# should be tree.last_revision FIXME
2062
rev_id = b.last_revision()
2064
if len(revision) != 1:
2065
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2066
rev_id = revision[0].as_revision_id(b)
2067
t = b.repository.revision_tree(rev_id)
3050
export(rev_tree, dest, format, root, subdir, filtered=filters,
3051
per_file_timestamps=per_file_timestamps)
2069
export(t, dest, format, root, subdir)
3052
2070
except errors.NoSuchExportFormat, e:
3053
2071
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3056
2074
class cmd_cat(Command):
3057
__doc__ = """Write the contents of a file as of a given revision to standard output.
2075
"""Write the contents of a file as of a given revision to standard output.
3059
2077
If no revision is nominated, the last revision is used.
3061
2079
Note: Take care to redirect standard output when using this command on a
3065
2083
_see_also = ['ls']
3066
takes_options = ['directory',
3067
2085
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
2088
takes_args = ['filename']
3073
2089
encoding_type = 'exact'
3075
2091
@display_command
3076
def run(self, filename, revision=None, name_from_revision=False,
3077
filters=False, directory=None):
2092
def run(self, filename, revision=None, name_from_revision=False):
3078
2093
if revision is not None and len(revision) != 1:
3079
2094
raise errors.BzrCommandError("bzr cat --revision takes exactly"
3080
2095
" one revision specifier")
3081
2096
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)
2097
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2100
return self._run(tree, branch, relpath, filename, revision,
3087
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2105
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
3089
2106
if tree is None:
3090
2107
tree = b.basis_tree()
3091
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3092
self.add_cleanup(rev_tree.lock_read().unlock)
2108
if revision is None:
2109
revision_id = b.last_revision()
2111
revision_id = revision[0].as_revision_id(b)
2113
cur_file_id = tree.path2id(relpath)
2114
rev_tree = b.repository.revision_tree(revision_id)
3094
2115
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
2117
if name_from_revision:
3101
# Try in revision if requested
3102
2118
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)
2119
raise errors.BzrCommandError("%r is not present in revision %s"
2120
% (filename, revision_id))
2122
content = rev_tree.get_file_text(old_file_id)
2123
elif cur_file_id is not None:
2124
content = rev_tree.get_file_text(cur_file_id)
2125
elif old_file_id is not None:
2126
content = rev_tree.get_file_text(old_file_id)
2128
raise errors.BzrCommandError("%r is not present in revision %s" %
2129
(filename, revision_id))
3126
2130
self.outf.write(content)
3129
2133
class cmd_local_time_offset(Command):
3130
__doc__ = """Show the offset in seconds from GMT to local time."""
2134
"""Show the offset in seconds from GMT to local time."""
3132
2136
@display_command
3134
self.outf.write("%s\n" % osutils.local_time_offset())
2138
print osutils.local_time_offset()
3138
2142
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.
2143
"""Commit changes into a new revision.
2145
If no arguments are given, the entire tree is committed.
2147
If selected files are specified, only changes to those files are
2148
committed. If a directory is specified then the directory and everything
2149
within it is committed.
2151
When excludes are given, they take precedence over selected files.
2152
For example, too commit only changes within foo, but not changes within
2155
bzr commit foo -x foo/bar
2157
If author of the change is not the same person as the committer, you can
2158
specify the author's name using the --author option. The name should be
2159
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2161
A selected-file commit may fail in some cases where the committed
2162
tree would be invalid. Consider::
2167
bzr commit foo -m "committing foo"
2168
bzr mv foo/bar foo/baz
2171
bzr commit foo/bar -m "committing bar but not baz"
2173
In the example above, the last commit will fail by design. This gives
2174
the user the opportunity to decide whether they want to commit the
2175
rename at the same time, separately first, or not at all. (As a general
2176
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2178
Note: A selected-file commit after a merge is not yet supported.
3195
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
2180
# TODO: Run hooks on tree to-be-committed, and after commit.
2182
# TODO: Strict commit that fails if there are deleted files.
2183
# (what does "deleted files" mean ??)
2185
# TODO: Give better message for -s, --summary, used by tla people
2187
# XXX: verbose currently does nothing
2189
_see_also = ['bugs', 'uncommit']
3196
2190
takes_args = ['selected*']
3197
2191
takes_options = [
3198
2192
ListOption('exclude', type=str, short_name='x',
3306
2274
if fixes is None:
3308
bug_property = bugtracker.encode_fixes_bug_urls(
3309
self._iter_bug_fix_urls(fixes, tree.branch))
2276
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
3310
2277
if bug_property:
3311
2278
properties['bugs'] = bug_property
3313
2280
if local and not tree.branch.get_bound_location():
3314
2281
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
2283
def get_message(commit_obj):
3338
2284
"""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,
2285
my_message = message
2286
if my_message is None and not file:
2287
t = make_commit_message_template_encoded(tree,
3351
2288
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)
2289
output_encoding=bzrlib.user_encoding)
2290
my_message = edit_commit_message_encoded(t)
3363
2291
if my_message is None:
3364
2292
raise errors.BzrCommandError("please specify a commit"
3365
2293
" 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 \"\".")
2294
elif my_message and file:
2295
raise errors.BzrCommandError(
2296
"please specify either --message or --file")
2298
my_message = codecs.open(file, 'rt',
2299
bzrlib.user_encoding).read()
2300
if my_message == "":
2301
raise errors.BzrCommandError("empty commit message specified")
3371
2302
return my_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
2305
tree.commit(message_callback=get_message,
3379
2306
specific_files=selected_list,
3380
2307
allow_pointless=unchanged, strict=strict, local=local,
3381
2308
reporter=None, verbose=verbose, revprops=properties,
3382
authors=author, timestamp=commit_stamp,
3384
exclude=tree.safe_relpath_files(exclude),
2310
exclude=safe_relpath_files(tree, exclude))
3386
2311
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.")
2312
# FIXME: This should really happen before the file is read in;
2313
# perhaps prepare the commit; get the message; then actually commit
2314
raise errors.BzrCommandError("no changes to commit."
2315
" use --unchanged to commit anyhow")
3390
2316
except ConflictsInTree:
3391
2317
raise errors.BzrCommandError('Conflicts detected in working '
3392
2318
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3765
2627
'throughout the test suite.',
3766
2628
type=get_transport_type),
3767
2629
Option('benchmark',
3768
help='Run the benchmarks rather than selftests.',
2630
help='Run the benchmarks rather than selftests.'),
3770
2631
Option('lsprof-timed',
3771
2632
help='Generate lsprof output for benchmarked'
3772
2633
' sections of code.'),
3773
Option('lsprof-tests',
3774
help='Generate lsprof output for each test.'),
2634
Option('cache-dir', type=str,
2635
help='Cache intermediate benchmark output in this '
3775
2637
Option('first',
3776
2638
help='Run all tests, but run specified tests first.',
3777
2639
short_name='f',
3779
2641
Option('list-only',
3780
2642
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
2643
Option('randomize', type=str, argname="SEED",
3787
2644
help='Randomize the order of tests using the given'
3788
2645
' 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.'),
2646
Option('exclude', type=str, argname="PATTERN",
2648
help='Exclude tests that match this regular'
3795
2650
Option('strict', help='Fail on missing dependencies or '
3796
2651
'known failures.'),
3797
2652
Option('load-list', type=str, argname='TESTLISTFILE',
3798
2653
help='Load a test id list from a text file.'),
3799
2654
ListOption('debugflag', type=str, short_name='E',
3800
2655
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.")
2656
Option('starting-with', type=str, argname='TESTID',
2658
help='Load only the tests starting with TESTID.'),
3809
2660
encoding_type = 'replace'
3812
Command.__init__(self)
3813
self.additional_selftest_args = {}
3815
2662
def run(self, testspecs_list=None, verbose=False, one=False,
3816
2663
transport=None, benchmark=None,
2664
lsprof_timed=None, cache_dir=None,
3818
2665
first=False, list_only=False,
3819
2666
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
2667
load_list=None, debugflag=None, starting_with=None):
2669
from bzrlib.tests import selftest
2670
import bzrlib.benchmarks as benchmarks
2671
from bzrlib.benchmarks import tree_creator
2673
# Make deprecation warnings visible, unless -Werror is set
2674
symbol_versioning.activate_deprecation_warnings(override=False)
2676
if cache_dir is not None:
2677
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2679
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2680
print ' %s (%s python%s)' % (
2682
bzrlib.version_string,
2683
bzrlib._format_version_tuple(sys.version_info),
3825
2686
if testspecs_list is not None:
3826
2687
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
2691
test_suite_factory = benchmarks.test_suite
2692
# Unless user explicitly asks for quiet, be verbose in benchmarks
2693
verbose = not is_quiet()
2694
# TODO: should possibly lock the history file...
2695
benchfile = open(".perf_history", "at", buffering=1)
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(
2697
test_suite_factory = None
3881
result = tests.selftest(**selftest_kwargs)
2700
result = selftest(verbose=verbose,
2702
stop_on_failure=one,
2703
transport=transport,
2704
test_suite_factory=test_suite_factory,
2705
lsprof_timed=lsprof_timed,
2706
bench_history=benchfile,
2707
matching_tests_first=first,
2708
list_only=list_only,
2709
random_seed=randomize,
2710
exclude_pattern=exclude,
2712
load_list=load_list,
2713
debug_flags=debugflag,
2714
starting_with=starting_with,
2717
if benchfile is not None:
2720
note('tests passed')
2722
note('tests failed')
3884
2723
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
2726
class cmd_version(Command):
3897
__doc__ = """Show version of bzr."""
2727
"""Show version of bzr."""
3899
2729
encoding_type = 'replace'
3900
2730
takes_options = [
3913
2743
class cmd_rocks(Command):
3914
__doc__ = """Statement of optimism."""
2744
"""Statement of optimism."""
3918
2748
@display_command
3920
self.outf.write("It sure does!\n")
2750
print "It sure does!"
3923
2753
class cmd_find_merge_base(Command):
3924
__doc__ = """Find and print a base revision for merging two branches."""
2754
"""Find and print a base revision for merging two branches."""
3925
2755
# TODO: Options to specify revisions on either side, as if
3926
2756
# merging only part of the history.
3927
2757
takes_args = ['branch', 'other']
3930
2760
@display_command
3931
2761
def run(self, branch, other):
3932
2762
from bzrlib.revision import ensure_null
3934
2764
branch1 = Branch.open_containing(branch)[0]
3935
2765
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)
2770
last1 = ensure_null(branch1.last_revision())
2771
last2 = ensure_null(branch2.last_revision())
2773
graph = branch1.repository.get_graph(branch2.repository)
2774
base_rev_id = graph.find_unique_lca(last1, last2)
2776
print 'merge base is revision %s' % base_rev_id
3947
2783
class cmd_merge(Command):
3948
__doc__ = """Perform a three-way merge.
2784
"""Perform a three-way merge.
3950
2786
The source of the merge can be specified either in the form of a branch,
3951
2787
or in the form of a path to a file containing a merge directive generated
3952
2788
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.
2789
or the branch most recently merged using --remember.
2791
When merging a branch, by default the tip will be merged. To pick a different
2792
revision, pass --revision. If you specify two values, the first will be used as
2793
BASE and the second one as OTHER. Merging individual revisions, or a subset of
2794
available revisions, like this is commonly referred to as "cherrypicking".
2796
Revision numbers are always relative to the branch being merged.
2798
By default, bzr will try to merge in all new work from the other
2799
branch, automatically determining an appropriate base. If this
2800
fails, you may need to give an explicit base.
3975
2802
Merge will do its best to combine the changes in two branches, but there
3976
2803
are some kinds of problems only a human can fix. When it encounters those,
3977
2804
it will mark a conflict. A conflict means that you need to fix something,
4070
2879
allow_pending = True
4071
2880
verified = 'inapplicable'
4073
2881
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')
2882
change_reporter = delta._ChangeReporter(
2883
unversioned_filter=tree.is_ignored)
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:
2886
pb = ui.ui_factory.nested_progress_bar()
2887
cleanups.append(pb.finished)
2889
cleanups.append(tree.unlock)
2890
if location is not None:
2892
mergeable = bundle.read_mergeable_from_url(location,
2893
possible_transports=possible_transports)
2894
except errors.NotABundle:
2898
raise errors.BzrCommandError('Cannot use --uncommitted'
2899
' with bundles or merge directives.')
2901
if revision is not None:
2902
raise errors.BzrCommandError(
2903
'Cannot use -r with merge directives or bundles')
2904
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2907
if merger is None and uncommitted:
2908
if revision is not None and len(revision) > 0:
2909
raise errors.BzrCommandError('Cannot use --uncommitted and'
2910
' --revision at the same time.')
2911
location = self._select_branch_location(tree, location)[0]
2912
other_tree, other_path = WorkingTree.open_containing(location)
2913
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2915
allow_pending = False
2916
if other_path != '':
2917
merger.interesting_files = [other_path]
2920
merger, allow_pending = self._get_merger_from_branch(tree,
2921
location, revision, remember, possible_transports, pb)
2923
merger.merge_type = merge_type
2924
merger.reprocess = reprocess
2925
merger.show_base = show_base
2926
self.sanity_check_merger(merger)
2927
if (merger.base_rev_id == merger.other_rev_id and
2928
merger.other_rev_id is not None):
2929
note('Nothing to do.')
2932
if merger.interesting_files is not None:
2933
raise errors.BzrCommandError('Cannot pull individual files')
2934
if (merger.base_rev_id == tree.last_revision()):
2935
result = tree.pull(merger.other_branch, False,
2936
merger.other_rev_id)
2937
result.report(self.outf)
2939
merger.check_basis(not force)
2941
return self._do_preview(merger)
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):
2943
return self._do_merge(merger, change_reporter, allow_pending,
2946
for cleanup in reversed(cleanups):
2949
def _do_preview(self, merger):
2950
from bzrlib.diff import show_diff_trees
4158
2951
tree_merger = merger.make_merger()
4159
2952
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)
2954
result_tree = tt.get_preview_tree()
2955
show_diff_trees(merger.this_tree, result_tree, self.outf,
2956
old_label='', new_label='')
4172
2960
def _do_merge(self, merger, change_reporter, allow_pending, verified):
4173
2961
merger.change_reporter = change_reporter
4366
3105
def run(self, file_list=None, merge_type=None, show_base=False,
4367
3106
reprocess=False):
4368
from bzrlib.conflicts import restore
4369
3107
if merge_type is None:
4370
3108
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:
3109
tree, file_list = tree_files(file_list)
3112
parents = tree.get_parent_ids()
3113
if len(parents) != 2:
3114
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3115
" merges. Not cherrypicking or"
3117
repository = tree.branch.repository
3118
interesting_ids = None
3120
conflicts = tree.conflicts()
3121
if file_list is not None:
3122
interesting_ids = set()
3123
for filename in file_list:
3124
file_id = tree.path2id(filename)
3126
raise errors.NotVersionedError(filename)
3127
interesting_ids.add(file_id)
3128
if tree.kind(file_id) != "directory":
3131
for name, ie in tree.inventory.iter_entries(file_id):
3132
interesting_ids.add(ie.file_id)
3133
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3135
# Remerge only supports resolving contents conflicts
3136
allowed_conflicts = ('text conflict', 'contents conflict')
3137
restore_files = [c.path for c in conflicts
3138
if c.typestring in allowed_conflicts]
3139
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3140
tree.set_conflicts(ConflictList(new_conflicts))
3141
if file_list is not None:
3142
restore_files = file_list
3143
for filename in restore_files:
3145
restore(tree.abspath(filename))
3146
except errors.NotConflicted:
3148
# Disable pending merges, because the file texts we are remerging
3149
# have not had those merges performed. If we use the wrong parents
3150
# list, we imply that the working tree text has seen and rejected
3151
# all the changes from the other tree, when in fact those changes
3152
# have not yet been seen.
3153
pb = ui.ui_factory.nested_progress_bar()
3154
tree.set_parent_ids(parents[:1])
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()
3156
merger = _mod_merge.Merger.from_revision_ids(pb,
3158
merger.interesting_ids = interesting_ids
3159
merger.merge_type = merge_type
3160
merger.show_base = show_base
3161
merger.reprocess = reprocess
3162
conflicts = merger.do_merge()
3164
tree.set_parent_ids(parents)
4423
tree.set_parent_ids(parents)
4424
3168
if conflicts > 0:
4640
3333
" or specified.")
4641
3334
display_url = urlutils.unescape_for_display(parent,
4642
3335
self.outf.encoding)
4643
message("Using saved parent location: "
4644
+ display_url + "\n")
3336
self.outf.write("Using last location: " + display_url + "\n")
4646
3338
remote_branch = Branch.open(other_branch)
4647
3339
if remote_branch.base == local_branch.base:
4648
3340
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")
3341
local_branch.lock_read()
3343
remote_branch.lock_read()
3345
local_extra, remote_extra = find_unmerged(
3346
local_branch, remote_branch, restrict)
3348
if log_format is None:
3349
registry = log.log_formatter_registry
3350
log_format = registry.get_default(local_branch)
3351
lf = log_format(to_file=self.outf,
3353
show_timezone='original')
3354
if reverse is False:
3355
if local_extra is not None:
3356
local_extra.reverse()
3357
if remote_extra is not None:
3358
remote_extra.reverse()
3361
if local_extra and not theirs_only:
3362
self.outf.write("You have %d extra revision(s):\n" %
3364
for revision in iter_log_revisions(local_extra,
3365
local_branch.repository,
3367
lf.log_revision(revision)
3368
printed_local = True
3371
printed_local = False
3373
if remote_extra and not mine_only:
3374
if printed_local is True:
3375
self.outf.write("\n\n\n")
3376
self.outf.write("You are missing %d revision(s):\n" %
3378
for revision in iter_log_revisions(remote_extra,
3379
remote_branch.repository,
3381
lf.log_revision(revision)
3384
if mine_only and not local_extra:
3385
# We checked local, and found nothing extra
3386
self.outf.write('This branch is up to date.\n')
3387
elif theirs_only and not remote_extra:
3388
# We checked remote, and found nothing extra
3389
self.outf.write('Other branch is up to date.\n')
3390
elif not (mine_only or theirs_only or local_extra or
3392
# We checked both branches, and neither one had extra
3394
self.outf.write("Branches are up to date.\n")
3396
remote_branch.unlock()
3398
local_branch.unlock()
4710
3399
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)
3400
local_branch.lock_write()
3402
# handle race conditions - a parent might be set while we run.
3403
if local_branch.get_parent() is None:
3404
local_branch.set_parent(remote_branch.base)
3406
local_branch.unlock()
4715
3407
return status_code
4718
3410
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.
3411
"""Compress the data within a repository."""
4737
3413
_see_also = ['repositories']
4738
3414
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):
3416
def run(self, branch_or_repo='.'):
4744
3417
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4746
3419
branch = dir.open_branch()
4747
3420
repository = branch.repository
4748
3421
except errors.NotBranchError:
4749
3422
repository = dir.open_repository()
4750
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4753
3426
class cmd_plugins(Command):
4754
__doc__ = """List the installed plugins.
3427
"""List the installed plugins.
4756
3429
This command displays the list of installed plugins including
4757
3430
version of plugin and a short description of each.
5158
3827
class cmd_serve(Command):
5159
__doc__ = """Run the bzr server."""
3828
"""Run the bzr server."""
5161
3830
aliases = ['server']
5163
3832
takes_options = [
5165
3834
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
3836
help='Listen for connections on nominated port of the form '
5172
3837
'[hostname:]portnumber. Passing 0 as the port number will '
5173
'result in a dynamically allocated port. The default port '
5174
'depends on the protocol.',
3838
'result in a dynamically allocated port. The default port is '
5176
custom_help('directory',
5177
help='Serve contents of this directory.'),
3842
help='Serve contents of this directory.',
5178
3844
Option('allow-writes',
5179
3845
help='By default the server is a readonly server. Supplying '
5180
3846
'--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 '
3847
'the served directory and below.'
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
3851
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3852
from bzrlib import lockdir
3853
from bzrlib.smart import medium, server
3854
from bzrlib.transport import get_transport
3855
from bzrlib.transport.chroot import ChrootServer
5211
3856
if directory is None:
5212
3857
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
3858
url = urlutils.local_path_to_url(directory)
5217
3859
if not allow_writes:
5218
3860
url = 'readonly+' + url
5219
t = transport.get_transport(url)
5220
protocol(t, host, port, inet)
3861
chroot_server = ChrootServer(get_transport(url))
3862
chroot_server.setUp()
3863
t = get_transport(chroot_server.get_url())
3865
smart_server = medium.SmartServerPipeStreamMedium(
3866
sys.stdin, sys.stdout, t)
3868
host = medium.BZR_DEFAULT_INTERFACE
3870
port = medium.BZR_DEFAULT_PORT
3873
host, port = port.split(':')
3875
smart_server = server.SmartTCPServer(t, host=host, port=port)
3876
print 'listening on port: ', smart_server.port
3878
# for the duration of this server, no UI output is permitted.
3879
# note that this may cause problems with blackbox tests. This should
3880
# be changed with care though, as we dont want to use bandwidth sending
3881
# progress over stderr to smart server clients!
3882
old_factory = ui.ui_factory
3883
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3885
ui.ui_factory = ui.SilentUIFactory()
3886
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3887
smart_server.serve()
3889
ui.ui_factory = old_factory
3890
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
5223
3893
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.
3894
"""Combine a subtree into its containing tree.
3896
This command is for experimental use only. It requires the target tree
3897
to be in dirstate-with-subtree format, which cannot be converted into
5228
3900
The TREE argument should be an independent tree, inside another tree, but
5229
3901
not part of it. (Such trees can be produced by "bzr split", but also by
5230
3902
running "bzr branch" with the target inside a tree.)
5232
The result is a combined tree, with the subtree no longer an independent
3904
The result is a combined tree, with the subtree no longer an independant
5233
3905
part. This is marked as a merge of the subtree into the containing tree,
5234
3906
and all history is preserved.
3908
If --reference is specified, the subtree retains its independence. It can
3909
be branched by itself, and can be part of multiple projects at the same
3910
time. But operations performed in the containing tree, such as commit
3911
and merge, will recurse into the subtree.
5237
3914
_see_also = ['split']
5238
3915
takes_args = ['tree']
5239
3916
takes_options = [
5240
Option('reference', help='Join by reference.', hidden=True),
3917
Option('reference', help='Join by reference.'),
5243
3921
def run(self, tree, reference=False):
5244
3922
sub_tree = WorkingTree.open(tree)
5488
4139
short_name='f',
5490
4141
Option('output', short_name='o',
5491
help='Write merge directive to this file or directory; '
4142
help='Write merge directive to this file; '
5492
4143
'use - for stdout.',
5495
help='Refuse to send if there are uncommitted changes in'
5496
' the working tree, --no-strict disables the check.'),
5497
4145
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')),
4149
RegistryOption.from_kwargs('format',
4150
'Use the specified output format.',
4151
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4152
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5507
4155
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,
4156
no_patch=False, revision=None, remember=False, output=None,
4157
format='4', mail_to=None, message=None, **kwargs):
4158
return self._run(submit_branch, revision, public_branch, remember,
4159
format, no_bundle, no_patch, output,
4160
kwargs.get('from', '.'), mail_to, message)
4162
def _run(self, submit_branch, revision, public_branch, remember, format,
4163
no_bundle, no_patch, output, from_, mail_to, message):
4164
from bzrlib.revision import NULL_REVISION
4165
branch = Branch.open_containing(from_)[0]
4167
outfile = StringIO()
4171
outfile = open(output, 'wb')
4172
# we may need to write data into branch's repository to calculate
4177
config = branch.get_config()
4179
mail_to = config.get_user_option('submit_to')
4180
mail_client = config.get_mail_client()
4181
if remember and submit_branch is None:
4182
raise errors.BzrCommandError(
4183
'--remember requires a branch to be specified.')
4184
stored_submit_branch = branch.get_submit_branch()
4185
remembered_submit_branch = False
4186
if submit_branch is None:
4187
submit_branch = stored_submit_branch
4188
remembered_submit_branch = True
4190
if stored_submit_branch is None or remember:
4191
branch.set_submit_branch(submit_branch)
4192
if submit_branch is None:
4193
submit_branch = branch.get_parent()
4194
remembered_submit_branch = True
4195
if submit_branch is None:
4196
raise errors.BzrCommandError('No submit branch known or'
4198
if remembered_submit_branch:
4199
note('Using saved location "%s" to determine what changes to submit.', submit_branch)
4202
submit_config = Branch.open(submit_branch).get_config()
4203
mail_to = submit_config.get_user_option("child_submit_to")
4205
stored_public_branch = branch.get_public_branch()
4206
if public_branch is None:
4207
public_branch = stored_public_branch
4208
elif stored_public_branch is None or remember:
4209
branch.set_public_branch(public_branch)
4210
if no_bundle and public_branch is None:
4211
raise errors.BzrCommandError('No public branch specified or'
4213
base_revision_id = None
4215
if revision is not None:
4216
if len(revision) > 2:
4217
raise errors.BzrCommandError('bzr send takes '
4218
'at most two one revision identifiers')
4219
revision_id = revision[-1].as_revision_id(branch)
4220
if len(revision) == 2:
4221
base_revision_id = revision[0].as_revision_id(branch)
4222
if revision_id is None:
4223
revision_id = branch.last_revision()
4224
if revision_id == NULL_REVISION:
4225
raise errors.BzrCommandError('No revisions to submit.')
4227
directive = merge_directive.MergeDirective2.from_objects(
4228
branch.repository, revision_id, time.time(),
4229
osutils.local_time_offset(), submit_branch,
4230
public_branch=public_branch, include_patch=not no_patch,
4231
include_bundle=not no_bundle, message=message,
4232
base_revision_id=base_revision_id)
4233
elif format == '0.9':
4236
patch_type = 'bundle'
4238
raise errors.BzrCommandError('Format 0.9 does not'
4239
' permit bundle with no patch')
4245
directive = merge_directive.MergeDirective.from_objects(
4246
branch.repository, revision_id, time.time(),
4247
osutils.local_time_offset(), submit_branch,
4248
public_branch=public_branch, patch_type=patch_type,
4251
outfile.writelines(directive.to_lines())
4253
subject = '[MERGE] '
4254
if message is not None:
4257
revision = branch.repository.get_revision(revision_id)
4258
subject += revision.get_summary()
4259
basename = directive.get_disk_name(branch)
4260
mail_client.compose_merge_request(mail_to, subject,
4261
outfile.getvalue(), basename)
5519
4268
class cmd_bundle_revisions(cmd_send):
5520
__doc__ = """Create a merge-directive for submitting changes.
4270
"""Create a merge-directive for submiting changes.
5522
4272
A merge directive provides many things needed for requesting merges:
5599
4345
Tags are stored in the branch. Tags are copied from one branch to another
5600
4346
along when you branch, push, pull or merge.
5602
It is an error to give a tag name that already exists unless you pass
4348
It is an error to give a tag name that already exists unless you pass
5603
4349
--force, in which case the tag is moved to point to the new revision.
5605
4351
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5606
4352
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
4355
_see_also = ['commit', 'tags']
5615
takes_args = ['tag_name?']
4356
takes_args = ['tag_name']
5616
4357
takes_options = [
5617
4358
Option('delete',
5618
4359
help='Delete this tag rather than placing it.',
5620
custom_help('directory',
5621
help='Branch in which to place the tag.'),
4362
help='Branch in which to place the tag.',
5622
4366
Option('force',
5623
4367
help='Replace existing tags.',
5628
def run(self, tag_name=None,
4372
def run(self, tag_name,
5634
4378
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)
4382
branch.tags.delete_tag(tag_name)
4383
self.outf.write('Deleted tag %s.\n' % tag_name)
4386
if len(revision) != 1:
4387
raise errors.BzrCommandError(
4388
"Tags can only be placed on a single revision, "
4390
revision_id = revision[0].as_revision_id(branch)
4392
revision_id = branch.last_revision()
4393
if (not force) and branch.tags.has_tag(tag_name):
4394
raise errors.TagAlreadyExists(tag_name)
5664
4395
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)
4396
self.outf.write('Created tag %s.\n' % tag_name)
5671
4401
class cmd_tags(Command):
5672
__doc__ = """List tags.
5674
4404
This command shows a table of tag names and the revisions they reference.
5677
4407
_see_also = ['tag']
5678
4408
takes_options = [
5679
custom_help('directory',
5680
help='Branch whose tags should be displayed.'),
5681
RegistryOption('sort',
4410
help='Branch whose tags should be displayed.',
4414
RegistryOption.from_kwargs('sort',
5682
4415
'Sort tags by different criteria.', title='Sorting',
5683
lazy_registry=('bzrlib.tag', 'tag_sort_methods')
4416
alpha='Sort tags lexicographically (default).',
4417
time='Sort tags chronologically.',
5689
4422
@display_command
5690
def run(self, directory='.', sort=None, show_ids=False, revision=None):
5691
from bzrlib.tag import tag_sort_methods
5692
4428
branch, relpath = Branch.open_containing(directory)
5694
4429
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()
4434
elif sort == 'time':
4436
for tag, revid in tags:
4438
revobj = branch.repository.get_revision(revid)
4439
except errors.NoSuchRevision:
4440
timestamp = sys.maxint # place them at the end
4442
timestamp = revobj.timestamp
4443
timestamps[revid] = timestamp
4444
tags.sort(key=lambda x: timestamps[x[1]])
5709
4445
if not show_ids:
5710
4446
# [ (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)
4447
revno_map = branch.get_revision_id_to_revno_map()
4448
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4449
for tag, revid in tags ]
5722
4450
for tag, revspec in tags:
5723
4451
self.outf.write('%-20s %s\n' % (tag, revspec))
5726
4454
class cmd_reconfigure(Command):
5727
__doc__ = """Reconfigure the type of a bzr directory.
4455
"""Reconfigure the type of a bzr directory.
5729
4457
A target configuration must be specified.
5740
4468
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5741
4469
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.',
4470
takes_options = [RegistryOption.from_kwargs('target_type',
4471
title='Target type',
4472
help='The type to reconfigure the directory to.',
4473
value_switches=True, enum_switch=False,
4474
branch='Reconfigure to be an unbound branch '
4475
'with no working tree.',
4476
tree='Reconfigure to be an unbound branch '
4477
'with a working tree.',
4478
checkout='Reconfigure to be a bound branch '
4479
'with a working tree.',
4480
lightweight_checkout='Reconfigure to be a lightweight'
4481
' checkout (with no local history).',
4482
standalone='Reconfigure to be a standalone branch '
4483
'(i.e. stop using shared repository).',
4484
use_shared='Reconfigure to use a shared repository.'),
4485
Option('bind-to', help='Branch to bind checkout to.',
4488
help='Perform reconfiguration even if local changes'
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):
4492
def run(self, location=None, target_type=None, bind_to=None, force=False):
5790
4493
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':
4494
if target_type is None:
4495
raise errors.BzrCommandError('No target configuration specified')
4496
elif target_type == 'branch':
5810
4497
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5811
elif tree_type == 'tree':
4498
elif target_type == 'tree':
5812
4499
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5813
elif tree_type == 'checkout':
5814
reconfiguration = reconfigure.Reconfigure.to_checkout(
5816
elif tree_type == 'lightweight-checkout':
4500
elif target_type == 'checkout':
4501
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4503
elif target_type == 'lightweight-checkout':
5817
4504
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5818
4505
directory, bind_to)
5820
reconfiguration.apply(force)
5821
reconfiguration = None
5822
if repository_type == 'use-shared':
4506
elif target_type == 'use-shared':
5823
4507
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5824
elif repository_type == 'standalone':
4508
elif target_type == 'standalone':
5825
4509
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
4510
reconfiguration.apply(force)
5840
4513
class cmd_switch(Command):
5841
__doc__ = """Set the branch of a checkout and update.
4514
"""Set the branch of a checkout and update.
5843
4516
For lightweight checkouts, this changes the branch being referenced.
5844
4517
For heavyweight checkouts, this checks that there are no local commits
5845
4518
versus the current bound branch, then it makes the local branch a mirror
5846
4519
of the new location and binds to it.
5848
4521
In both cases, the working tree is updated and uncommitted changes
5849
4522
are merged. The user can commit or revert these as they desire.
5854
4527
directory of the current branch. For example, if you are currently in a
5855
4528
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5856
4529
/path/to/newbranch.
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.'),
4532
takes_args = ['to_location']
4533
takes_options = [Option('force',
4534
help='Switch even if local commits will be lost.')
5873
def run(self, to_location=None, force=False, create_branch=False,
5874
revision=None, directory=u'.'):
4537
def run(self, to_location, force=False):
5875
4538
from bzrlib import switch
5876
tree_location = directory
5877
revision = _get_one_revision('switch', revision)
5878
4540
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()
4542
to_branch = Branch.open(to_location)
5887
4543
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
4544
to_branch = Branch.open(
4545
control_dir.open_branch().base + '../' + to_location)
4546
switch.switch(control_dir, to_branch, force)
5916
4547
note('Switched to branch: %s',
5917
4548
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
4551
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()
4552
"""Show a branch's currently registered hooks.
4556
takes_args = ['path?']
4558
def run(self, path=None):
6316
4559
if path is None:
6317
info = branch._get_all_reference_info().iteritems()
6318
self._display_reference_info(tree, branch, info)
4561
branch_hooks = Branch.open(path).hooks
4562
for hook_type in branch_hooks:
4563
hooks = branch_hooks[hook_type]
4564
self.outf.write("%s:\n" % (hook_type,))
4567
self.outf.write(" %s\n" %
4568
(branch_hooks.get_hook_name(hook),))
4570
self.outf.write(" <no hooks installed>\n")
4573
def _create_prefix(cur_transport):
4574
needed = [cur_transport]
4575
# Recurse upwards until we can create a directory successfully
4577
new_transport = cur_transport.clone('..')
4578
if new_transport.base == cur_transport.base:
4579
raise errors.BzrCommandError(
4580
"Failed to create path prefix for %s."
4581
% cur_transport.base)
4583
new_transport.mkdir('.')
4584
except errors.NoSuchFile:
4585
needed.append(new_transport)
4586
cur_transport = new_transport
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)
4589
# Now we only need to create child directories
4591
cur_transport = needed.pop()
4592
cur_transport.ensure_base()
4595
# these get imported and then picked up by the scan for cmd_*
4596
# TODO: Some more consistent way to split command definitions across files;
4597
# we do need to load at least some information about them to know of
4598
# aliases. ideally we would avoid loading the implementation until the
4599
# details were needed.
4600
from bzrlib.cmd_version_info import cmd_version_info
4601
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
4602
from bzrlib.bundle.commands import (
4605
from bzrlib.sign_my_commits import cmd_sign_my_commits
4606
from bzrlib.weave_commands import cmd_versionedfile_list, \
4607
cmd_weave_plan_merge, cmd_weave_merge_text