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
304
197
show_tree_status(tree, show_ids=show_ids,
305
198
specific_files=relfile_list, revision=revision,
306
199
to_file=self.outf, short=short, versioned=versioned,
307
show_pending=(not no_pending), verbose=verbose,
308
classify=not no_classify)
200
show_pending=(not no_pending))
311
203
class cmd_cat_revision(Command):
312
__doc__ = """Write out metadata for a revision.
204
"""Write out metadata for a revision.
314
206
The revision to print can either be specified by a specific
315
207
revision identifier, or you can use --revision.
319
211
takes_args = ['revision_id?']
320
takes_options = ['directory', 'revision']
212
takes_options = ['revision']
321
213
# cat-revision is more for frontends so should be exact
322
214
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'.'):
217
def run(self, revision_id=None, revision=None):
334
218
if revision_id is not None and revision is not None:
335
219
raise errors.BzrCommandError('You can only supply one of'
336
220
' revision_id or --revision')
337
221
if revision_id is None and revision is None:
338
222
raise errors.BzrCommandError('You must supply either'
339
223
' --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])
224
b = WorkingTree.open_containing(u'.')[0].branch
226
# TODO: jam 20060112 should cat-revision always output utf-8?
227
if revision_id is not None:
228
revision_id = osutils.safe_revision_id(revision_id, warn=False)
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,))
230
self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
231
except errors.NoSuchRevision:
232
msg = "The repository %s contains no revision %s." % (b.repository.base,
234
raise errors.BzrCommandError(msg)
235
elif revision is not None:
238
raise errors.BzrCommandError('You cannot specify a NULL'
240
rev_id = rev.as_revision_id(b)
241
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
454
244
class cmd_remove_tree(Command):
455
__doc__ = """Remove the working tree from a given branch/checkout.
245
"""Remove the working tree from a given branch/checkout.
457
247
Since a lightweight checkout is little more than a working tree
458
248
this will refuse to run against one.
460
250
To re-create the working tree, use "bzr checkout".
462
252
_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]
254
takes_args = ['location?']
256
def run(self, location='.'):
257
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'
260
working = d.open_workingtree()
261
except errors.NoWorkingTree:
262
raise errors.BzrCommandError("No working tree to remove")
263
except errors.NotLocalUrl:
264
raise errors.BzrCommandError("You cannot remove the working tree of a "
267
working_path = working.bzrdir.root_transport.base
268
branch_path = working.branch.bzrdir.root_transport.base
269
if working_path != branch_path:
270
raise errors.BzrCommandError("You cannot remove the working tree from "
271
"a lightweight checkout")
273
d.destroy_workingtree()
550
276
class cmd_revno(Command):
551
__doc__ = """Show current revision number.
277
"""Show current revision number.
553
279
This is equal to the number of revisions on this branch.
556
282
_see_also = ['info']
557
283
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')
286
def run(self, location=u'.'):
287
self.outf.write(str(Branch.open_containing(location)[0].revno()))
288
self.outf.write('\n')
584
291
class cmd_revision_info(Command):
585
__doc__ = """Show revision number and revision id for a given revision identifier.
292
"""Show revision number and revision id for a given revision identifier.
588
295
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'),
296
takes_options = ['revision']
598
def run(self, revision=None, directory=u'.', tree=False,
599
revision_info_list=[]):
299
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
302
if revision is not None:
611
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
303
revs.extend(revision)
612
304
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:
305
for rev in revision_info_list:
306
revs.append(RevisionSpec.from_string(rev))
308
b = Branch.open_containing(u'.')[0]
311
revs.append(RevisionSpec.from_string('-1'))
314
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)
316
revno = '%4d' % (b.revision_id_to_revno(revision_id))
631
317
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]))
318
dotted_map = b.get_revision_id_to_revno_map()
319
revno = '.'.join(str(i) for i in dotted_map[revision_id])
320
print '%s %s' % (revno, revision_id)
641
323
class cmd_add(Command):
642
__doc__ = """Add specified files or directories.
324
"""Add specified files or directories.
644
326
In non-recursive mode, all the named items are added, regardless
645
327
of whether they were previously ignored. A warning is given if
888
569
into_existing = False
890
571
inv = tree.inventory
891
# 'fix' the case of a potential 'from'
892
from_id = tree.path2id(
893
tree.get_canonical_inventory_path(rel_names[0]))
572
from_id = tree.path2id(rel_names[0])
894
573
if (not osutils.lexists(names_list[0]) and
895
574
from_id and inv.get_file_kind(from_id) == "directory"):
896
575
into_existing = False
898
577
if into_existing:
899
578
# move into existing directory
900
# All entries reference existing inventory items, so fix them up
901
# for cicp file-systems.
902
rel_names = tree.get_canonical_inventory_paths(rel_names)
903
for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
905
self.outf.write("%s => %s\n" % (src, dest))
579
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
580
self.outf.write("%s => %s\n" % pair)
907
582
if len(names_list) != 2:
908
583
raise errors.BzrCommandError('to mv multiple files the'
909
584
' destination must be a versioned'
912
# for cicp file-systems: the src references an existing inventory
914
src = tree.get_canonical_inventory_path(rel_names[0])
915
# Find the canonical version of the destination: In all cases, the
916
# parent of the target must be in the inventory, so we fetch the
917
# canonical version from there (we do not always *use* the
918
# canonicalized tail portion - we may be attempting to rename the
920
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
921
dest_parent = osutils.dirname(canon_dest)
922
spec_tail = osutils.basename(rel_names[1])
923
# For a CICP file-system, we need to avoid creating 2 inventory
924
# entries that differ only by case. So regardless of the case
925
# we *want* to use (ie, specified by the user or the file-system),
926
# we must always choose to use the case of any existing inventory
927
# items. The only exception to this is when we are attempting a
928
# case-only rename (ie, canonical versions of src and dest are
930
dest_id = tree.path2id(canon_dest)
931
if dest_id is None or tree.path2id(src) == dest_id:
932
# No existing item we care about, so work out what case we
933
# are actually going to use.
935
# If 'after' is specified, the tail must refer to a file on disk.
937
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
939
# pathjoin with an empty tail adds a slash, which breaks
941
dest_parent_fq = tree.basedir
943
dest_tail = osutils.canonical_relpath(
945
osutils.pathjoin(dest_parent_fq, spec_tail))
947
# not 'after', so case as specified is used
948
dest_tail = spec_tail
950
# Use the existing item so 'mv' fails with AlreadyVersioned.
951
dest_tail = os.path.basename(canon_dest)
952
dest = osutils.pathjoin(dest_parent, dest_tail)
953
mutter("attempting to move %s => %s", src, dest)
954
tree.rename_one(src, dest, after=after)
956
self.outf.write("%s => %s\n" % (src, dest))
586
tree.rename_one(rel_names[0], rel_names[1], after=after)
587
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
959
590
class cmd_pull(Command):
960
__doc__ = """Turn this branch into a mirror of another branch.
591
"""Turn this branch into a mirror of another branch.
962
By default, this command only works on branches that have not diverged.
963
Branches are considered diverged if the destination branch's most recent
964
commit is one that has not been merged (directly or indirectly) into the
593
This command only works on branches that have not diverged. Branches are
594
considered diverged if the destination branch's most recent commit is one
595
that has not been merged (directly or indirectly) into the parent.
967
597
If branches have diverged, you can use 'bzr merge' to integrate the changes
968
598
from one into the other. Once one branch has merged, the other should
969
599
be able to pull it again.
971
If you want to replace your local changes and just want your branch to
972
match the remote one, use pull --overwrite. This will work even if the two
973
branches have diverged.
601
If you want to forget your local changes and just update your branch to
602
match the remote one, use pull --overwrite.
975
If there is no default location set, the first pull will set it (use
976
--no-remember to avoid settting it). After that, you can omit the
977
location to use the default. To change the default, use --remember. The
978
value will only be saved if the remote location can be accessed.
604
If there is no default location set, the first pull will set it. After
605
that, you can omit the location to use the default. To change the
606
default, use --remember. The value will only be saved if the remote
607
location can be accessed.
980
609
Note: The location can be specified either in the form of a branch,
981
610
or in the form of a path to a file containing a merge directive generated
985
_see_also = ['push', 'update', 'status-flags', 'send']
614
_see_also = ['push', 'update', 'status-flags']
986
615
takes_options = ['remember', 'overwrite', 'revision',
987
616
custom_help('verbose',
988
617
help='Show logs of pulled revisions.'),
989
custom_help('directory',
990
619
help='Branch to pull into, '
991
'rather than the one containing the working directory.'),
993
help="Perform a local pull in a bound "
994
"branch. Local pulls are not applied to "
620
'rather than the one containing the working directory.',
998
help="Show base revision text in conflicts.")
1000
625
takes_args = ['location?']
1001
626
encoding_type = 'replace'
1003
def run(self, location=None, remember=None, overwrite=False,
628
def run(self, location=None, remember=False, overwrite=False,
1004
629
revision=None, verbose=False,
1005
directory=None, local=False,
1007
631
# FIXME: too much stuff is in the command class
1008
632
revision_id = None
1009
633
mergeable = None
1217
828
To retrieve the branch as of a particular revision, supply the --revision
1218
829
parameter, as in "branch foo/bar -r 5".
1220
The synonyms 'clone' and 'get' for this command are deprecated.
1223
832
_see_also = ['checkout']
1224
833
takes_args = ['from_location', 'to_location?']
1225
takes_options = ['revision',
1226
Option('hardlink', help='Hard-link working tree files where possible.'),
1227
Option('files-from', type=str,
1228
help="Get file contents from this tree."),
1230
help="Create a branch without a working-tree."),
1232
help="Switch the checkout in the current directory "
1233
"to the new branch."),
834
takes_options = ['revision', Option('hardlink',
835
help='Hard-link working tree files where possible.'),
1234
836
Option('stacked',
1235
837
help='Create a stacked branch referring to the source branch. '
1236
838
'The new branch will depend on the availability of the source '
1237
839
'branch for all operations.'),
1238
Option('standalone',
1239
help='Do not use a shared repository, even if available.'),
1240
Option('use-existing-dir',
1241
help='By default branch will fail if the target'
1242
' directory exists, but does not already'
1243
' have a control directory. This flag will'
1244
' allow branch to proceed.'),
1246
help="Bind new branch to from location."),
1248
841
aliases = ['get', 'clone']
1250
843
def run(self, from_location, to_location=None, revision=None,
1251
hardlink=False, stacked=False, standalone=False, no_tree=False,
1252
use_existing_dir=False, switch=False, bind=False,
1254
from bzrlib import switch as _mod_switch
844
hardlink=False, stacked=False):
1255
845
from bzrlib.tag import _merge_tags_if_possible
1256
if self.invoked_as in ['get', 'clone']:
1257
ui.ui_factory.show_user_warning(
1258
'deprecated_command',
1259
deprecated_name=self.invoked_as,
1260
recommended_name='branch',
1261
deprecated_in_version='2.4')
848
elif len(revision) > 1:
849
raise errors.BzrCommandError(
850
'bzr branch --revision takes exactly 1 revision value')
1262
852
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1264
if not (hardlink or files_from):
1265
# accelerator_tree is usually slower because you have to read N
1266
# files (no readahead, lots of seeks, etc), but allow the user to
1267
# explicitly request it
1268
accelerator_tree = None
1269
if files_from is not None and files_from != from_location:
1270
accelerator_tree = WorkingTree.open(files_from)
1271
revision = _get_one_revision('branch', revision)
1272
self.add_cleanup(br_from.lock_read().unlock)
1273
if revision is not None:
1274
revision_id = revision.as_revision_id(br_from)
1276
# FIXME - wt.last_revision, fallback to branch, fall back to
1277
# None or perhaps NULL_REVISION to mean copy nothing
1279
revision_id = br_from.last_revision()
1280
if to_location is None:
1281
to_location = urlutils.derive_to_location(from_location)
1282
to_transport = transport.get_transport(to_location)
1284
to_transport.mkdir('.')
1285
except errors.FileExists:
1286
if not use_existing_dir:
1287
raise errors.BzrCommandError('Target directory "%s" '
1288
'already exists.' % to_location)
856
if len(revision) == 1 and revision[0] is not None:
857
revision_id = revision[0].as_revision_id(br_from)
1291
bzrdir.BzrDir.open_from_transport(to_transport)
1292
except errors.NotBranchError:
1295
raise errors.AlreadyBranchError(to_location)
1296
except errors.NoSuchFile:
1297
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1300
# preserve whatever source format we have.
1301
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1302
possible_transports=[to_transport],
1303
accelerator_tree=accelerator_tree,
1304
hardlink=hardlink, stacked=stacked,
1305
force_new_repo=standalone,
1306
create_tree_if_local=not no_tree,
1307
source_branch=br_from)
1308
branch = dir.open_branch()
1309
except errors.NoSuchRevision:
1310
to_transport.delete_tree('.')
1311
msg = "The branch %s has no revision %s." % (from_location,
1313
raise errors.BzrCommandError(msg)
1314
_merge_tags_if_possible(br_from, branch)
1315
# If the source branch is stacked, the new branch may
1316
# be stacked whether we asked for that explicitly or not.
1317
# We therefore need a try/except here and not just 'if stacked:'
1319
note('Created new stacked branch referring to %s.' %
1320
branch.get_stacked_on_url())
1321
except (errors.NotStacked, errors.UnstackableBranchFormat,
1322
errors.UnstackableRepositoryFormat), e:
1323
note('Branched %d revision(s).' % branch.revno())
1325
# Bind to the parent
1326
parent_branch = Branch.open(from_location)
1327
branch.bind(parent_branch)
1328
note('New branch bound to %s' % from_location)
1330
# Switch to the new branch
1331
wt, _ = WorkingTree.open_containing('.')
1332
_mod_switch.switch(wt.bzrdir, branch)
1333
note('Switched to branch: %s',
1334
urlutils.unescape_for_display(branch.base, 'utf-8'))
859
# FIXME - wt.last_revision, fallback to branch, fall back to
860
# None or perhaps NULL_REVISION to mean copy nothing
862
revision_id = br_from.last_revision()
863
if to_location is None:
864
to_location = urlutils.derive_to_location(from_location)
865
to_transport = transport.get_transport(to_location)
867
to_transport.mkdir('.')
868
except errors.FileExists:
869
raise errors.BzrCommandError('Target directory "%s" already'
870
' exists.' % to_location)
871
except errors.NoSuchFile:
872
raise errors.BzrCommandError('Parent of "%s" does not exist.'
875
# preserve whatever source format we have.
876
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
877
possible_transports=[to_transport],
878
accelerator_tree=accelerator_tree,
879
hardlink=hardlink, stacked=stacked)
880
branch = dir.open_branch()
881
except errors.NoSuchRevision:
882
to_transport.delete_tree('.')
883
msg = "The branch %s has no revision %s." % (from_location,
885
raise errors.BzrCommandError(msg)
886
_merge_tags_if_possible(br_from, branch)
887
# If the source branch is stacked, the new branch may
888
# be stacked whether we asked for that explicitly or not.
889
# We therefore need a try/except here and not just 'if stacked:'
891
note('Created new stacked branch referring to %s.' %
892
branch.get_stacked_on_url())
893
except (errors.NotStacked, errors.UnstackableBranchFormat,
894
errors.UnstackableRepositoryFormat), e:
895
note('Branched %d revision(s).' % branch.revno())
1337
900
class cmd_checkout(Command):
1338
__doc__ = """Create a new checkout of an existing branch.
901
"""Create a new checkout of an existing branch.
1340
903
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1341
904
the branch found in '.'. This is useful if you have removed the working tree
1342
905
or if it was never created - i.e. if you pushed the branch to its current
1343
906
location using SFTP.
1345
908
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1346
909
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
1347
910
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1420
982
@display_command
1421
983
def run(self, dir=u'.'):
1422
984
tree = WorkingTree.open_containing(dir)[0]
1423
self.add_cleanup(tree.lock_read().unlock)
1424
new_inv = tree.inventory
1425
old_tree = tree.basis_tree()
1426
self.add_cleanup(old_tree.lock_read().unlock)
1427
old_inv = old_tree.inventory
1429
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1430
for f, paths, c, v, p, n, k, e in iterator:
1431
if paths[0] == paths[1]:
1435
renames.append(paths)
1437
for old_name, new_name in renames:
1438
self.outf.write("%s => %s\n" % (old_name, new_name))
987
new_inv = tree.inventory
988
old_tree = tree.basis_tree()
991
old_inv = old_tree.inventory
992
renames = list(_mod_tree.find_renames(old_inv, new_inv))
994
for old_name, new_name in renames:
995
self.outf.write("%s => %s\n" % (old_name, new_name))
1441
1002
class cmd_update(Command):
1442
__doc__ = """Update a tree to have the latest code committed to its branch.
1003
"""Update a tree to have the latest code committed to its branch.
1444
1005
This will perform a merge into the working tree, and may generate
1445
conflicts. If you have any local changes, you will still
1006
conflicts. If you have any local changes, you will still
1446
1007
need to commit them after the update for the update to be complete.
1448
If you want to discard your local changes, you can just do a
1009
If you want to discard your local changes, you can just do a
1449
1010
'bzr revert' instead of 'bzr commit' after the update.
1451
If you want to restore a file that has been removed locally, use
1452
'bzr revert' instead of 'bzr update'.
1454
If the tree's branch is bound to a master branch, it will also update
1455
the branch from the master.
1458
1013
_see_also = ['pull', 'working-trees', 'status-flags']
1459
1014
takes_args = ['dir?']
1460
takes_options = ['revision',
1462
help="Show base revision text in conflicts."),
1464
1015
aliases = ['up']
1466
def run(self, dir='.', revision=None, show_base=None):
1467
if revision is not None and len(revision) != 1:
1468
raise errors.BzrCommandError(
1469
"bzr update --revision takes exactly one revision")
1017
def run(self, dir='.'):
1470
1018
tree = WorkingTree.open_containing(dir)[0]
1471
branch = tree.branch
1472
1019
possible_transports = []
1473
master = branch.get_master_branch(
1020
master = tree.branch.get_master_branch(
1474
1021
possible_transports=possible_transports)
1475
1022
if master is not None:
1476
branch_location = master.base
1477
1023
tree.lock_write()
1479
branch_location = tree.branch.base
1480
1025
tree.lock_tree_write()
1481
self.add_cleanup(tree.unlock)
1482
# get rid of the final '/' and be ready for display
1483
branch_location = urlutils.unescape_for_display(
1484
branch_location.rstrip('/'),
1486
existing_pending_merges = tree.get_parent_ids()[1:]
1490
# may need to fetch data into a heavyweight checkout
1491
# XXX: this may take some time, maybe we should display a
1493
old_tip = branch.update(possible_transports)
1494
if revision is not None:
1495
revision_id = revision[0].as_revision_id(branch)
1497
revision_id = branch.last_revision()
1498
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1499
revno = branch.revision_id_to_dotted_revno(revision_id)
1500
note("Tree is up to date at revision %s of branch %s" %
1501
('.'.join(map(str, revno)), branch_location))
1503
view_info = _get_view_info_for_change_reporter(tree)
1504
change_reporter = delta._ChangeReporter(
1505
unversioned_filter=tree.is_ignored,
1506
view_info=view_info)
1027
existing_pending_merges = tree.get_parent_ids()[1:]
1028
last_rev = _mod_revision.ensure_null(tree.last_revision())
1029
if last_rev == _mod_revision.ensure_null(
1030
tree.branch.last_revision()):
1031
# may be up to date, check master too.
1032
if master is None or last_rev == _mod_revision.ensure_null(
1033
master.last_revision()):
1034
revno = tree.branch.revision_id_to_revno(last_rev)
1035
note("Tree is up to date at revision %d." % (revno,))
1508
1037
conflicts = tree.update(
1510
possible_transports=possible_transports,
1511
revision=revision_id,
1513
show_base=show_base)
1514
except errors.NoSuchRevision, e:
1515
raise errors.BzrCommandError(
1516
"branch has no revision %s\n"
1517
"bzr update --revision only works"
1518
" for a revision in the branch history"
1520
revno = tree.branch.revision_id_to_dotted_revno(
1521
_mod_revision.ensure_null(tree.last_revision()))
1522
note('Updated to revision %s of branch %s' %
1523
('.'.join(map(str, revno)), branch_location))
1524
parent_ids = tree.get_parent_ids()
1525
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1526
note('Your local commits will now show as pending merges with '
1527
"'bzr status', and can be committed with 'bzr commit'.")
1038
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1039
possible_transports=possible_transports)
1040
revno = tree.branch.revision_id_to_revno(
1041
_mod_revision.ensure_null(tree.last_revision()))
1042
note('Updated to revision %d.' % (revno,))
1043
if tree.get_parent_ids()[1:] != existing_pending_merges:
1044
note('Your local commits will now show as pending merges with '
1045
"'bzr status', and can be committed with 'bzr commit'.")
1534
1054
class cmd_info(Command):
1535
__doc__ = """Show information about a working tree, branch or repository.
1055
"""Show information about a working tree, branch or repository.
1537
1057
This command will show all known locations and formats associated to the
1538
tree, branch or repository.
1540
In verbose mode, statistical information is included with each report.
1541
To see extended statistic information, use a verbosity level of 2 or
1542
higher by specifying the verbose option multiple times, e.g. -vv.
1058
tree, branch or repository. Statistical information is included with
1544
1061
Branches and working trees will also report any missing revisions.
1548
Display information on the format and related locations:
1552
Display the above together with extended format information and
1553
basic statistics (like the number of files in the working tree and
1554
number of revisions in the branch and repository):
1558
Display the above together with number of committers to the branch:
1562
1063
_see_also = ['revno', 'working-trees', 'repositories']
1563
1064
takes_args = ['location?']
1590
1090
RegistryOption.from_kwargs('file-deletion-strategy',
1591
1091
'The file deletion mode to be used.',
1592
1092
title='Deletion Strategy', value_switches=True, enum_switch=False,
1593
safe='Backup changed files (default).',
1594
keep='Delete from bzr but leave the working copy.',
1595
no_backup='Don\'t backup changed files.',
1093
safe='Only delete files if they can be'
1094
' safely recovered (default).',
1095
keep="Don't delete any files.",
1596
1096
force='Delete all the specified files, even if they can not be '
1597
'recovered and even if they are non-empty directories. '
1598
'(deprecated, use no-backup)')]
1097
'recovered and even if they are non-empty directories.')]
1599
1098
aliases = ['rm', 'del']
1600
1099
encoding_type = 'replace'
1602
1101
def run(self, file_list, verbose=False, new=False,
1603
1102
file_deletion_strategy='safe'):
1604
if file_deletion_strategy == 'force':
1605
note("(The --force option is deprecated, rather use --no-backup "
1607
file_deletion_strategy = 'no-backup'
1609
tree, file_list = WorkingTree.open_containing_paths(file_list)
1103
tree, file_list = tree_files(file_list)
1611
1105
if file_list is not None:
1612
1106
file_list = [f for f in file_list]
1614
self.add_cleanup(tree.lock_write().unlock)
1615
# Heuristics should probably all move into tree.remove_smart or
1618
added = tree.changes_from(tree.basis_tree(),
1619
specific_files=file_list).added
1620
file_list = sorted([f[0] for f in added], reverse=True)
1621
if len(file_list) == 0:
1622
raise errors.BzrCommandError('No matching files.')
1623
elif file_list is None:
1624
# missing files show up in iter_changes(basis) as
1625
# versioned-with-no-kind.
1627
for change in tree.iter_changes(tree.basis_tree()):
1628
# Find paths in the working tree that have no kind:
1629
if change[1][1] is not None and change[6][1] is None:
1630
missing.append(change[1][1])
1631
file_list = sorted(missing, reverse=True)
1632
file_deletion_strategy = 'keep'
1633
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1634
keep_files=file_deletion_strategy=='keep',
1635
force=(file_deletion_strategy=='no-backup'))
1110
# Heuristics should probably all move into tree.remove_smart or
1113
added = tree.changes_from(tree.basis_tree(),
1114
specific_files=file_list).added
1115
file_list = sorted([f[0] for f in added], reverse=True)
1116
if len(file_list) == 0:
1117
raise errors.BzrCommandError('No matching files.')
1118
elif file_list is None:
1119
# missing files show up in iter_changes(basis) as
1120
# versioned-with-no-kind.
1122
for change in tree.iter_changes(tree.basis_tree()):
1123
# Find paths in the working tree that have no kind:
1124
if change[1][1] is not None and change[6][1] is None:
1125
missing.append(change[1][1])
1126
file_list = sorted(missing, reverse=True)
1127
file_deletion_strategy = 'keep'
1128
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1129
keep_files=file_deletion_strategy=='keep',
1130
force=file_deletion_strategy=='force')
1638
1135
class cmd_file_id(Command):
1639
__doc__ = """Print file_id of a particular file or directory.
1136
"""Print file_id of a particular file or directory.
1641
1138
The file_id is assigned when the file is first added and remains the
1642
1139
same through all revisions where the file exists, even when it is
2197
1628
raise errors.BzrCommandError(msg)
2200
def _parse_levels(s):
2204
msg = "The levels argument must be an integer."
2205
raise errors.BzrCommandError(msg)
2208
1631
class cmd_log(Command):
2209
__doc__ = """Show historical log for a branch or subset of a branch.
2211
log is bzr's default tool for exploring the history of a branch.
2212
The branch to use is taken from the first parameter. If no parameters
2213
are given, the branch containing the working directory is logged.
2214
Here are some simple examples::
2216
bzr log log the current branch
2217
bzr log foo.py log a file in its branch
2218
bzr log http://server/branch log a branch on a server
2220
The filtering, ordering and information shown for each revision can
2221
be controlled as explained below. By default, all revisions are
2222
shown sorted (topologically) so that newer revisions appear before
2223
older ones and descendants always appear before ancestors. If displayed,
2224
merged revisions are shown indented under the revision in which they
2229
The log format controls how information about each revision is
2230
displayed. The standard log formats are called ``long``, ``short``
2231
and ``line``. The default is long. See ``bzr help log-formats``
2232
for more details on log formats.
2234
The following options can be used to control what information is
2237
-l N display a maximum of N revisions
2238
-n N display N levels of revisions (0 for all, 1 for collapsed)
2239
-v display a status summary (delta) for each revision
2240
-p display a diff (patch) for each revision
2241
--show-ids display revision-ids (and file-ids), not just revnos
2243
Note that the default number of levels to display is a function of the
2244
log format. If the -n option is not used, the standard log formats show
2245
just the top level (mainline).
2247
Status summaries are shown using status flags like A, M, etc. To see
2248
the changes explained using words like ``added`` and ``modified``
2249
instead, use the -vv option.
2253
To display revisions from oldest to newest, use the --forward option.
2254
In most cases, using this option will have little impact on the total
2255
time taken to produce a log, though --forward does not incrementally
2256
display revisions like --reverse does when it can.
2258
:Revision filtering:
2260
The -r option can be used to specify what revision or range of revisions
2261
to filter against. The various forms are shown below::
2263
-rX display revision X
2264
-rX.. display revision X and later
2265
-r..Y display up to and including revision Y
2266
-rX..Y display from X to Y inclusive
2268
See ``bzr help revisionspec`` for details on how to specify X and Y.
2269
Some common examples are given below::
2271
-r-1 show just the tip
2272
-r-10.. show the last 10 mainline revisions
2273
-rsubmit:.. show what's new on this branch
2274
-rancestor:path.. show changes since the common ancestor of this
2275
branch and the one at location path
2276
-rdate:yesterday.. show changes since yesterday
2278
When logging a range of revisions using -rX..Y, log starts at
2279
revision Y and searches back in history through the primary
2280
("left-hand") parents until it finds X. When logging just the
2281
top level (using -n1), an error is reported if X is not found
2282
along the way. If multi-level logging is used (-n0), X may be
2283
a nested merge revision and the log will be truncated accordingly.
2287
If parameters are given and the first one is not a branch, the log
2288
will be filtered to show only those revisions that changed the
2289
nominated files or directories.
2291
Filenames are interpreted within their historical context. To log a
2292
deleted file, specify a revision range so that the file existed at
2293
the end or start of the range.
2295
Historical context is also important when interpreting pathnames of
2296
renamed files/directories. Consider the following example:
2298
* revision 1: add tutorial.txt
2299
* revision 2: modify tutorial.txt
2300
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2304
* ``bzr log guide.txt`` will log the file added in revision 1
2306
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2308
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2309
the original file in revision 2.
2311
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2312
was no file called guide.txt in revision 2.
2314
Renames are always followed by log. By design, there is no need to
2315
explicitly ask for this (and no way to stop logging a file back
2316
until it was last renamed).
2320
The --match option can be used for finding revisions that match a
2321
regular expression in a commit message, committer, author or bug.
2322
Specifying the option several times will match any of the supplied
2323
expressions. --match-author, --match-bugs, --match-committer and
2324
--match-message can be used to only match a specific field.
2328
GUI tools and IDEs are often better at exploring history than command
2329
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2330
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2331
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2332
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2334
You may find it useful to add the aliases below to ``bazaar.conf``::
2338
top = log -l10 --line
2341
``bzr tip`` will then show the latest revision while ``bzr top``
2342
will show the last 10 mainline revisions. To see the details of a
2343
particular revision X, ``bzr show -rX``.
2345
If you are interested in looking deeper into a particular merge X,
2346
use ``bzr log -n0 -rX``.
2348
``bzr log -v`` on a branch with lots of history is currently
2349
very slow. A fix for this issue is currently under development.
2350
With or without that fix, it is recommended that a revision range
2351
be given when using the -v option.
2353
bzr has a generic full-text matching plugin, bzr-search, that can be
2354
used to find revisions matching user names, commit messages, etc.
2355
Among other features, this plugin can find all revisions containing
2356
a list of words but not others.
2358
When exploring non-mainline history on large projects with deep
2359
history, the performance of log can be greatly improved by installing
2360
the historycache plugin. This plugin buffers historical information
2361
trading disk space for faster speed.
1632
"""Show log of a branch, file, or directory.
1634
By default show the log of the branch containing the working directory.
1636
To request a range of logs, you can use the command -r begin..end
1637
-r revision requests a specific revision, -r ..end or -r begin.. are
1641
Log the current branch::
1649
Log the last 10 revisions of a branch::
1651
bzr log -r -10.. http://server/branch
2363
takes_args = ['file*']
2364
_see_also = ['log-formats', 'revisionspec']
1654
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1656
takes_args = ['location?']
2365
1657
takes_options = [
2366
1658
Option('forward',
2367
1659
help='Show from oldest to newest.'),
1662
help='Display timezone as local, original, or utc.'),
2369
1663
custom_help('verbose',
2370
1664
help='Show files changed in each revision.'),
2374
type=bzrlib.option._parse_revision_str,
2376
help='Show just the specified revision.'
2377
' See also "help revisionspec".'),
2379
RegistryOption('authors',
2380
'What names to list as authors - first, all or committer.',
2382
lazy_registry=('bzrlib.log', 'author_list_registry'),
2386
help='Number of levels to display - 0 for all, 1 for flat.',
2388
type=_parse_levels),
2389
1668
Option('message',
2390
1670
help='Show revisions whose message matches this '
2391
1671
'regular expression.',
2394
1673
Option('limit',
2395
1674
short_name='l',
2396
1675
help='Limit the output to the first N revisions.',
2398
1677
type=_parse_limit),
2401
help='Show changes made in each revision as a patch.'),
2402
Option('include-merges',
2403
help='Show merged revisions like --levels 0 does.'),
2404
Option('exclude-common-ancestry',
2405
help='Display only the revisions that are not part'
2406
' of both ancestries (require -rX..Y)'
2408
Option('signatures',
2409
help='Show digital signature validity'),
2412
help='Show revisions whose properties match this '
2415
ListOption('match-message',
2416
help='Show revisions whose message matches this '
2419
ListOption('match-committer',
2420
help='Show revisions whose committer matches this '
2423
ListOption('match-author',
2424
help='Show revisions whose authors match this '
2427
ListOption('match-bugs',
2428
help='Show revisions whose bugs match this '
2432
1679
encoding_type = 'replace'
2434
1681
@display_command
2435
def run(self, file_list=None, timezone='original',
1682
def run(self, location=None, timezone='original',
2437
1684
show_ids=False,
2441
1687
log_format=None,
2446
include_merges=False,
2448
exclude_common_ancestry=False,
2452
match_committer=None,
2456
from bzrlib.log import (
2458
make_log_request_dict,
2459
_get_info_for_log_files,
1690
from bzrlib.log import show_log
2461
1691
direction = (forward and 'forward') or 'reverse'
2462
if (exclude_common_ancestry
2463
and (revision is None or len(revision) != 2)):
2464
raise errors.BzrCommandError(
2465
'--exclude-common-ancestry requires -r with two revisions')
2470
raise errors.BzrCommandError(
2471
'--levels and --include-merges are mutually exclusive')
2473
if change is not None:
2475
raise errors.RangeInChangeOption()
2476
if revision is not None:
2477
raise errors.BzrCommandError(
2478
'--revision and --change are mutually exclusive')
2483
filter_by_dir = False
2485
# find the file ids to log and check for directory filtering
2486
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2487
revision, file_list, self.add_cleanup)
2488
for relpath, file_id, kind in file_info_list:
1696
# find the file id to log:
1698
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1702
tree = b.basis_tree()
1703
file_id = tree.path2id(fp)
2489
1704
if file_id is None:
2490
1705
raise errors.BzrCommandError(
2491
"Path unknown at end or start of revision range: %s" %
2493
# If the relpath is the top of the tree, we log everything
2498
file_ids.append(file_id)
2499
filter_by_dir = filter_by_dir or (
2500
kind in ['directory', 'tree-reference'])
1706
"Path does not have any revision history: %s" %
2503
# FIXME ? log the current subdir only RBC 20060203
1710
# FIXME ? log the current subdir only RBC 20060203
2504
1711
if revision is not None \
2505
1712
and len(revision) > 0 and revision[0].get_branch():
2506
1713
location = revision[0].get_branch()
2509
1716
dir, relpath = bzrdir.BzrDir.open_containing(location)
2510
1717
b = dir.open_branch()
2511
self.add_cleanup(b.lock_read().unlock)
2512
rev1, rev2 = _get_revision_range(revision, b, self.name())
2514
if b.get_config().validate_signatures_in_log():
2518
if not gpg.GPGStrategy.verify_signatures_available():
2519
raise errors.GpgmeNotInstalled(None)
2521
# Decide on the type of delta & diff filtering to use
2522
# TODO: add an --all-files option to make this configurable & consistent
2530
diff_type = 'partial'
2534
# Build the log formatter
2535
if log_format is None:
2536
log_format = log.log_formatter_registry.get_default(b)
2537
# Make a non-encoding output to include the diffs - bug 328007
2538
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2539
lf = log_format(show_ids=show_ids, to_file=self.outf,
2540
to_exact_file=unencoded_output,
2541
show_timezone=timezone,
2542
delta_format=get_verbosity_level(),
2544
show_advice=levels is None,
2545
author_list_handler=authors)
2547
# Choose the algorithm for doing the logging. It's annoying
2548
# having multiple code paths like this but necessary until
2549
# the underlying repository format is faster at generating
2550
# deltas or can provide everything we need from the indices.
2551
# The default algorithm - match-using-deltas - works for
2552
# multiple files and directories and is faster for small
2553
# amounts of history (200 revisions say). However, it's too
2554
# slow for logging a single file in a repository with deep
2555
# history, i.e. > 10K revisions. In the spirit of "do no
2556
# evil when adding features", we continue to use the
2557
# original algorithm - per-file-graph - for the "single
2558
# file that isn't a directory without showing a delta" case.
2559
partial_history = revision and b.repository._format.supports_chks
2560
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2561
or delta_type or partial_history)
2565
match_dict[''] = match
2567
match_dict['message'] = match_message
2569
match_dict['committer'] = match_committer
2571
match_dict['author'] = match_author
2573
match_dict['bugs'] = match_bugs
2575
# Build the LogRequest and execute it
2576
if len(file_ids) == 0:
2578
rqst = make_log_request_dict(
2579
direction=direction, specific_fileids=file_ids,
2580
start_revision=rev1, end_revision=rev2, limit=limit,
2581
message_search=message, delta_type=delta_type,
2582
diff_type=diff_type, _match_using_deltas=match_using_deltas,
2583
exclude_common_ancestry=exclude_common_ancestry, match=match_dict,
2584
signature=signatures
2586
Logger(b, rqst).show(lf)
2589
def _get_revision_range(revisionspec_list, branch, command_name):
2590
"""Take the input of a revision option and turn it into a revision range.
2592
It returns RevisionInfo objects which can be used to obtain the rev_id's
2593
of the desired revisions. It does some user input validations.
2595
if revisionspec_list is None:
2598
elif len(revisionspec_list) == 1:
2599
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2600
elif len(revisionspec_list) == 2:
2601
start_spec = revisionspec_list[0]
2602
end_spec = revisionspec_list[1]
2603
if end_spec.get_branch() != start_spec.get_branch():
2604
# b is taken from revision[0].get_branch(), and
2605
# show_log will use its revision_history. Having
2606
# different branches will lead to weird behaviors.
2607
raise errors.BzrCommandError(
2608
"bzr %s doesn't accept two revisions in different"
2609
" branches." % command_name)
2610
if start_spec.spec is None:
2611
# Avoid loading all the history.
2612
rev1 = RevisionInfo(branch, None, None)
2614
rev1 = start_spec.in_history(branch)
2615
# Avoid loading all of history when we know a missing
2616
# end of range means the last revision ...
2617
if end_spec.spec is None:
2618
last_revno, last_revision_id = branch.last_revision_info()
2619
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2621
rev2 = end_spec.in_history(branch)
2623
raise errors.BzrCommandError(
2624
'bzr %s --revision takes one or two values.' % command_name)
2628
def _revision_range_to_revid_range(revision_range):
2631
if revision_range[0] is not None:
2632
rev_id1 = revision_range[0].rev_id
2633
if revision_range[1] is not None:
2634
rev_id2 = revision_range[1].rev_id
2635
return rev_id1, rev_id2
1721
if revision is None:
1724
elif len(revision) == 1:
1725
rev1 = rev2 = revision[0].in_history(b)
1726
elif len(revision) == 2:
1727
if revision[1].get_branch() != revision[0].get_branch():
1728
# b is taken from revision[0].get_branch(), and
1729
# show_log will use its revision_history. Having
1730
# different branches will lead to weird behaviors.
1731
raise errors.BzrCommandError(
1732
"Log doesn't accept two revisions in different"
1734
rev1 = revision[0].in_history(b)
1735
rev2 = revision[1].in_history(b)
1737
raise errors.BzrCommandError(
1738
'bzr log --revision takes one or two values.')
1740
if log_format is None:
1741
log_format = log.log_formatter_registry.get_default(b)
1743
lf = log_format(show_ids=show_ids, to_file=self.outf,
1744
show_timezone=timezone)
1750
direction=direction,
1751
start_revision=rev1,
2637
1759
def get_log_format(long=False, short=False, line=False, default='long'):
2638
1760
log_format = default
2709
1829
if path is None:
2713
1834
raise errors.BzrCommandError('cannot specify both --from-root'
2716
tree, branch, relpath = \
2717
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2719
# Calculate the prefix to use
1838
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2723
prefix = relpath + '/'
2724
elif fs_path != '.' and not fs_path.endswith('/'):
2725
prefix = fs_path + '/'
2727
if revision is not None or tree is None:
2728
tree = _get_one_revision_tree('ls', revision, branch=branch)
2731
if isinstance(tree, WorkingTree) and tree.supports_views():
2732
view_files = tree.views.lookup_view()
2735
view_str = views.view_display_str(view_files)
2736
note("Ignoring files outside view. View is %s" % view_str)
2738
self.add_cleanup(tree.lock_read().unlock)
2739
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2740
from_dir=relpath, recursive=recursive):
2741
# Apply additional masking
2742
if not all and not selection[fc]:
2744
if kind is not None and fkind != kind:
2749
fullpath = osutils.pathjoin(relpath, fp)
2752
views.check_path_in_view(tree, fullpath)
2753
except errors.FileOutsideView:
2758
fp = osutils.pathjoin(prefix, fp)
2759
kindch = entry.kind_character()
2760
outstring = fp + kindch
2761
ui.ui_factory.clear_term()
2763
outstring = '%-8s %s' % (fc, outstring)
2764
if show_ids and fid is not None:
2765
outstring = "%-50s %s" % (outstring, fid)
2766
self.outf.write(outstring + '\n')
2768
self.outf.write(fp + '\0')
2771
self.outf.write(fid)
2772
self.outf.write('\0')
2780
self.outf.write('%-50s %s\n' % (outstring, my_id))
2782
self.outf.write(outstring + '\n')
1844
if revision is not None:
1845
tree = branch.repository.revision_tree(
1846
revision[0].as_revision_id(branch))
1848
tree = branch.basis_tree()
1852
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1853
if fp.startswith(relpath):
1854
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1855
if non_recursive and '/' in fp:
1857
if not all and not selection[fc]:
1859
if kind is not None and fkind != kind:
1862
kindch = entry.kind_character()
1863
outstring = '%-8s %s%s' % (fc, fp, kindch)
1864
if show_ids and fid is not None:
1865
outstring = "%-50s %s" % (outstring, fid)
1866
self.outf.write(outstring + '\n')
1868
self.outf.write(fp + '\0')
1871
self.outf.write(fid)
1872
self.outf.write('\0')
1880
self.outf.write('%-50s %s\n' % (fp, my_id))
1882
self.outf.write(fp + '\n')
2785
1887
class cmd_unknowns(Command):
2786
__doc__ = """List unknown files.
1888
"""List unknown files.
2790
1892
_see_also = ['ls']
2791
takes_options = ['directory']
2793
1894
@display_command
2794
def run(self, directory=u'.'):
2795
for f in WorkingTree.open_containing(directory)[0].unknowns():
1896
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2796
1897
self.outf.write(osutils.quotefn(f) + '\n')
2799
1900
class cmd_ignore(Command):
2800
__doc__ = """Ignore specified files or patterns.
1901
"""Ignore specified files or patterns.
2802
1903
See ``bzr help patterns`` for details on the syntax of patterns.
2804
If a .bzrignore file does not exist, the ignore command
2805
will create one and add the specified files or patterns to the newly
2806
created file. The ignore command will also automatically add the
2807
.bzrignore file to be versioned. Creating a .bzrignore file without
2808
the use of the ignore command will require an explicit add command.
2810
1905
To remove patterns from the ignore list, edit the .bzrignore file.
2811
1906
After adding, editing or deleting that file either indirectly by
2812
1907
using this command or directly by using an editor, be sure to commit
2815
Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
2816
the global ignore file can be found in the application data directory as
2817
C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
2818
Global ignores are not touched by this command. The global ignore file
2819
can be edited directly using an editor.
2821
Patterns prefixed with '!' are exceptions to ignore patterns and take
2822
precedence over regular ignores. Such exceptions are used to specify
2823
files that should be versioned which would otherwise be ignored.
2825
Patterns prefixed with '!!' act as regular ignore patterns, but have
2826
precedence over the '!' exception patterns.
2830
* Ignore patterns containing shell wildcards must be quoted from
2833
* Ignore patterns starting with "#" act as comments in the ignore file.
2834
To ignore patterns that begin with that character, use the "RE:" prefix.
1910
Note: ignore patterns containing shell wildcards must be quoted from
2837
1914
Ignore the top level Makefile::
2839
1916
bzr ignore ./Makefile
2841
Ignore .class files in all directories...::
1918
Ignore class files in all directories::
2843
1920
bzr ignore "*.class"
2845
...but do not ignore "special.class"::
2847
bzr ignore "!special.class"
2849
Ignore files whose name begins with the "#" character::
2853
1922
Ignore .o files under the lib directory::
2855
1924
bzr ignore "lib/**/*.o"
2998
2050
================= =========================
3001
2052
takes_args = ['dest', 'branch_or_subdir?']
3002
takes_options = ['directory',
3003
2054
Option('format',
3004
2055
help="Type of file to export to.",
3007
Option('filters', help='Apply content filters to export the '
3008
'convenient form.'),
3011
2060
help="Name of the root directory inside the exported file."),
3012
Option('per-file-timestamps',
3013
help='Set modification time of files to that of the last '
3014
'revision in which it was changed.'),
3016
2062
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3017
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
3018
2064
from bzrlib.export import export
3020
2066
if branch_or_subdir is None:
3021
tree = WorkingTree.open_containing(directory)[0]
2067
tree = WorkingTree.open_containing(u'.')[0]
3022
2068
b = tree.branch
3025
2071
b, subdir = Branch.open_containing(branch_or_subdir)
3028
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2073
if revision is None:
2074
# should be tree.last_revision FIXME
2075
rev_id = b.last_revision()
2077
if len(revision) != 1:
2078
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2079
rev_id = revision[0].as_revision_id(b)
2080
t = b.repository.revision_tree(rev_id)
3030
export(rev_tree, dest, format, root, subdir, filtered=filters,
3031
per_file_timestamps=per_file_timestamps)
2082
export(t, dest, format, root, subdir)
3032
2083
except errors.NoSuchExportFormat, e:
3033
2084
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3036
2087
class cmd_cat(Command):
3037
__doc__ = """Write the contents of a file as of a given revision to standard output.
2088
"""Write the contents of a file as of a given revision to standard output.
3039
2090
If no revision is nominated, the last revision is used.
3041
2092
Note: Take care to redirect standard output when using this command on a
3045
2096
_see_also = ['ls']
3046
takes_options = ['directory',
3047
2098
Option('name-from-revision', help='The path name in the old tree.'),
3048
Option('filters', help='Apply content filters to display the '
3049
'convenience form.'),
3052
2101
takes_args = ['filename']
3053
2102
encoding_type = 'exact'
3055
2104
@display_command
3056
def run(self, filename, revision=None, name_from_revision=False,
3057
filters=False, directory=None):
2105
def run(self, filename, revision=None, name_from_revision=False):
3058
2106
if revision is not None and len(revision) != 1:
3059
2107
raise errors.BzrCommandError("bzr cat --revision takes exactly"
3060
2108
" one revision specifier")
3061
2109
tree, branch, relpath = \
3062
_open_directory_or_containing_tree_or_branch(filename, directory)
3063
self.add_cleanup(branch.lock_read().unlock)
3064
return self._run(tree, branch, relpath, filename, revision,
3065
name_from_revision, filters)
2110
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2113
return self._run(tree, branch, relpath, filename, revision,
3067
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2118
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
3069
2119
if tree is None:
3070
2120
tree = b.basis_tree()
3071
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3072
self.add_cleanup(rev_tree.lock_read().unlock)
2121
if revision is None:
2122
revision_id = b.last_revision()
2124
revision_id = revision[0].as_revision_id(b)
2126
cur_file_id = tree.path2id(relpath)
2127
rev_tree = b.repository.revision_tree(revision_id)
3074
2128
old_file_id = rev_tree.path2id(relpath)
3076
# TODO: Split out this code to something that generically finds the
3077
# best id for a path across one or more trees; it's like
3078
# find_ids_across_trees but restricted to find just one. -- mbp
3080
2130
if name_from_revision:
3081
# Try in revision if requested
3082
2131
if old_file_id is None:
3083
raise errors.BzrCommandError(
3084
"%r is not present in revision %s" % (
3085
filename, rev_tree.get_revision_id()))
3087
actual_file_id = old_file_id
3089
cur_file_id = tree.path2id(relpath)
3090
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3091
actual_file_id = cur_file_id
3092
elif old_file_id is not None:
3093
actual_file_id = old_file_id
3095
raise errors.BzrCommandError(
3096
"%r is not present in revision %s" % (
3097
filename, rev_tree.get_revision_id()))
3099
from bzrlib.filter_tree import ContentFilterTree
3100
filter_tree = ContentFilterTree(rev_tree,
3101
rev_tree._content_filter_stack)
3102
content = filter_tree.get_file_text(actual_file_id)
3104
content = rev_tree.get_file_text(actual_file_id)
2132
raise errors.BzrCommandError("%r is not present in revision %s"
2133
% (filename, revision_id))
2135
content = rev_tree.get_file_text(old_file_id)
2136
elif cur_file_id is not None:
2137
content = rev_tree.get_file_text(cur_file_id)
2138
elif old_file_id is not None:
2139
content = rev_tree.get_file_text(old_file_id)
2141
raise errors.BzrCommandError("%r is not present in revision %s" %
2142
(filename, revision_id))
3106
2143
self.outf.write(content)
3109
2146
class cmd_local_time_offset(Command):
3110
__doc__ = """Show the offset in seconds from GMT to local time."""
2147
"""Show the offset in seconds from GMT to local time."""
3112
2149
@display_command
3114
self.outf.write("%s\n" % osutils.local_time_offset())
2151
print osutils.local_time_offset()
3118
2155
class cmd_commit(Command):
3119
__doc__ = """Commit changes into a new revision.
3121
An explanatory message needs to be given for each commit. This is
3122
often done by using the --message option (getting the message from the
3123
command line) or by using the --file option (getting the message from
3124
a file). If neither of these options is given, an editor is opened for
3125
the user to enter the message. To see the changed files in the
3126
boilerplate text loaded into the editor, use the --show-diff option.
3128
By default, the entire tree is committed and the person doing the
3129
commit is assumed to be the author. These defaults can be overridden
3134
If selected files are specified, only changes to those files are
3135
committed. If a directory is specified then the directory and
3136
everything within it is committed.
3138
When excludes are given, they take precedence over selected files.
3139
For example, to commit only changes within foo, but not changes
3142
bzr commit foo -x foo/bar
3144
A selective commit after a merge is not yet supported.
3148
If the author of the change is not the same person as the committer,
3149
you can specify the author's name using the --author option. The
3150
name should be in the same format as a committer-id, e.g.
3151
"John Doe <jdoe@example.com>". If there is more than one author of
3152
the change you can specify the option multiple times, once for each
3157
A common mistake is to forget to add a new file or directory before
3158
running the commit command. The --strict option checks for unknown
3159
files and aborts the commit if any are found. More advanced pre-commit
3160
checks can be implemented by defining hooks. See ``bzr help hooks``
3165
If you accidentially commit the wrong changes or make a spelling
3166
mistake in the commit message say, you can use the uncommit command
3167
to undo it. See ``bzr help uncommit`` for details.
3169
Hooks can also be configured to run after a commit. This allows you
3170
to trigger updates to external systems like bug trackers. The --fixes
3171
option can be used to record the association between a revision and
3172
one or more bugs. See ``bzr help bugs`` for details.
2156
"""Commit changes into a new revision.
2158
If no arguments are given, the entire tree is committed.
2160
If selected files are specified, only changes to those files are
2161
committed. If a directory is specified then the directory and everything
2162
within it is committed.
2164
When excludes are given, they take precedence over selected files.
2165
For example, too commit only changes within foo, but not changes within
2168
bzr commit foo -x foo/bar
2170
If author of the change is not the same person as the committer, you can
2171
specify the author's name using the --author option. The name should be
2172
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2174
A selected-file commit may fail in some cases where the committed
2175
tree would be invalid. Consider::
2180
bzr commit foo -m "committing foo"
2181
bzr mv foo/bar foo/baz
2184
bzr commit foo/bar -m "committing bar but not baz"
2186
In the example above, the last commit will fail by design. This gives
2187
the user the opportunity to decide whether they want to commit the
2188
rename at the same time, separately first, or not at all. (As a general
2189
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2191
Note: A selected-file commit after a merge is not yet supported.
3175
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
2193
# TODO: Run hooks on tree to-be-committed, and after commit.
2195
# TODO: Strict commit that fails if there are deleted files.
2196
# (what does "deleted files" mean ??)
2198
# TODO: Give better message for -s, --summary, used by tla people
2200
# XXX: verbose currently does nothing
2202
_see_also = ['bugs', 'uncommit']
3176
2203
takes_args = ['selected*']
3177
2204
takes_options = [
3178
2205
ListOption('exclude', type=str, short_name='x',
3270
2287
if fixes is None:
3272
bug_property = bugtracker.encode_fixes_bug_urls(
3273
self._iter_bug_fix_urls(fixes, tree.branch))
2289
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
3274
2290
if bug_property:
3275
2291
properties['bugs'] = bug_property
3277
2293
if local and not tree.branch.get_bound_location():
3278
2294
raise errors.LocalRequiresBoundBranch()
3280
if message is not None:
3282
file_exists = osutils.lexists(message)
3283
except UnicodeError:
3284
# The commit message contains unicode characters that can't be
3285
# represented in the filesystem encoding, so that can't be a
3290
'The commit message is a file name: "%(f)s".\n'
3291
'(use --file "%(f)s" to take commit message from that file)'
3293
ui.ui_factory.show_warning(warning_msg)
3295
message = message.replace('\r\n', '\n')
3296
message = message.replace('\r', '\n')
3298
raise errors.BzrCommandError(
3299
"please specify either --message or --file")
3301
2296
def get_message(commit_obj):
3302
2297
"""Callback to get commit message"""
3306
my_message = f.read().decode(osutils.get_user_encoding())
3309
elif message is not None:
3310
my_message = message
3312
# No message supplied: make one up.
3313
# text is the status of the tree
3314
text = make_commit_message_template_encoded(tree,
2298
my_message = message
2299
if my_message is None and not file:
2300
t = make_commit_message_template_encoded(tree,
3315
2301
selected_list, diff=show_diff,
3316
output_encoding=osutils.get_user_encoding())
3317
# start_message is the template generated from hooks
3318
# XXX: Warning - looks like hooks return unicode,
3319
# make_commit_message_template_encoded returns user encoding.
3320
# We probably want to be using edit_commit_message instead to
3322
my_message = set_commit_message(commit_obj)
3323
if my_message is None:
3324
start_message = generate_commit_message_template(commit_obj)
3325
my_message = edit_commit_message_encoded(text,
3326
start_message=start_message)
2302
output_encoding=bzrlib.user_encoding)
2303
my_message = edit_commit_message_encoded(t)
3327
2304
if my_message is None:
3328
2305
raise errors.BzrCommandError("please specify a commit"
3329
2306
" message with either --message or --file")
2307
elif my_message and file:
2308
raise errors.BzrCommandError(
2309
"please specify either --message or --file")
2311
my_message = codecs.open(file, 'rt',
2312
bzrlib.user_encoding).read()
3330
2313
if my_message == "":
3331
raise errors.BzrCommandError("Empty commit message specified."
3332
" Please specify a commit message with either"
3333
" --message or --file or leave a blank message"
3334
" with --message \"\".")
2314
raise errors.BzrCommandError("empty commit message specified")
3335
2315
return my_message
3337
# The API permits a commit with a filter of [] to mean 'select nothing'
3338
# but the command line should not do that.
3339
if not selected_list:
3340
selected_list = None
3342
2318
tree.commit(message_callback=get_message,
3343
2319
specific_files=selected_list,
3344
2320
allow_pointless=unchanged, strict=strict, local=local,
3345
2321
reporter=None, verbose=verbose, revprops=properties,
3346
authors=author, timestamp=commit_stamp,
3348
exclude=tree.safe_relpath_files(exclude),
2323
exclude=safe_relpath_files(tree, exclude))
3350
2324
except PointlessCommit:
3351
raise errors.BzrCommandError("No changes to commit."
3352
" Please 'bzr add' the files you want to commit, or use"
3353
" --unchanged to force an empty commit.")
2325
# FIXME: This should really happen before the file is read in;
2326
# perhaps prepare the commit; get the message; then actually commit
2327
raise errors.BzrCommandError("no changes to commit."
2328
" use --unchanged to commit anyhow")
3354
2329
except ConflictsInTree:
3355
2330
raise errors.BzrCommandError('Conflicts detected in working '
3356
2331
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3770
2674
encoding_type = 'replace'
3773
Command.__init__(self)
3774
self.additional_selftest_args = {}
3776
2676
def run(self, testspecs_list=None, verbose=False, one=False,
3777
2677
transport=None, benchmark=None,
2678
lsprof_timed=None, cache_dir=None,
3779
2679
first=False, list_only=False,
3780
2680
randomize=None, exclude=None, strict=False,
3781
load_list=None, debugflag=None, starting_with=None, subunit=False,
3782
parallel=None, lsprof_tests=False):
3783
from bzrlib import tests
2681
load_list=None, debugflag=None, starting_with=None):
2683
from bzrlib.tests import selftest
2684
import bzrlib.benchmarks as benchmarks
2685
from bzrlib.benchmarks import tree_creator
2687
# Make deprecation warnings visible, unless -Werror is set
2688
symbol_versioning.activate_deprecation_warnings(override=False)
2690
if cache_dir is not None:
2691
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2693
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2694
print ' %s (%s python%s)' % (
2696
bzrlib.version_string,
2697
bzrlib._format_version_tuple(sys.version_info),
3785
2700
if testspecs_list is not None:
3786
2701
pattern = '|'.join(testspecs_list)
3791
from bzrlib.tests import SubUnitBzrRunner
3793
raise errors.BzrCommandError("subunit not available. subunit "
3794
"needs to be installed to use --subunit.")
3795
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3796
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3797
# stdout, which would corrupt the subunit stream.
3798
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3799
# following code can be deleted when it's sufficiently deployed
3800
# -- vila/mgz 20100514
3801
if (sys.platform == "win32"
3802
and getattr(sys.stdout, 'fileno', None) is not None):
3804
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3806
self.additional_selftest_args.setdefault(
3807
'suite_decorators', []).append(parallel)
3809
raise errors.BzrCommandError(
3810
"--benchmark is no longer supported from bzr 2.2; "
3811
"use bzr-usertest instead")
3812
test_suite_factory = None
3814
exclude_pattern = None
2705
test_suite_factory = benchmarks.test_suite
2706
# Unless user explicitly asks for quiet, be verbose in benchmarks
2707
verbose = not is_quiet()
2708
# TODO: should possibly lock the history file...
2709
benchfile = open(".perf_history", "at", buffering=1)
3816
exclude_pattern = '(' + '|'.join(exclude) + ')'
3817
selftest_kwargs = {"verbose": verbose,
3819
"stop_on_failure": one,
3820
"transport": transport,
3821
"test_suite_factory": test_suite_factory,
3822
"lsprof_timed": lsprof_timed,
3823
"lsprof_tests": lsprof_tests,
3824
"matching_tests_first": first,
3825
"list_only": list_only,
3826
"random_seed": randomize,
3827
"exclude_pattern": exclude_pattern,
3829
"load_list": load_list,
3830
"debug_flags": debugflag,
3831
"starting_with": starting_with
3833
selftest_kwargs.update(self.additional_selftest_args)
3835
# Make deprecation warnings visible, unless -Werror is set
3836
cleanup = symbol_versioning.activate_deprecation_warnings(
2711
test_suite_factory = None
3839
result = tests.selftest(**selftest_kwargs)
2714
result = selftest(verbose=verbose,
2716
stop_on_failure=one,
2717
transport=transport,
2718
test_suite_factory=test_suite_factory,
2719
lsprof_timed=lsprof_timed,
2720
bench_history=benchfile,
2721
matching_tests_first=first,
2722
list_only=list_only,
2723
random_seed=randomize,
2724
exclude_pattern=exclude,
2726
load_list=load_list,
2727
debug_flags=debugflag,
2728
starting_with=starting_with,
2731
if benchfile is not None:
2734
note('tests passed')
2736
note('tests failed')
3842
2737
return int(not result)
3845
2740
class cmd_version(Command):
3846
__doc__ = """Show version of bzr."""
2741
"""Show version of bzr."""
3848
2743
encoding_type = 'replace'
3849
2744
takes_options = [
3862
2757
class cmd_rocks(Command):
3863
__doc__ = """Statement of optimism."""
2758
"""Statement of optimism."""
3867
2762
@display_command
3869
self.outf.write("It sure does!\n")
2764
print "It sure does!"
3872
2767
class cmd_find_merge_base(Command):
3873
__doc__ = """Find and print a base revision for merging two branches."""
2768
"""Find and print a base revision for merging two branches."""
3874
2769
# TODO: Options to specify revisions on either side, as if
3875
2770
# merging only part of the history.
3876
2771
takes_args = ['branch', 'other']
3879
2774
@display_command
3880
2775
def run(self, branch, other):
3881
2776
from bzrlib.revision import ensure_null
3883
2778
branch1 = Branch.open_containing(branch)[0]
3884
2779
branch2 = Branch.open_containing(other)[0]
3885
self.add_cleanup(branch1.lock_read().unlock)
3886
self.add_cleanup(branch2.lock_read().unlock)
3887
last1 = ensure_null(branch1.last_revision())
3888
last2 = ensure_null(branch2.last_revision())
3890
graph = branch1.repository.get_graph(branch2.repository)
3891
base_rev_id = graph.find_unique_lca(last1, last2)
3893
self.outf.write('merge base is revision %s\n' % base_rev_id)
2784
last1 = ensure_null(branch1.last_revision())
2785
last2 = ensure_null(branch2.last_revision())
2787
graph = branch1.repository.get_graph(branch2.repository)
2788
base_rev_id = graph.find_unique_lca(last1, last2)
2790
print 'merge base is revision %s' % base_rev_id
3896
2797
class cmd_merge(Command):
3897
__doc__ = """Perform a three-way merge.
2798
"""Perform a three-way merge.
3899
2800
The source of the merge can be specified either in the form of a branch,
3900
2801
or in the form of a path to a file containing a merge directive generated
3901
2802
with bzr send. If neither is specified, the default is the upstream branch
3902
or the branch most recently merged using --remember. The source of the
3903
merge may also be specified in the form of a path to a file in another
3904
branch: in this case, only the modifications to that file are merged into
3905
the current working tree.
3907
When merging from a branch, by default bzr will try to merge in all new
3908
work from the other branch, automatically determining an appropriate base
3909
revision. If this fails, you may need to give an explicit base.
3911
To pick a different ending revision, pass "--revision OTHER". bzr will
3912
try to merge in all new work up to and including revision OTHER.
3914
If you specify two values, "--revision BASE..OTHER", only revisions BASE
3915
through OTHER, excluding BASE but including OTHER, will be merged. If this
3916
causes some revisions to be skipped, i.e. if the destination branch does
3917
not already contain revision BASE, such a merge is commonly referred to as
3918
a "cherrypick". Unlike a normal merge, Bazaar does not currently track
3919
cherrypicks. The changes look like a normal commit, and the history of the
3920
changes from the other branch is not stored in the commit.
3922
Revision numbers are always relative to the source branch.
2803
or the branch most recently merged using --remember.
2805
When merging a branch, by default the tip will be merged. To pick a different
2806
revision, pass --revision. If you specify two values, the first will be used as
2807
BASE and the second one as OTHER. Merging individual revisions, or a subset of
2808
available revisions, like this is commonly referred to as "cherrypicking".
2810
Revision numbers are always relative to the branch being merged.
2812
By default, bzr will try to merge in all new work from the other
2813
branch, automatically determining an appropriate base. If this
2814
fails, you may need to give an explicit base.
3924
2816
Merge will do its best to combine the changes in two branches, but there
3925
2817
are some kinds of problems only a human can fix. When it encounters those,
3926
2818
it will mark a conflict. A conflict means that you need to fix something,
4019
2893
allow_pending = True
4020
2894
verified = 'inapplicable'
4022
2895
tree = WorkingTree.open_containing(directory)[0]
4023
if tree.branch.revno() == 0:
4024
raise errors.BzrCommandError('Merging into empty branches not currently supported, '
4025
'https://bugs.launchpad.net/bzr/+bug/308562')
2896
change_reporter = delta._ChangeReporter(
2897
unversioned_filter=tree.is_ignored)
4028
basis_tree = tree.revision_tree(tree.last_revision())
4029
except errors.NoSuchRevision:
4030
basis_tree = tree.basis_tree()
4032
# die as quickly as possible if there are uncommitted changes
4034
if tree.has_changes():
4035
raise errors.UncommittedChanges(tree)
4037
view_info = _get_view_info_for_change_reporter(tree)
4038
change_reporter = delta._ChangeReporter(
4039
unversioned_filter=tree.is_ignored, view_info=view_info)
4040
pb = ui.ui_factory.nested_progress_bar()
4041
self.add_cleanup(pb.finished)
4042
self.add_cleanup(tree.lock_write().unlock)
4043
if location is not None:
4045
mergeable = bundle.read_mergeable_from_url(location,
4046
possible_transports=possible_transports)
4047
except errors.NotABundle:
2900
pb = ui.ui_factory.nested_progress_bar()
2901
cleanups.append(pb.finished)
2903
cleanups.append(tree.unlock)
2904
if location is not None:
2906
mergeable = bundle.read_mergeable_from_url(location,
2907
possible_transports=possible_transports)
2908
except errors.NotABundle:
2912
raise errors.BzrCommandError('Cannot use --uncommitted'
2913
' with bundles or merge directives.')
2915
if revision is not None:
2916
raise errors.BzrCommandError(
2917
'Cannot use -r with merge directives or bundles')
2918
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2921
if merger is None and uncommitted:
2922
if revision is not None and len(revision) > 0:
2923
raise errors.BzrCommandError('Cannot use --uncommitted and'
2924
' --revision at the same time.')
2925
location = self._select_branch_location(tree, location)[0]
2926
other_tree, other_path = WorkingTree.open_containing(location)
2927
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2929
allow_pending = False
2930
if other_path != '':
2931
merger.interesting_files = [other_path]
2934
merger, allow_pending = self._get_merger_from_branch(tree,
2935
location, revision, remember, possible_transports, pb)
2937
merger.merge_type = merge_type
2938
merger.reprocess = reprocess
2939
merger.show_base = show_base
2940
self.sanity_check_merger(merger)
2941
if (merger.base_rev_id == merger.other_rev_id and
2942
merger.other_rev_id is not None):
2943
note('Nothing to do.')
2946
if merger.interesting_files is not None:
2947
raise errors.BzrCommandError('Cannot pull individual files')
2948
if (merger.base_rev_id == tree.last_revision()):
2949
result = tree.pull(merger.other_branch, False,
2950
merger.other_rev_id)
2951
result.report(self.outf)
2953
merger.check_basis(not force)
2955
return self._do_preview(merger)
4051
raise errors.BzrCommandError('Cannot use --uncommitted'
4052
' with bundles or merge directives.')
4054
if revision is not None:
4055
raise errors.BzrCommandError(
4056
'Cannot use -r with merge directives or bundles')
4057
merger, verified = _mod_merge.Merger.from_mergeable(tree,
4060
if merger is None and uncommitted:
4061
if revision is not None and len(revision) > 0:
4062
raise errors.BzrCommandError('Cannot use --uncommitted and'
4063
' --revision at the same time.')
4064
merger = self.get_merger_from_uncommitted(tree, location, None)
4065
allow_pending = False
4068
merger, allow_pending = self._get_merger_from_branch(tree,
4069
location, revision, remember, possible_transports, None)
4071
merger.merge_type = merge_type
4072
merger.reprocess = reprocess
4073
merger.show_base = show_base
4074
self.sanity_check_merger(merger)
4075
if (merger.base_rev_id == merger.other_rev_id and
4076
merger.other_rev_id is not None):
4077
# check if location is a nonexistent file (and not a branch) to
4078
# disambiguate the 'Nothing to do'
4079
if merger.interesting_files:
4080
if not merger.other_tree.has_filename(
4081
merger.interesting_files[0]):
4082
note("merger: " + str(merger))
4083
raise errors.PathsDoNotExist([location])
4084
note('Nothing to do.')
4086
if pull and not preview:
4087
if merger.interesting_files is not None:
4088
raise errors.BzrCommandError('Cannot pull individual files')
4089
if (merger.base_rev_id == tree.last_revision()):
4090
result = tree.pull(merger.other_branch, False,
4091
merger.other_rev_id)
4092
result.report(self.outf)
4094
if merger.this_basis is None:
4095
raise errors.BzrCommandError(
4096
"This branch has no commits."
4097
" (perhaps you would prefer 'bzr pull')")
4099
return self._do_preview(merger)
4101
return self._do_interactive(merger)
4103
return self._do_merge(merger, change_reporter, allow_pending,
4106
def _get_preview(self, merger):
2957
return self._do_merge(merger, change_reporter, allow_pending,
2960
for cleanup in reversed(cleanups):
2963
def _do_preview(self, merger):
2964
from bzrlib.diff import show_diff_trees
4107
2965
tree_merger = merger.make_merger()
4108
2966
tt = tree_merger.make_preview_transform()
4109
self.add_cleanup(tt.finalize)
4110
result_tree = tt.get_preview_tree()
4113
def _do_preview(self, merger):
4114
from bzrlib.diff import show_diff_trees
4115
result_tree = self._get_preview(merger)
4116
path_encoding = osutils.get_diff_header_encoding()
4117
show_diff_trees(merger.this_tree, result_tree, self.outf,
4118
old_label='', new_label='',
4119
path_encoding=path_encoding)
2968
result_tree = tt.get_preview_tree()
2969
show_diff_trees(merger.this_tree, result_tree, self.outf,
2970
old_label='', new_label='')
4121
2974
def _do_merge(self, merger, change_reporter, allow_pending, verified):
4122
2975
merger.change_reporter = change_reporter
4315
3122
def run(self, file_list=None, merge_type=None, show_base=False,
4316
3123
reprocess=False):
4317
from bzrlib.conflicts import restore
4318
3124
if merge_type is None:
4319
3125
merge_type = _mod_merge.Merge3Merger
4320
tree, file_list = WorkingTree.open_containing_paths(file_list)
4321
self.add_cleanup(tree.lock_write().unlock)
4322
parents = tree.get_parent_ids()
4323
if len(parents) != 2:
4324
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4325
" merges. Not cherrypicking or"
4327
repository = tree.branch.repository
4328
interesting_ids = None
4330
conflicts = tree.conflicts()
4331
if file_list is not None:
4332
interesting_ids = set()
4333
for filename in file_list:
4334
file_id = tree.path2id(filename)
4336
raise errors.NotVersionedError(filename)
4337
interesting_ids.add(file_id)
4338
if tree.kind(file_id) != "directory":
4341
for name, ie in tree.inventory.iter_entries(file_id):
4342
interesting_ids.add(ie.file_id)
4343
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4345
# Remerge only supports resolving contents conflicts
4346
allowed_conflicts = ('text conflict', 'contents conflict')
4347
restore_files = [c.path for c in conflicts
4348
if c.typestring in allowed_conflicts]
4349
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4350
tree.set_conflicts(ConflictList(new_conflicts))
4351
if file_list is not None:
4352
restore_files = file_list
4353
for filename in restore_files:
3126
tree, file_list = tree_files(file_list)
3129
parents = tree.get_parent_ids()
3130
if len(parents) != 2:
3131
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3132
" merges. Not cherrypicking or"
3134
repository = tree.branch.repository
3135
interesting_ids = None
3137
conflicts = tree.conflicts()
3138
if file_list is not None:
3139
interesting_ids = set()
3140
for filename in file_list:
3141
file_id = tree.path2id(filename)
3143
raise errors.NotVersionedError(filename)
3144
interesting_ids.add(file_id)
3145
if tree.kind(file_id) != "directory":
3148
for name, ie in tree.inventory.iter_entries(file_id):
3149
interesting_ids.add(ie.file_id)
3150
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3152
# Remerge only supports resolving contents conflicts
3153
allowed_conflicts = ('text conflict', 'contents conflict')
3154
restore_files = [c.path for c in conflicts
3155
if c.typestring in allowed_conflicts]
3156
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3157
tree.set_conflicts(ConflictList(new_conflicts))
3158
if file_list is not None:
3159
restore_files = file_list
3160
for filename in restore_files:
3162
restore(tree.abspath(filename))
3163
except errors.NotConflicted:
3165
# Disable pending merges, because the file texts we are remerging
3166
# have not had those merges performed. If we use the wrong parents
3167
# list, we imply that the working tree text has seen and rejected
3168
# all the changes from the other tree, when in fact those changes
3169
# have not yet been seen.
3170
pb = ui.ui_factory.nested_progress_bar()
3171
tree.set_parent_ids(parents[:1])
4355
restore(tree.abspath(filename))
4356
except errors.NotConflicted:
4358
# Disable pending merges, because the file texts we are remerging
4359
# have not had those merges performed. If we use the wrong parents
4360
# list, we imply that the working tree text has seen and rejected
4361
# all the changes from the other tree, when in fact those changes
4362
# have not yet been seen.
4363
tree.set_parent_ids(parents[:1])
4365
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4366
merger.interesting_ids = interesting_ids
4367
merger.merge_type = merge_type
4368
merger.show_base = show_base
4369
merger.reprocess = reprocess
4370
conflicts = merger.do_merge()
3173
merger = _mod_merge.Merger.from_revision_ids(pb,
3175
merger.interesting_ids = interesting_ids
3176
merger.merge_type = merge_type
3177
merger.show_base = show_base
3178
merger.reprocess = reprocess
3179
conflicts = merger.do_merge()
3181
tree.set_parent_ids(parents)
4372
tree.set_parent_ids(parents)
4373
3185
if conflicts > 0:
4589
3350
" or specified.")
4590
3351
display_url = urlutils.unescape_for_display(parent,
4591
3352
self.outf.encoding)
4592
message("Using saved parent location: "
3353
self.outf.write("Using saved parent location: "
4593
3354
+ display_url + "\n")
4595
3356
remote_branch = Branch.open(other_branch)
4596
3357
if remote_branch.base == local_branch.base:
4597
3358
remote_branch = local_branch
4599
self.add_cleanup(remote_branch.lock_read().unlock)
4601
local_revid_range = _revision_range_to_revid_range(
4602
_get_revision_range(my_revision, local_branch,
4605
remote_revid_range = _revision_range_to_revid_range(
4606
_get_revision_range(revision,
4607
remote_branch, self.name()))
4609
local_extra, remote_extra = find_unmerged(
4610
local_branch, remote_branch, restrict,
4611
backward=not reverse,
4612
include_merges=include_merges,
4613
local_revid_range=local_revid_range,
4614
remote_revid_range=remote_revid_range)
4616
if log_format is None:
4617
registry = log.log_formatter_registry
4618
log_format = registry.get_default(local_branch)
4619
lf = log_format(to_file=self.outf,
4621
show_timezone='original')
4624
if local_extra and not theirs_only:
4625
message("You have %d extra revision(s):\n" %
4627
for revision in iter_log_revisions(local_extra,
4628
local_branch.repository,
4630
lf.log_revision(revision)
4631
printed_local = True
4634
printed_local = False
4636
if remote_extra and not mine_only:
4637
if printed_local is True:
4639
message("You are missing %d revision(s):\n" %
4641
for revision in iter_log_revisions(remote_extra,
4642
remote_branch.repository,
4644
lf.log_revision(revision)
4647
if mine_only and not local_extra:
4648
# We checked local, and found nothing extra
4649
message('This branch is up to date.\n')
4650
elif theirs_only and not remote_extra:
4651
# We checked remote, and found nothing extra
4652
message('Other branch is up to date.\n')
4653
elif not (mine_only or theirs_only or local_extra or
4655
# We checked both branches, and neither one had extra
4657
message("Branches are up to date.\n")
3359
local_branch.lock_read()
3361
remote_branch.lock_read()
3363
local_extra, remote_extra = find_unmerged(
3364
local_branch, remote_branch, restrict)
3366
if log_format is None:
3367
registry = log.log_formatter_registry
3368
log_format = registry.get_default(local_branch)
3369
lf = log_format(to_file=self.outf,
3371
show_timezone='original')
3372
if reverse is False:
3373
if local_extra is not None:
3374
local_extra.reverse()
3375
if remote_extra is not None:
3376
remote_extra.reverse()
3379
if local_extra and not theirs_only:
3380
self.outf.write("You have %d extra revision(s):\n" %
3382
for revision in iter_log_revisions(local_extra,
3383
local_branch.repository,
3385
lf.log_revision(revision)
3386
printed_local = True
3389
printed_local = False
3391
if remote_extra and not mine_only:
3392
if printed_local is True:
3393
self.outf.write("\n\n\n")
3394
self.outf.write("You are missing %d revision(s):\n" %
3396
for revision in iter_log_revisions(remote_extra,
3397
remote_branch.repository,
3399
lf.log_revision(revision)
3402
if mine_only and not local_extra:
3403
# We checked local, and found nothing extra
3404
self.outf.write('This branch is up to date.\n')
3405
elif theirs_only and not remote_extra:
3406
# We checked remote, and found nothing extra
3407
self.outf.write('Other branch is up to date.\n')
3408
elif not (mine_only or theirs_only or local_extra or
3410
# We checked both branches, and neither one had extra
3412
self.outf.write("Branches are up to date.\n")
3414
remote_branch.unlock()
3416
local_branch.unlock()
4659
3417
if not status_code and parent is None and other_branch is not None:
4660
self.add_cleanup(local_branch.lock_write().unlock)
4661
# handle race conditions - a parent might be set while we run.
4662
if local_branch.get_parent() is None:
4663
local_branch.set_parent(remote_branch.base)
3418
local_branch.lock_write()
3420
# handle race conditions - a parent might be set while we run.
3421
if local_branch.get_parent() is None:
3422
local_branch.set_parent(remote_branch.base)
3424
local_branch.unlock()
4664
3425
return status_code
4667
3428
class cmd_pack(Command):
4668
__doc__ = """Compress the data within a repository.
4670
This operation compresses the data within a bazaar repository. As
4671
bazaar supports automatic packing of repository, this operation is
4672
normally not required to be done manually.
4674
During the pack operation, bazaar takes a backup of existing repository
4675
data, i.e. pack files. This backup is eventually removed by bazaar
4676
automatically when it is safe to do so. To save disk space by removing
4677
the backed up pack files, the --clean-obsolete-packs option may be
4680
Warning: If you use --clean-obsolete-packs and your machine crashes
4681
during or immediately after repacking, you may be left with a state
4682
where the deletion has been written to disk but the new packs have not
4683
been. In this case the repository may be unusable.
3429
"""Compress the data within a repository."""
4686
3431
_see_also = ['repositories']
4687
3432
takes_args = ['branch_or_repo?']
4689
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
4692
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
3434
def run(self, branch_or_repo='.'):
4693
3435
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
4695
3437
branch = dir.open_branch()
4696
3438
repository = branch.repository
4697
3439
except errors.NotBranchError:
4698
3440
repository = dir.open_repository()
4699
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
4702
3444
class cmd_plugins(Command):
4703
__doc__ = """List the installed plugins.
3445
"""List the installed plugins.
4705
3447
This command displays the list of installed plugins including
4706
3448
version of plugin and a short description of each.
5104
3845
class cmd_serve(Command):
5105
__doc__ = """Run the bzr server."""
3846
"""Run the bzr server."""
5107
3848
aliases = ['server']
5109
3850
takes_options = [
5111
3852
help='Serve on stdin/out for use from inetd or sshd.'),
5112
RegistryOption('protocol',
5113
help="Protocol to serve.",
5114
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5115
value_switches=True),
5117
3854
help='Listen for connections on nominated port of the form '
5118
3855
'[hostname:]portnumber. Passing 0 as the port number will '
5119
'result in a dynamically allocated port. The default port '
5120
'depends on the protocol.',
3856
'result in a dynamically allocated port. The default port is '
5122
custom_help('directory',
5123
help='Serve contents of this directory.'),
3860
help='Serve contents of this directory.',
5124
3862
Option('allow-writes',
5125
3863
help='By default the server is a readonly server. Supplying '
5126
3864
'--allow-writes enables write access to the contents of '
5127
'the served directory and below. Note that ``bzr serve`` '
5128
'does not perform authentication, so unless some form of '
5129
'external authentication is arranged supplying this '
5130
'option leads to global uncontrolled write access to your '
3865
'the served directory and below.'
5135
def get_host_and_port(self, port):
5136
"""Return the host and port to run the smart server on.
5138
If 'port' is None, None will be returned for the host and port.
5140
If 'port' has a colon in it, the string before the colon will be
5141
interpreted as the host.
5143
:param port: A string of the port to run the server on.
5144
:return: A tuple of (host, port), where 'host' is a host name or IP,
5145
and port is an integer TCP/IP port.
5148
if port is not None:
5150
host, port = port.split(':')
5154
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5156
from bzrlib import transport
3869
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3870
from bzrlib import lockdir
3871
from bzrlib.smart import medium, server
3872
from bzrlib.transport import get_transport
3873
from bzrlib.transport.chroot import ChrootServer
5157
3874
if directory is None:
5158
3875
directory = os.getcwd()
5159
if protocol is None:
5160
protocol = transport.transport_server_registry.get()
5161
host, port = self.get_host_and_port(port)
5162
3876
url = urlutils.local_path_to_url(directory)
5163
3877
if not allow_writes:
5164
3878
url = 'readonly+' + url
5165
t = transport.get_transport(url)
5166
protocol(t, host, port, inet)
3879
chroot_server = ChrootServer(get_transport(url))
3880
chroot_server.setUp()
3881
t = get_transport(chroot_server.get_url())
3883
smart_server = medium.SmartServerPipeStreamMedium(
3884
sys.stdin, sys.stdout, t)
3886
host = medium.BZR_DEFAULT_INTERFACE
3888
port = medium.BZR_DEFAULT_PORT
3891
host, port = port.split(':')
3893
smart_server = server.SmartTCPServer(t, host=host, port=port)
3894
print 'listening on port: ', smart_server.port
3896
# for the duration of this server, no UI output is permitted.
3897
# note that this may cause problems with blackbox tests. This should
3898
# be changed with care though, as we dont want to use bandwidth sending
3899
# progress over stderr to smart server clients!
3900
old_factory = ui.ui_factory
3901
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3903
ui.ui_factory = ui.SilentUIFactory()
3904
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3905
smart_server.serve()
3907
ui.ui_factory = old_factory
3908
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
5169
3911
class cmd_join(Command):
5170
__doc__ = """Combine a tree into its containing tree.
5172
This command requires the target tree to be in a rich-root format.
3912
"""Combine a subtree into its containing tree.
3914
This command is for experimental use only. It requires the target tree
3915
to be in dirstate-with-subtree format, which cannot be converted into
5174
3918
The TREE argument should be an independent tree, inside another tree, but
5175
3919
not part of it. (Such trees can be produced by "bzr split", but also by
5176
3920
running "bzr branch" with the target inside a tree.)
5178
The result is a combined tree, with the subtree no longer an independent
3922
The result is a combined tree, with the subtree no longer an independant
5179
3923
part. This is marked as a merge of the subtree into the containing tree,
5180
3924
and all history is preserved.
3926
If --reference is specified, the subtree retains its independence. It can
3927
be branched by itself, and can be part of multiple projects at the same
3928
time. But operations performed in the containing tree, such as commit
3929
and merge, will recurse into the subtree.
5183
3932
_see_also = ['split']
5184
3933
takes_args = ['tree']
5185
3934
takes_options = [
5186
Option('reference', help='Join by reference.', hidden=True),
3935
Option('reference', help='Join by reference.'),
5189
3939
def run(self, tree, reference=False):
5190
3940
sub_tree = WorkingTree.open(tree)
5434
4157
short_name='f',
5436
4159
Option('output', short_name='o',
5437
help='Write merge directive to this file or directory; '
4160
help='Write merge directive to this file; '
5438
4161
'use - for stdout.',
5441
help='Refuse to send if there are uncommitted changes in'
5442
' the working tree, --no-strict disables the check.'),
5443
4163
Option('mail-to', help='Mail the request to this address.',
5447
Option('body', help='Body for the email.', type=unicode),
5448
RegistryOption('format',
5449
help='Use the specified output format.',
5450
lazy_registry=('bzrlib.send', 'format_registry')),
4167
RegistryOption.from_kwargs('format',
4168
'Use the specified output format.',
4169
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4170
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5453
4173
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5454
no_patch=False, revision=None, remember=None, output=None,
5455
format=None, mail_to=None, message=None, body=None,
5456
strict=None, **kwargs):
5457
from bzrlib.send import send
5458
return send(submit_branch, revision, public_branch, remember,
5459
format, no_bundle, no_patch, output,
5460
kwargs.get('from', '.'), mail_to, message, body,
4174
no_patch=False, revision=None, remember=False, output=None,
4175
format='4', mail_to=None, message=None, **kwargs):
4176
return self._run(submit_branch, revision, public_branch, remember,
4177
format, no_bundle, no_patch, output,
4178
kwargs.get('from', '.'), mail_to, message)
4180
def _run(self, submit_branch, revision, public_branch, remember, format,
4181
no_bundle, no_patch, output, from_, mail_to, message):
4182
from bzrlib.revision import NULL_REVISION
4183
branch = Branch.open_containing(from_)[0]
4185
outfile = StringIO()
4189
outfile = open(output, 'wb')
4190
# we may need to write data into branch's repository to calculate
4195
config = branch.get_config()
4197
mail_to = config.get_user_option('submit_to')
4198
mail_client = config.get_mail_client()
4199
if remember and submit_branch is None:
4200
raise errors.BzrCommandError(
4201
'--remember requires a branch to be specified.')
4202
stored_submit_branch = branch.get_submit_branch()
4203
remembered_submit_branch = None
4204
if submit_branch is None:
4205
submit_branch = stored_submit_branch
4206
remembered_submit_branch = "submit"
4208
if stored_submit_branch is None or remember:
4209
branch.set_submit_branch(submit_branch)
4210
if submit_branch is None:
4211
submit_branch = branch.get_parent()
4212
remembered_submit_branch = "parent"
4213
if submit_branch is None:
4214
raise errors.BzrCommandError('No submit branch known or'
4216
if remembered_submit_branch is not None:
4217
note('Using saved %s location "%s" to determine what '
4218
'changes to submit.', remembered_submit_branch,
4222
submit_config = Branch.open(submit_branch).get_config()
4223
mail_to = submit_config.get_user_option("child_submit_to")
4225
stored_public_branch = branch.get_public_branch()
4226
if public_branch is None:
4227
public_branch = stored_public_branch
4228
elif stored_public_branch is None or remember:
4229
branch.set_public_branch(public_branch)
4230
if no_bundle and public_branch is None:
4231
raise errors.BzrCommandError('No public branch specified or'
4233
base_revision_id = None
4235
if revision is not None:
4236
if len(revision) > 2:
4237
raise errors.BzrCommandError('bzr send takes '
4238
'at most two one revision identifiers')
4239
revision_id = revision[-1].as_revision_id(branch)
4240
if len(revision) == 2:
4241
base_revision_id = revision[0].as_revision_id(branch)
4242
if revision_id is None:
4243
revision_id = branch.last_revision()
4244
if revision_id == NULL_REVISION:
4245
raise errors.BzrCommandError('No revisions to submit.')
4247
directive = merge_directive.MergeDirective2.from_objects(
4248
branch.repository, revision_id, time.time(),
4249
osutils.local_time_offset(), submit_branch,
4250
public_branch=public_branch, include_patch=not no_patch,
4251
include_bundle=not no_bundle, message=message,
4252
base_revision_id=base_revision_id)
4253
elif format == '0.9':
4256
patch_type = 'bundle'
4258
raise errors.BzrCommandError('Format 0.9 does not'
4259
' permit bundle with no patch')
4265
directive = merge_directive.MergeDirective.from_objects(
4266
branch.repository, revision_id, time.time(),
4267
osutils.local_time_offset(), submit_branch,
4268
public_branch=public_branch, patch_type=patch_type,
4271
outfile.writelines(directive.to_lines())
4273
subject = '[MERGE] '
4274
if message is not None:
4277
revision = branch.repository.get_revision(revision_id)
4278
subject += revision.get_summary()
4279
basename = directive.get_disk_name(branch)
4280
mail_client.compose_merge_request(mail_to, subject,
4281
outfile.getvalue(), basename)
5465
4288
class cmd_bundle_revisions(cmd_send):
5466
__doc__ = """Create a merge-directive for submitting changes.
4290
"""Create a merge-directive for submiting changes.
5468
4292
A merge directive provides many things needed for requesting merges:
5545
4365
Tags are stored in the branch. Tags are copied from one branch to another
5546
4366
along when you branch, push, pull or merge.
5548
It is an error to give a tag name that already exists unless you pass
4368
It is an error to give a tag name that already exists unless you pass
5549
4369
--force, in which case the tag is moved to point to the new revision.
5551
4371
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5552
4372
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5554
If no tag name is specified it will be determined through the
5555
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5556
upstream releases by reading configure.ac. See ``bzr help hooks`` for
5560
4375
_see_also = ['commit', 'tags']
5561
takes_args = ['tag_name?']
4376
takes_args = ['tag_name']
5562
4377
takes_options = [
5563
4378
Option('delete',
5564
4379
help='Delete this tag rather than placing it.',
5566
custom_help('directory',
5567
help='Branch in which to place the tag.'),
4382
help='Branch in which to place the tag.',
5568
4386
Option('force',
5569
4387
help='Replace existing tags.',
5574
def run(self, tag_name=None,
4392
def run(self, tag_name,
5580
4398
branch, relpath = Branch.open_containing(directory)
5581
self.add_cleanup(branch.lock_write().unlock)
5583
if tag_name is None:
5584
raise errors.BzrCommandError("No tag specified to delete.")
5585
branch.tags.delete_tag(tag_name)
5586
note('Deleted tag %s.' % tag_name)
5589
if len(revision) != 1:
5590
raise errors.BzrCommandError(
5591
"Tags can only be placed on a single revision, "
5593
revision_id = revision[0].as_revision_id(branch)
4402
branch.tags.delete_tag(tag_name)
4403
self.outf.write('Deleted tag %s.\n' % tag_name)
5595
revision_id = branch.last_revision()
5596
if tag_name is None:
5597
tag_name = branch.automatic_tag_name(revision_id)
5598
if tag_name is None:
5599
raise errors.BzrCommandError(
5600
"Please specify a tag name.")
5601
if (not force) and branch.tags.has_tag(tag_name):
5602
raise errors.TagAlreadyExists(tag_name)
5603
branch.tags.set_tag(tag_name, revision_id)
5604
note('Created tag %s.' % tag_name)
4406
if len(revision) != 1:
4407
raise errors.BzrCommandError(
4408
"Tags can only be placed on a single revision, "
4410
revision_id = revision[0].as_revision_id(branch)
4412
revision_id = branch.last_revision()
4413
if (not force) and branch.tags.has_tag(tag_name):
4414
raise errors.TagAlreadyExists(tag_name)
4415
branch.tags.set_tag(tag_name, revision_id)
4416
self.outf.write('Created tag %s.\n' % tag_name)
5607
4421
class cmd_tags(Command):
5608
__doc__ = """List tags.
5610
4424
This command shows a table of tag names and the revisions they reference.
5613
4427
_see_also = ['tag']
5614
4428
takes_options = [
5615
custom_help('directory',
5616
help='Branch whose tags should be displayed.'),
5617
RegistryOption('sort',
4430
help='Branch whose tags should be displayed.',
4434
RegistryOption.from_kwargs('sort',
5618
4435
'Sort tags by different criteria.', title='Sorting',
5619
lazy_registry=('bzrlib.tag', 'tag_sort_methods')
4436
alpha='Sort tags lexicographically (default).',
4437
time='Sort tags chronologically.',
5625
4442
@display_command
5626
def run(self, directory='.', sort=None, show_ids=False, revision=None):
5627
from bzrlib.tag import tag_sort_methods
5628
4448
branch, relpath = Branch.open_containing(directory)
5630
4449
tags = branch.tags.get_tag_dict().items()
5634
self.add_cleanup(branch.lock_read().unlock)
5636
graph = branch.repository.get_graph()
5637
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5638
revid1, revid2 = rev1.rev_id, rev2.rev_id
5639
# only show revisions between revid1 and revid2 (inclusive)
5640
tags = [(tag, revid) for tag, revid in tags if
5641
graph.is_between(revid, revid1, revid2)]
5643
sort = tag_sort_methods.get()
4454
elif sort == 'time':
4456
for tag, revid in tags:
4458
revobj = branch.repository.get_revision(revid)
4459
except errors.NoSuchRevision:
4460
timestamp = sys.maxint # place them at the end
4462
timestamp = revobj.timestamp
4463
timestamps[revid] = timestamp
4464
tags.sort(key=lambda x: timestamps[x[1]])
5645
4465
if not show_ids:
5646
4466
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5647
for index, (tag, revid) in enumerate(tags):
5649
revno = branch.revision_id_to_dotted_revno(revid)
5650
if isinstance(revno, tuple):
5651
revno = '.'.join(map(str, revno))
5652
except (errors.NoSuchRevision, errors.GhostRevisionsHaveNoRevno):
5653
# Bad tag data/merges can lead to tagged revisions
5654
# which are not in this branch. Fail gracefully ...
5656
tags[index] = (tag, revno)
4467
revno_map = branch.get_revision_id_to_revno_map()
4468
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
4469
for tag, revid in tags ]
5658
4470
for tag, revspec in tags:
5659
4471
self.outf.write('%-20s %s\n' % (tag, revspec))
5662
4474
class cmd_reconfigure(Command):
5663
__doc__ = """Reconfigure the type of a bzr directory.
4475
"""Reconfigure the type of a bzr directory.
5665
4477
A target configuration must be specified.
5767
4547
directory of the current branch. For example, if you are currently in a
5768
4548
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5769
4549
/path/to/newbranch.
5771
Bound branches use the nickname of its master branch unless it is set
5772
locally, in which case switching will update the local nickname to be
5776
takes_args = ['to_location?']
5777
takes_options = ['directory',
5779
help='Switch even if local commits will be lost.'),
5781
Option('create-branch', short_name='b',
5782
help='Create the target branch from this one before'
5783
' switching to it.'),
4552
takes_args = ['to_location']
4553
takes_options = [Option('force',
4554
help='Switch even if local commits will be lost.')
5786
def run(self, to_location=None, force=False, create_branch=False,
5787
revision=None, directory=u'.'):
4557
def run(self, to_location, force=False):
5788
4558
from bzrlib import switch
5789
tree_location = directory
5790
revision = _get_one_revision('switch', revision)
5791
4560
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5792
if to_location is None:
5793
if revision is None:
5794
raise errors.BzrCommandError('You must supply either a'
5795
' revision or a location')
5796
to_location = tree_location
5798
branch = control_dir.open_branch()
5799
had_explicit_nick = branch.get_config().has_explicit_nickname()
4562
to_branch = Branch.open(to_location)
5800
4563
except errors.NotBranchError:
5802
had_explicit_nick = False
5805
raise errors.BzrCommandError('cannot create branch without'
5807
to_location = directory_service.directories.dereference(
5809
if '/' not in to_location and '\\' not in to_location:
5810
# This path is meant to be relative to the existing branch
5811
this_url = self._get_branch_location(control_dir)
5812
to_location = urlutils.join(this_url, '..', to_location)
5813
to_branch = branch.bzrdir.sprout(to_location,
5814
possible_transports=[branch.bzrdir.root_transport],
5815
source_branch=branch).open_branch()
5818
to_branch = Branch.open(to_location)
5819
except errors.NotBranchError:
5820
this_url = self._get_branch_location(control_dir)
5821
to_branch = Branch.open(
5822
urlutils.join(this_url, '..', to_location))
5823
if revision is not None:
5824
revision = revision.as_revision_id(to_branch)
5825
switch.switch(control_dir, to_branch, force, revision_id=revision)
5826
if had_explicit_nick:
5827
branch = control_dir.open_branch() #get the new branch!
5828
branch.nick = to_branch.nick
4564
to_branch = Branch.open(
4565
control_dir.open_branch().base + '../' + to_location)
4566
switch.switch(control_dir, to_branch, force)
5829
4567
note('Switched to branch: %s',
5830
4568
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5832
def _get_branch_location(self, control_dir):
5833
"""Return location of branch for this control dir."""
5835
this_branch = control_dir.open_branch()
5836
# This may be a heavy checkout, where we want the master branch
5837
master_location = this_branch.get_bound_location()
5838
if master_location is not None:
5839
return master_location
5840
# If not, use a local sibling
5841
return this_branch.base
5842
except errors.NotBranchError:
5843
format = control_dir.find_branch_format()
5844
if getattr(format, 'get_reference', None) is not None:
5845
return format.get_reference(control_dir)
5847
return control_dir.root_transport.base
5850
class cmd_view(Command):
5851
__doc__ = """Manage filtered views.
5853
Views provide a mask over the tree so that users can focus on
5854
a subset of a tree when doing their work. After creating a view,
5855
commands that support a list of files - status, diff, commit, etc -
5856
effectively have that list of files implicitly given each time.
5857
An explicit list of files can still be given but those files
5858
must be within the current view.
5860
In most cases, a view has a short life-span: it is created to make
5861
a selected change and is deleted once that change is committed.
5862
At other times, you may wish to create one or more named views
5863
and switch between them.
5865
To disable the current view without deleting it, you can switch to
5866
the pseudo view called ``off``. This can be useful when you need
5867
to see the whole tree for an operation or two (e.g. merge) but
5868
want to switch back to your view after that.
5871
To define the current view::
5873
bzr view file1 dir1 ...
5875
To list the current view::
5879
To delete the current view::
5883
To disable the current view without deleting it::
5885
bzr view --switch off
5887
To define a named view and switch to it::
5889
bzr view --name view-name file1 dir1 ...
5891
To list a named view::
5893
bzr view --name view-name
5895
To delete a named view::
5897
bzr view --name view-name --delete
5899
To switch to a named view::
5901
bzr view --switch view-name
5903
To list all views defined::
5907
To delete all views::
5909
bzr view --delete --all
5913
takes_args = ['file*']
5916
help='Apply list or delete action to all views.',
5919
help='Delete the view.',
5922
help='Name of the view to define, list or delete.',
5926
help='Name of the view to switch to.',
5931
def run(self, file_list,
5937
tree, file_list = WorkingTree.open_containing_paths(file_list,
5939
current_view, view_dict = tree.views.get_view_info()
5944
raise errors.BzrCommandError(
5945
"Both --delete and a file list specified")
5947
raise errors.BzrCommandError(
5948
"Both --delete and --switch specified")
5950
tree.views.set_view_info(None, {})
5951
self.outf.write("Deleted all views.\n")
5953
raise errors.BzrCommandError("No current view to delete")
5955
tree.views.delete_view(name)
5956
self.outf.write("Deleted '%s' view.\n" % name)
5959
raise errors.BzrCommandError(
5960
"Both --switch and a file list specified")
5962
raise errors.BzrCommandError(
5963
"Both --switch and --all specified")
5964
elif switch == 'off':
5965
if current_view is None:
5966
raise errors.BzrCommandError("No current view to disable")
5967
tree.views.set_view_info(None, view_dict)
5968
self.outf.write("Disabled '%s' view.\n" % (current_view))
5970
tree.views.set_view_info(switch, view_dict)
5971
view_str = views.view_display_str(tree.views.lookup_view())
5972
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5975
self.outf.write('Views defined:\n')
5976
for view in sorted(view_dict):
5977
if view == current_view:
5981
view_str = views.view_display_str(view_dict[view])
5982
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5984
self.outf.write('No views defined.\n')
5987
# No name given and no current view set
5990
raise errors.BzrCommandError(
5991
"Cannot change the 'off' pseudo view")
5992
tree.views.set_view(name, sorted(file_list))
5993
view_str = views.view_display_str(tree.views.lookup_view())
5994
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5998
# No name given and no current view set
5999
self.outf.write('No current view.\n')
6001
view_str = views.view_display_str(tree.views.lookup_view(name))
6002
self.outf.write("'%s' view is: %s\n" % (name, view_str))
6005
4571
class cmd_hooks(Command):
6006
__doc__ = """Show hooks."""
6011
for hook_key in sorted(hooks.known_hooks.keys()):
6012
some_hooks = hooks.known_hooks_key_to_object(hook_key)
6013
self.outf.write("%s:\n" % type(some_hooks).__name__)
6014
for hook_name, hook_point in sorted(some_hooks.items()):
6015
self.outf.write(" %s:\n" % (hook_name,))
6016
found_hooks = list(hook_point)
6018
for hook in found_hooks:
6019
self.outf.write(" %s\n" %
6020
(some_hooks.get_hook_name(hook),))
6022
self.outf.write(" <no hooks installed>\n")
6025
class cmd_remove_branch(Command):
6026
__doc__ = """Remove a branch.
6028
This will remove the branch from the specified location but
6029
will keep any working tree or repository in place.
6033
Remove the branch at repo/trunk::
6035
bzr remove-branch repo/trunk
6039
takes_args = ["location?"]
6041
aliases = ["rmbranch"]
6043
def run(self, location=None):
6044
if location is None:
6046
branch = Branch.open_containing(location)[0]
6047
branch.bzrdir.destroy_branch()
6050
class cmd_shelve(Command):
6051
__doc__ = """Temporarily set aside some changes from the current tree.
6053
Shelve allows you to temporarily put changes you've made "on the shelf",
6054
ie. out of the way, until a later time when you can bring them back from
6055
the shelf with the 'unshelve' command. The changes are stored alongside
6056
your working tree, and so they aren't propagated along with your branch nor
6057
will they survive its deletion.
6059
If shelve --list is specified, previously-shelved changes are listed.
6061
Shelve is intended to help separate several sets of changes that have
6062
been inappropriately mingled. If you just want to get rid of all changes
6063
and you don't need to restore them later, use revert. If you want to
6064
shelve all text changes at once, use shelve --all.
6066
If filenames are specified, only the changes to those files will be
6067
shelved. Other files will be left untouched.
6069
If a revision is specified, changes since that revision will be shelved.
6071
You can put multiple items on the shelf, and by default, 'unshelve' will
6072
restore the most recently shelved changes.
6074
For complicated changes, it is possible to edit the changes in a separate
6075
editor program to decide what the file remaining in the working copy
6076
should look like. To do this, add the configuration option
6078
change_editor = PROGRAM @new_path @old_path
6080
where @new_path is replaced with the path of the new version of the
6081
file and @old_path is replaced with the path of the old version of
6082
the file. The PROGRAM should save the new file with the desired
6083
contents of the file in the working tree.
6087
takes_args = ['file*']
6092
Option('all', help='Shelve all changes.'),
6094
RegistryOption('writer', 'Method to use for writing diffs.',
6095
bzrlib.option.diff_writer_registry,
6096
value_switches=True, enum_switch=False),
6098
Option('list', help='List shelved changes.'),
6100
help='Destroy removed changes instead of shelving them.'),
6102
_see_also = ['unshelve', 'configuration']
6104
def run(self, revision=None, all=False, file_list=None, message=None,
6105
writer=None, list=False, destroy=False, directory=None):
6107
return self.run_for_list(directory=directory)
6108
from bzrlib.shelf_ui import Shelver
6110
writer = bzrlib.option.diff_writer_registry.get()
6112
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
6113
file_list, message, destroy=destroy, directory=directory)
6118
except errors.UserAbort:
6121
def run_for_list(self, directory=None):
6122
if directory is None:
6124
tree = WorkingTree.open_containing(directory)[0]
6125
self.add_cleanup(tree.lock_read().unlock)
6126
manager = tree.get_shelf_manager()
6127
shelves = manager.active_shelves()
6128
if len(shelves) == 0:
6129
note('No shelved changes.')
6131
for shelf_id in reversed(shelves):
6132
message = manager.get_metadata(shelf_id).get('message')
6134
message = '<no message>'
6135
self.outf.write('%3d: %s\n' % (shelf_id, message))
6139
class cmd_unshelve(Command):
6140
__doc__ = """Restore shelved changes.
6142
By default, the most recently shelved changes are restored. However if you
6143
specify a shelf by id those changes will be restored instead. This works
6144
best when the changes don't depend on each other.
6147
takes_args = ['shelf_id?']
6150
RegistryOption.from_kwargs(
6151
'action', help="The action to perform.",
6152
enum_switch=False, value_switches=True,
6153
apply="Apply changes and remove from the shelf.",
6154
dry_run="Show changes, but do not apply or remove them.",
6155
preview="Instead of unshelving the changes, show the diff that "
6156
"would result from unshelving.",
6157
delete_only="Delete changes without applying them.",
6158
keep="Apply changes but don't delete them.",
6161
_see_also = ['shelve']
6163
def run(self, shelf_id=None, action='apply', directory=u'.'):
6164
from bzrlib.shelf_ui import Unshelver
6165
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
6169
unshelver.tree.unlock()
6172
class cmd_clean_tree(Command):
6173
__doc__ = """Remove unwanted files from working tree.
6175
By default, only unknown files, not ignored files, are deleted. Versioned
6176
files are never deleted.
6178
Another class is 'detritus', which includes files emitted by bzr during
6179
normal operations and selftests. (The value of these files decreases with
6182
If no options are specified, unknown files are deleted. Otherwise, option
6183
flags are respected, and may be combined.
6185
To check what clean-tree will do, use --dry-run.
6187
takes_options = ['directory',
6188
Option('ignored', help='Delete all ignored files.'),
6189
Option('detritus', help='Delete conflict files, merge and revert'
6190
' backups, and failed selftest dirs.'),
6192
help='Delete files unknown to bzr (default).'),
6193
Option('dry-run', help='Show files to delete instead of'
6195
Option('force', help='Do not prompt before deleting.')]
6196
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6197
force=False, directory=u'.'):
6198
from bzrlib.clean_tree import clean_tree
6199
if not (unknown or ignored or detritus):
6203
clean_tree(directory, unknown=unknown, ignored=ignored,
6204
detritus=detritus, dry_run=dry_run, no_prompt=force)
6207
class cmd_reference(Command):
6208
__doc__ = """list, view and set branch locations for nested trees.
6210
If no arguments are provided, lists the branch locations for nested trees.
6211
If one argument is provided, display the branch location for that tree.
6212
If two arguments are provided, set the branch location for that tree.
6217
takes_args = ['path?', 'location?']
6219
def run(self, path=None, location=None):
6221
if path is not None:
6223
tree, branch, relpath =(
6224
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
6225
if path is not None:
6228
tree = branch.basis_tree()
4572
"""Show a branch's currently registered hooks.
4576
takes_args = ['path?']
4578
def run(self, path=None):
6229
4579
if path is None:
6230
info = branch._get_all_reference_info().iteritems()
6231
self._display_reference_info(tree, branch, info)
4581
branch_hooks = Branch.open(path).hooks
4582
for hook_type in branch_hooks:
4583
hooks = branch_hooks[hook_type]
4584
self.outf.write("%s:\n" % (hook_type,))
4587
self.outf.write(" %s\n" %
4588
(branch_hooks.get_hook_name(hook),))
4590
self.outf.write(" <no hooks installed>\n")
4593
def _create_prefix(cur_transport):
4594
needed = [cur_transport]
4595
# Recurse upwards until we can create a directory successfully
4597
new_transport = cur_transport.clone('..')
4598
if new_transport.base == cur_transport.base:
4599
raise errors.BzrCommandError(
4600
"Failed to create path prefix for %s."
4601
% cur_transport.base)
4603
new_transport.mkdir('.')
4604
except errors.NoSuchFile:
4605
needed.append(new_transport)
4606
cur_transport = new_transport
6233
file_id = tree.path2id(path)
6235
raise errors.NotVersionedError(path)
6236
if location is None:
6237
info = [(file_id, branch.get_reference_info(file_id))]
6238
self._display_reference_info(tree, branch, info)
6240
branch.set_reference_info(file_id, path, location)
6242
def _display_reference_info(self, tree, branch, info):
6244
for file_id, (path, location) in info:
6246
path = tree.id2path(file_id)
6247
except errors.NoSuchId:
6249
ref_list.append((path, location))
6250
for path, location in sorted(ref_list):
6251
self.outf.write('%s %s\n' % (path, location))
6254
class cmd_export_pot(Command):
6255
__doc__ = """Export command helps and error messages in po format."""
6260
from bzrlib.export_pot import export_pot
6261
export_pot(self.outf)
6264
def _register_lazy_builtins():
6265
# register lazy builtins from other modules; called at startup and should
6266
# be only called once.
6267
for (name, aliases, module_name) in [
6268
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6269
('cmd_config', [], 'bzrlib.config'),
6270
('cmd_dpush', [], 'bzrlib.foreign'),
6271
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6272
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6273
('cmd_conflicts', [], 'bzrlib.conflicts'),
6274
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6275
('cmd_verify_signatures', [],
6276
'bzrlib.commit_signature_commands'),
6277
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6279
builtin_command_registry.register_lazy(name, aliases, module_name)
4609
# Now we only need to create child directories
4611
cur_transport = needed.pop()
4612
cur_transport.ensure_base()
4615
# these get imported and then picked up by the scan for cmd_*
4616
# TODO: Some more consistent way to split command definitions across files;
4617
# we do need to load at least some information about them to know of
4618
# aliases. ideally we would avoid loading the implementation until the
4619
# details were needed.
4620
from bzrlib.cmd_version_info import cmd_version_info
4621
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
4622
from bzrlib.bundle.commands import (
4625
from bzrlib.sign_my_commits import cmd_sign_my_commits
4626
from bzrlib.weave_commands import cmd_versionedfile_list, \
4627
cmd_weave_plan_merge, cmd_weave_merge_text