52
46
revision as _mod_revision,
61
from breezy.branch import Branch
62
from breezy.conflicts import ConflictList
63
from breezy.transport import memory
64
from breezy.smtp_connection import SMTPConnection
65
from breezy.workingtree import WorkingTree
66
from breezy.i18n import gettext, ngettext
55
from bzrlib.branch import Branch
56
from bzrlib.conflicts import ConflictList
57
from bzrlib.transport import memory
58
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
59
from bzrlib.smtp_connection import SMTPConnection
60
from bzrlib.workingtree import WorkingTree
69
from .commands import (
71
builtin_command_registry,
63
from bzrlib.commands import Command, display_command
64
from bzrlib.option import (
79
69
_parse_revision_str,
81
from .revisionspec import (
91
from .trace import mutter, note, warning, is_quiet, get_verbosity_level
94
def _get_branch_location(control_dir, possible_transports=None):
95
"""Return location of branch for this control dir."""
97
target = control_dir.get_branch_reference()
98
except errors.NotBranchError:
99
return control_dir.root_transport.base
100
if target is not None:
102
this_branch = control_dir.open_branch(
103
possible_transports=possible_transports)
104
# This may be a heavy checkout, where we want the master branch
105
master_location = this_branch.get_bound_location()
106
if master_location is not None:
107
return master_location
108
# If not, use a local sibling
109
return this_branch.base
112
def _is_colocated(control_dir, possible_transports=None):
113
"""Check if the branch in control_dir is colocated.
115
:param control_dir: Control directory
116
:return: Tuple with boolean indicating whether the branch is colocated
117
and the full URL to the actual branch
119
# This path is meant to be relative to the existing branch
120
this_url = _get_branch_location(control_dir,
121
possible_transports=possible_transports)
122
# Perhaps the target control dir supports colocated branches?
124
root = controldir.ControlDir.open(this_url,
125
possible_transports=possible_transports)
126
except errors.NotBranchError:
127
return (False, this_url)
130
wt = control_dir.open_workingtree()
131
except (errors.NoWorkingTree, errors.NotLocalUrl):
132
return (False, this_url)
135
root._format.colocated_branches and
136
control_dir.control_url == root.control_url,
140
def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
141
"""Lookup the location for a new sibling branch.
143
:param control_dir: Control directory to find sibling branches from
144
:param location: Name of the new branch
145
:return: Full location to the new branch
147
location = directory_service.directories.dereference(location)
148
if '/' not in location and '\\' not in location:
149
(colocated, this_url) = _is_colocated(control_dir, possible_transports)
152
return urlutils.join_segment_parameters(this_url,
153
{"branch": urlutils.escape(location)})
155
return urlutils.join(this_url, '..', urlutils.escape(location))
159
def open_sibling_branch(control_dir, location, possible_transports=None):
160
"""Open a branch, possibly a sibling of another.
162
:param control_dir: Control directory relative to which to lookup the
164
:param location: Location to look up
165
:return: branch to open
168
# Perhaps it's a colocated branch?
169
return control_dir.open_branch(location,
170
possible_transports=possible_transports)
171
except (errors.NotBranchError, errors.NoColocatedBranchSupport):
172
this_url = _get_branch_location(control_dir)
175
this_url, '..', urlutils.escape(location)))
178
def open_nearby_branch(near=None, location=None, possible_transports=None):
179
"""Open a nearby branch.
181
:param near: Optional location of container from which to open branch
182
:param location: Location of the branch
183
:return: Branch instance
189
return Branch.open(location,
190
possible_transports=possible_transports)
191
except errors.NotBranchError:
193
cdir = controldir.ControlDir.open(near,
194
possible_transports=possible_transports)
195
return open_sibling_branch(cdir, location,
196
possible_transports=possible_transports)
199
def iter_sibling_branches(control_dir, possible_transports=None):
200
"""Iterate over the siblings of a branch.
202
:param control_dir: Control directory for which to look up the siblings
203
:return: Iterator over tuples with branch name and branch object
207
reference = control_dir.get_branch_reference()
208
except errors.NotBranchError:
209
# There is no active branch, just return the colocated branches.
210
for name, branch in viewitems(control_dir.get_branches()):
213
if reference is not None:
214
ref_branch = Branch.open(reference,
215
possible_transports=possible_transports)
218
if ref_branch is None or ref_branch.name:
219
if ref_branch is not None:
220
control_dir = ref_branch.controldir
221
for name, branch in viewitems(control_dir.get_branches()):
224
repo = ref_branch.controldir.find_repository()
225
for branch in repo.find_branches(using=True):
226
name = urlutils.relative_url(repo.user_url,
227
branch.user_url).rstrip("/")
71
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
74
def tree_files(file_list, default_branch=u'.', canonicalize=True,
77
return internal_tree_files(file_list, default_branch, canonicalize,
79
except errors.FileInWrongBranch, e:
80
raise errors.BzrCommandError("%s is not in the same branch as %s" %
81
(e.path, file_list[0]))
231
84
def tree_files_for_add(file_list):
149
# XXX: Bad function name; should possibly also be a class method of
150
# WorkingTree rather than a function.
151
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
153
"""Convert command-line paths to a WorkingTree and relative paths.
155
This is typically used for command-line processors that take one or
156
more filenames, and infer the workingtree that contains them.
158
The filenames given are not required to exist.
160
:param file_list: Filenames to convert.
162
:param default_branch: Fallback tree path to use if file_list is empty or
165
:param apply_view: if True and a view is set, apply it or check that
166
specified files are within it
168
:return: workingtree, [relative_paths]
170
if file_list is None or len(file_list) == 0:
171
tree = WorkingTree.open_containing(default_branch)[0]
172
if tree.supports_views() and apply_view:
173
view_files = tree.views.lookup_view()
175
file_list = view_files
176
view_str = views.view_display_str(view_files)
177
note("Ignoring files outside view. View is %s" % view_str)
178
return tree, file_list
179
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
180
return tree, safe_relpath_files(tree, file_list, canonicalize,
181
apply_view=apply_view)
184
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
185
"""Convert file_list into a list of relpaths in tree.
187
:param tree: A tree to operate on.
188
:param file_list: A list of user provided paths or None.
189
:param apply_view: if True and a view is set, apply it or check that
190
specified files are within it
191
:return: A list of relative paths.
192
:raises errors.PathNotChild: When a provided path is in a different tree
195
if file_list is None:
197
if tree.supports_views() and apply_view:
198
view_files = tree.views.lookup_view()
202
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
203
# doesn't - fix that up here before we enter the loop.
205
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
208
for filename in file_list:
210
relpath = fixer(osutils.dereference_path(filename))
211
if view_files and not osutils.is_inside_any(view_files, relpath):
212
raise errors.FileOutsideView(filename, view_files)
213
new_list.append(relpath)
214
except errors.PathNotChild:
215
raise errors.FileInWrongBranch(tree.branch, filename)
296
219
def _get_view_info_for_change_reporter(tree):
297
220
"""Get the view information from a tree for change reporting."""
433
338
takes_args = ['revision_id?']
434
takes_options = ['directory', 'revision']
339
takes_options = ['revision']
435
340
# cat-revision is more for frontends so should be exact
436
341
encoding = 'strict'
438
343
def print_revision(self, revisions, revid):
439
344
stream = revisions.get_record_stream([(revid,)], 'unordered', True)
440
record = next(stream)
345
record = stream.next()
441
346
if record.storage_kind == 'absent':
442
347
raise errors.NoSuchRevision(revisions, revid)
443
348
revtext = record.get_bytes_as('fulltext')
444
349
self.outf.write(revtext.decode('utf-8'))
447
def run(self, revision_id=None, revision=None, directory=u'.'):
352
def run(self, revision_id=None, revision=None):
448
353
if revision_id is not None and revision is not None:
449
raise errors.BzrCommandError(gettext('You can only supply one of'
450
' revision_id or --revision'))
354
raise errors.BzrCommandError('You can only supply one of'
355
' revision_id or --revision')
451
356
if revision_id is None and revision is None:
452
raise errors.BzrCommandError(gettext('You must supply either'
453
' --revision or a revision_id'))
455
b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
357
raise errors.BzrCommandError('You must supply either'
358
' --revision or a revision_id')
359
b = WorkingTree.open_containing(u'.')[0].branch
457
361
revisions = b.repository.revisions
458
362
if revisions is None:
459
raise errors.BzrCommandError(gettext('Repository %r does not support '
460
'access to raw revision texts'))
363
raise errors.BzrCommandError('Repository %r does not support '
364
'access to raw revision texts')
462
with b.repository.lock_read():
366
b.repository.lock_read()
463
368
# TODO: jam 20060112 should cat-revision always output utf-8?
464
369
if revision_id is not None:
465
revision_id = cache_utf8.encode(revision_id)
370
revision_id = osutils.safe_revision_id(revision_id, warn=False)
467
372
self.print_revision(revisions, revision_id)
468
373
except errors.NoSuchRevision:
469
msg = gettext("The repository {0} contains no revision {1}.").format(
374
msg = "The repository %s contains no revision %s." % (
470
375
b.repository.base, revision_id)
471
376
raise errors.BzrCommandError(msg)
472
377
elif revision is not None:
473
378
for rev in revision:
475
380
raise errors.BzrCommandError(
476
gettext('You cannot specify a NULL revision.'))
381
'You cannot specify a NULL revision.')
477
382
rev_id = rev.as_revision_id(b)
478
383
self.print_revision(revisions, rev_id)
385
b.repository.unlock()
388
class cmd_dump_btree(Command):
389
"""Dump the contents of a btree index file to stdout.
391
PATH is a btree index file, it can be any URL. This includes things like
392
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
394
By default, the tuples stored in the index file will be displayed. With
395
--raw, we will uncompress the pages, but otherwise display the raw bytes
399
# TODO: Do we want to dump the internal nodes as well?
400
# TODO: It would be nice to be able to dump the un-parsed information,
401
# rather than only going through iter_all_entries. However, this is
402
# good enough for a start
404
encoding_type = 'exact'
405
takes_args = ['path']
406
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
407
' rather than the parsed tuples.'),
410
def run(self, path, raw=False):
411
dirname, basename = osutils.split(path)
412
t = transport.get_transport(dirname)
414
self._dump_raw_bytes(t, basename)
416
self._dump_entries(t, basename)
418
def _get_index_and_bytes(self, trans, basename):
419
"""Create a BTreeGraphIndex and raw bytes."""
420
bt = btree_index.BTreeGraphIndex(trans, basename, None)
421
bytes = trans.get_bytes(basename)
422
bt._file = cStringIO.StringIO(bytes)
423
bt._size = len(bytes)
426
def _dump_raw_bytes(self, trans, basename):
429
# We need to parse at least the root node.
430
# This is because the first page of every row starts with an
431
# uncompressed header.
432
bt, bytes = self._get_index_and_bytes(trans, basename)
433
for page_idx, page_start in enumerate(xrange(0, len(bytes),
434
btree_index._PAGE_SIZE)):
435
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
436
page_bytes = bytes[page_start:page_end]
438
self.outf.write('Root node:\n')
439
header_end, data = bt._parse_header_from_bytes(page_bytes)
440
self.outf.write(page_bytes[:header_end])
442
self.outf.write('\nPage %d\n' % (page_idx,))
443
decomp_bytes = zlib.decompress(page_bytes)
444
self.outf.write(decomp_bytes)
445
self.outf.write('\n')
447
def _dump_entries(self, trans, basename):
449
st = trans.stat(basename)
450
except errors.TransportNotPossible:
451
# We can't stat, so we'll fake it because we have to do the 'get()'
453
bt, _ = self._get_index_and_bytes(trans, basename)
455
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
456
for node in bt.iter_all_entries():
457
# Node is made up of:
458
# (index, key, value, [references])
459
refs_as_tuples = static_tuple.as_tuples(node[3])
460
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
461
self.outf.write('%s\n' % (as_tuple,))
481
464
class cmd_remove_tree(Command):
482
__doc__ = """Remove the working tree from a given branch/checkout.
465
"""Remove the working tree from a given branch/checkout.
484
467
Since a lightweight checkout is little more than a working tree
485
468
this will refuse to run against one.
487
To re-create the working tree, use "brz checkout".
470
To re-create the working tree, use "bzr checkout".
489
472
_see_also = ['checkout', 'working-trees']
490
473
takes_args = ['location*']
491
474
takes_options = [
493
476
help='Remove the working tree even if it has '
494
'uncommitted or shelved changes.'),
477
'uncommitted changes.'),
497
480
def run(self, location_list, force=False):
499
482
location_list=['.']
501
484
for location in location_list:
502
d = controldir.ControlDir.open(location)
485
d = bzrdir.BzrDir.open(location)
505
488
working = d.open_workingtree()
506
489
except errors.NoWorkingTree:
507
raise errors.BzrCommandError(gettext("No working tree to remove"))
490
raise errors.BzrCommandError("No working tree to remove")
508
491
except errors.NotLocalUrl:
509
raise errors.BzrCommandError(gettext("You cannot remove the working tree"
510
" of a remote path"))
492
raise errors.BzrCommandError("You cannot remove the working tree"
512
495
if (working.has_changes()):
513
496
raise errors.UncommittedChanges(working)
514
if working.get_shelf_manager().last_shelf() is not None:
515
raise errors.ShelvedChanges(working)
517
if working.user_url != working.branch.user_url:
518
raise errors.BzrCommandError(gettext("You cannot remove the working tree"
519
" from a lightweight checkout"))
498
working_path = working.bzrdir.root_transport.base
499
branch_path = working.branch.bzrdir.root_transport.base
500
if working_path != branch_path:
501
raise errors.BzrCommandError("You cannot remove the working tree"
502
" from a lightweight checkout")
521
504
d.destroy_workingtree()
524
class cmd_repair_workingtree(Command):
525
__doc__ = """Reset the working tree state file.
527
This is not meant to be used normally, but more as a way to recover from
528
filesystem corruption, etc. This rebuilds the working inventory back to a
529
'known good' state. Any new modifications (adding a file, renaming, etc)
530
will be lost, though modified files will still be detected as such.
532
Most users will want something more like "brz revert" or "brz update"
533
unless the state file has become corrupted.
535
By default this attempts to recover the current state by looking at the
536
headers of the state file. If the state file is too corrupted to even do
537
that, you can supply --revision to force the state of the tree.
540
takes_options = ['revision', 'directory',
542
help='Reset the tree even if it doesn\'t appear to be'
547
def run(self, revision=None, directory='.', force=False):
548
tree, _ = WorkingTree.open_containing(directory)
549
self.add_cleanup(tree.lock_tree_write().unlock)
553
except errors.BzrError:
554
pass # There seems to be a real error here, so we'll reset
557
raise errors.BzrCommandError(gettext(
558
'The tree does not appear to be corrupt. You probably'
559
' want "brz revert" instead. Use "--force" if you are'
560
' sure you want to reset the working tree.'))
564
revision_ids = [r.as_revision_id(tree.branch) for r in revision]
566
tree.reset_state(revision_ids)
567
except errors.BzrError as e:
568
if revision_ids is None:
569
extra = (gettext(', the header appears corrupt, try passing -r -1'
570
' to set the state to the last commit'))
573
raise errors.BzrCommandError(gettext('failed to reset the tree state{0}').format(extra))
576
507
class cmd_revno(Command):
577
__doc__ = """Show current revision number.
508
"""Show current revision number.
579
510
This is equal to the number of revisions on this branch.
582
513
_see_also = ['info']
583
514
takes_args = ['location?']
584
515
takes_options = [
585
Option('tree', help='Show revno of working tree.'),
516
Option('tree', help='Show revno of working tree'),
590
def run(self, tree=False, location=u'.', revision=None):
591
if revision is not None and tree:
592
raise errors.BzrCommandError(gettext("--tree and --revision can "
593
"not be used together"))
520
def run(self, tree=False, location=u'.'):
597
523
wt = WorkingTree.open_containing(location)[0]
598
self.add_cleanup(wt.lock_read().unlock)
599
525
except (errors.NoWorkingTree, errors.NotLocalUrl):
600
526
raise errors.NoWorkingTree(location)
527
self.add_cleanup(wt.unlock)
602
528
revid = wt.last_revision()
530
revno_t = wt.branch.revision_id_to_dotted_revno(revid)
531
except errors.NoSuchRevision:
533
revno = ".".join(str(n) for n in revno_t)
604
535
b = Branch.open_containing(location)[0]
605
self.add_cleanup(b.lock_read().unlock)
607
if len(revision) != 1:
608
raise errors.BzrCommandError(gettext(
609
"Revision numbers only make sense for single "
610
"revisions, not ranges"))
611
revid = revision[0].as_revision_id(b)
613
revid = b.last_revision()
615
revno_t = b.revision_id_to_dotted_revno(revid)
616
except errors.NoSuchRevision:
618
revno = ".".join(str(n) for n in revno_t)
537
self.add_cleanup(b.unlock)
619
539
self.cleanup_now()
620
self.outf.write(revno + '\n')
540
self.outf.write(str(revno) + '\n')
623
543
class cmd_revision_info(Command):
624
__doc__ = """Show revision number and revision id for a given revision identifier.
544
"""Show revision number and revision id for a given revision identifier.
627
547
takes_args = ['revision_info*']
628
548
takes_options = [
630
custom_help('directory',
631
551
help='Branch to examine, '
632
'rather than the one containing the working directory.'),
633
Option('tree', help='Show revno of working tree.'),
552
'rather than the one containing the working directory.',
556
Option('tree', help='Show revno of working tree'),
751
668
base_tree = base_branch.basis_tree()
753
action = breezy.add.AddFromBaseAction(base_tree, base_path,
670
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
754
671
to_file=self.outf, should_print=(not is_quiet()))
756
action = breezy.add.AddWithSkipLargeAction(to_file=self.outf,
673
action = bzrlib.add.AddAction(to_file=self.outf,
757
674
should_print=(not is_quiet()))
760
self.add_cleanup(base_tree.lock_read().unlock)
677
base_tree.lock_read()
678
self.add_cleanup(base_tree.unlock)
761
679
tree, file_list = tree_files_for_add(file_list)
762
680
added, ignored = tree.smart_add(file_list, not
763
681
no_recurse, action=action, save=not dry_run)
764
682
self.cleanup_now()
765
683
if len(ignored) > 0:
767
for glob in sorted(ignored):
685
for glob in sorted(ignored.keys()):
768
686
for path in ignored[glob]:
770
gettext("ignored {0} matching \"{1}\"\n").format(
687
self.outf.write("ignored %s matching \"%s\"\n"
774
691
class cmd_mkdir(Command):
775
__doc__ = """Create a new versioned directory.
692
"""Create a new versioned directory.
777
694
This is equivalent to creating the directory and then adding it.
780
697
takes_args = ['dir+']
784
help='No error if existing, make parent directories as needed.',
788
698
encoding_type = 'replace'
791
def add_file_with_parents(cls, wt, relpath):
792
if wt.is_versioned(relpath):
794
cls.add_file_with_parents(wt, osutils.dirname(relpath))
798
def add_file_single(cls, wt, relpath):
801
def run(self, dir_list, parents=False):
803
add_file = self.add_file_with_parents
805
add_file = self.add_file_single
807
wt, relpath = WorkingTree.open_containing(dir)
812
if e.errno != errno.EEXIST:
816
add_file(wt, relpath)
818
self.outf.write(gettext('added %s\n') % dir)
700
def run(self, dir_list):
703
wt, dd = WorkingTree.open_containing(d)
705
self.outf.write('added %s\n' % d)
821
708
class cmd_relpath(Command):
822
__doc__ = """Show path of a file relative to root"""
709
"""Show path of a file relative to root"""
824
711
takes_args = ['filename']
852
739
help='List entries of a particular kind: file, directory, symlink.',
855
742
takes_args = ['file*']
858
745
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
859
746
if kind and kind not in ['file', 'directory', 'symlink']:
860
raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
747
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
862
749
revision = _get_one_revision('inventory', revision)
863
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
864
self.add_cleanup(work_tree.lock_read().unlock)
750
work_tree, file_list = tree_files(file_list)
751
work_tree.lock_read()
752
self.add_cleanup(work_tree.unlock)
865
753
if revision is not None:
866
754
tree = revision.as_tree(work_tree.branch)
868
756
extra_trees = [work_tree]
869
self.add_cleanup(tree.lock_read().unlock)
758
self.add_cleanup(tree.unlock)
874
self.add_cleanup(tree.lock_read().unlock)
875
763
if file_list is not None:
876
paths = tree.find_related_paths_across_trees(
877
file_list, extra_trees, require_versioned=True)
764
file_ids = tree.paths2ids(file_list, trees=extra_trees,
765
require_versioned=True)
878
766
# find_ids_across_trees may include some paths that don't
879
767
# exist in 'tree'.
880
entries = tree.iter_entries_by_dir(specific_files=paths)
768
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
769
for file_id in file_ids if file_id in tree)
882
entries = tree.iter_entries_by_dir()
771
entries = tree.inventory.entries()
884
for path, entry in sorted(entries):
774
for path, entry in entries:
885
775
if kind and kind != entry.kind:
890
778
self.outf.write('%-50s %s\n' % (path, entry.file_id))
893
781
self.outf.write('\n')
896
class cmd_cp(Command):
897
__doc__ = """Copy a file.
900
brz cp OLDNAME NEWNAME
902
brz cp SOURCE... DESTINATION
904
If the last argument is a versioned directory, all the other names
905
are copied into it. Otherwise, there must be exactly two arguments
906
and the file is copied to a new name.
908
Files cannot be copied between branches. Only files can be copied
912
takes_args = ['names*']
915
encoding_type = 'replace'
917
def run(self, names_list):
919
if names_list is None:
921
if len(names_list) < 2:
922
raise errors.BzrCommandError(gettext("missing file argument"))
923
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
924
for file_name in rel_names[0:-1]:
926
raise errors.BzrCommandError(gettext("can not copy root of branch"))
927
self.add_cleanup(tree.lock_tree_write().unlock)
928
into_existing = osutils.isdir(names_list[-1])
929
if not into_existing:
931
(src, dst) = rel_names
933
raise errors.BzrCommandError(gettext('to copy multiple files the'
934
' destination must be a versioned'
938
pairs = [(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
939
for n in rel_names[:-1]]
941
for src, dst in pairs:
943
src_kind = tree.stored_kind(src)
944
except errors.NoSuchFile:
945
raise errors.BzrCommandError(
946
gettext('Could not copy %s => %s: %s is not versioned.')
949
raise errors.BzrCommandError(
950
gettext('Could not copy %s => %s . %s is not versioned\.'
952
if src_kind == 'directory':
953
raise errors.BzrCommandError(
954
gettext('Could not copy %s => %s . %s is a directory.'
956
dst_parent = osutils.split(dst)[0]
959
dst_parent_kind = tree.stored_kind(dst_parent)
960
except errors.NoSuchFile:
961
raise errors.BzrCommandError(
962
gettext('Could not copy %s => %s: %s is not versioned.')
963
% (src, dst, dst_parent))
964
if dst_parent_kind != 'directory':
965
raise errors.BzrCommandError(
966
gettext('Could not copy to %s: %s is not a directory.')
967
% (dst_parent, dst_parent))
969
tree.copy_one(src, dst)
972
784
class cmd_mv(Command):
973
__doc__ = """Move or rename a file.
785
"""Move or rename a file.
976
brz mv OLDNAME NEWNAME
788
bzr mv OLDNAME NEWNAME
978
brz mv SOURCE... DESTINATION
790
bzr mv SOURCE... DESTINATION
980
792
If the last argument is a versioned directory, all the other names
981
793
are moved into it. Otherwise, there must be exactly two arguments
1004
816
return self.run_auto(names_list, after, dry_run)
1006
raise errors.BzrCommandError(gettext('--dry-run requires --auto.'))
818
raise errors.BzrCommandError('--dry-run requires --auto.')
1007
819
if names_list is None:
1009
821
if len(names_list) < 2:
1010
raise errors.BzrCommandError(gettext("missing file argument"))
1011
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
1012
for file_name in rel_names[0:-1]:
1014
raise errors.BzrCommandError(gettext("can not move root of branch"))
1015
self.add_cleanup(tree.lock_tree_write().unlock)
822
raise errors.BzrCommandError("missing file argument")
823
tree, rel_names = tree_files(names_list, canonicalize=False)
824
tree.lock_tree_write()
825
self.add_cleanup(tree.unlock)
1016
826
self._run(tree, names_list, rel_names, after)
1018
828
def run_auto(self, names_list, after, dry_run):
1019
829
if names_list is not None and len(names_list) > 1:
1020
raise errors.BzrCommandError(gettext('Only one path may be specified to'
830
raise errors.BzrCommandError('Only one path may be specified to'
1023
raise errors.BzrCommandError(gettext('--after cannot be specified with'
1025
work_tree, file_list = WorkingTree.open_containing_paths(
1026
names_list, default_directory='.')
1027
self.add_cleanup(work_tree.lock_tree_write().unlock)
1028
rename_map.RenameMap.guess_renames(
1029
work_tree.basis_tree(), work_tree, dry_run)
833
raise errors.BzrCommandError('--after cannot be specified with'
835
work_tree, file_list = tree_files(names_list, default_branch='.')
836
work_tree.lock_tree_write()
837
self.add_cleanup(work_tree.unlock)
838
rename_map.RenameMap.guess_renames(work_tree, dry_run)
1031
840
def _run(self, tree, names_list, rel_names, after):
1032
841
into_existing = osutils.isdir(names_list[-1])
1124
934
match the remote one, use pull --overwrite. This will work even if the two
1125
935
branches have diverged.
1127
If there is no default location set, the first pull will set it (use
1128
--no-remember to avoid setting it). After that, you can omit the
1129
location to use the default. To change the default, use --remember. The
1130
value will only be saved if the remote location can be accessed.
1132
The --verbose option will display the revisions pulled using the log_format
1133
configuration option. You can use a different format by overriding it with
1134
-Olog_format=<other_format>.
937
If there is no default location set, the first pull will set it. After
938
that, you can omit the location to use the default. To change the
939
default, use --remember. The value will only be saved if the remote
940
location can be accessed.
1136
942
Note: The location can be specified either in the form of a branch,
1137
943
or in the form of a path to a file containing a merge directive generated
1141
947
_see_also = ['push', 'update', 'status-flags', 'send']
1142
948
takes_options = ['remember', 'overwrite', 'revision',
1143
949
custom_help('verbose',
1144
950
help='Show logs of pulled revisions.'),
1145
custom_help('directory',
1146
952
help='Branch to pull into, '
1147
'rather than the one containing the working directory.'),
953
'rather than the one containing the working directory.',
1149
958
help="Perform a local pull in a bound "
1150
959
"branch. Local pulls are not applied to "
1151
960
"the master branch."
1154
help="Show base revision text in conflicts."),
1155
Option('overwrite-tags',
1156
help="Overwrite tags only."),
1158
963
takes_args = ['location?']
1159
964
encoding_type = 'replace'
1161
def run(self, location=None, remember=None, overwrite=False,
966
def run(self, location=None, remember=False, overwrite=False,
1162
967
revision=None, verbose=False,
1163
directory=None, local=False,
1164
show_base=False, overwrite_tags=False):
1167
overwrite = ["history", "tags"]
1168
elif overwrite_tags:
1169
overwrite = ["tags"]
968
directory=None, local=False):
1172
969
# FIXME: too much stuff is in the command class
1173
970
revision_id = None
1174
971
mergeable = None
1267
1057
considered diverged if the destination branch's most recent commit is one
1268
1058
that has not been merged (directly or indirectly) by the source branch.
1270
If branches have diverged, you can use 'brz push --overwrite' to replace
1060
If branches have diverged, you can use 'bzr push --overwrite' to replace
1271
1061
the other branch completely, discarding its unmerged changes.
1273
1063
If you want to ensure you have the different changes in the other branch,
1274
do a merge (see brz help merge) from the other branch, and commit that.
1064
do a merge (see bzr help merge) from the other branch, and commit that.
1275
1065
After that you will be able to do a push without '--overwrite'.
1277
If there is no default push location set, the first push will set it (use
1278
--no-remember to avoid setting it). After that, you can omit the
1279
location to use the default. To change the default, use --remember. The
1280
value will only be saved if the remote location can be accessed.
1282
The --verbose option will display the revisions pushed using the log_format
1283
configuration option. You can use a different format by overriding it with
1284
-Olog_format=<other_format>.
1067
If there is no default push location set, the first push will set it.
1068
After that, you can omit the location to use the default. To change the
1069
default, use --remember. The value will only be saved if the remote
1070
location can be accessed.
1287
1073
_see_also = ['pull', 'update', 'working-trees']
1304
1093
help='Create a stacked branch that refers to another branch '
1305
1094
'for the commit history. Only the work not present in the '
1306
1095
'referenced branch is included in the branch created.',
1308
1097
Option('strict',
1309
1098
help='Refuse to push if there are uncommitted changes in'
1310
1099
' the working tree, --no-strict disables the check.'),
1312
help="Don't populate the working tree, even for protocols"
1313
" that support it."),
1314
Option('overwrite-tags',
1315
help="Overwrite tags only."),
1316
Option('lossy', help="Allow lossy push, i.e. dropping metadata "
1317
"that can't be represented in the target.")
1319
1101
takes_args = ['location?']
1320
1102
encoding_type = 'replace'
1322
def run(self, location=None, remember=None, overwrite=False,
1104
def run(self, location=None, remember=False, overwrite=False,
1323
1105
create_prefix=False, verbose=False, revision=None,
1324
1106
use_existing_dir=False, directory=None, stacked_on=None,
1325
stacked=False, strict=None, no_tree=False,
1326
overwrite_tags=False, lossy=False):
1327
from .push import _show_push_branch
1330
overwrite = ["history", "tags"]
1331
elif overwrite_tags:
1332
overwrite = ["tags"]
1107
stacked=False, strict=None):
1108
from bzrlib.push import _show_push_branch
1336
1110
if directory is None:
1337
1111
directory = '.'
1338
1112
# Get the source branch
1339
1113
(tree, br_from,
1340
_unused) = controldir.ControlDir.open_containing_tree_or_branch(directory)
1114
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1116
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1117
if strict is None: strict = True # default value
1341
1118
# Get the tip's revision_id
1342
1119
revision = _get_one_revision('push', revision)
1343
1120
if revision is not None:
1344
1121
revision_id = revision.in_history(br_from).rev_id
1346
1123
revision_id = None
1347
if tree is not None and revision_id is None:
1348
tree.check_changed_or_out_of_date(
1349
strict, 'push_strict',
1350
more_error='Use --no-strict to force the push.',
1351
more_warning='Uncommitted changes will not be pushed.')
1124
if strict and tree is not None and revision_id is None:
1125
if (tree.has_changes()):
1126
raise errors.UncommittedChanges(
1127
tree, more='Use --no-strict to force the push.')
1128
if tree.last_revision() != tree.branch.last_revision():
1129
# The tree has lost sync with its branch, there is little
1130
# chance that the user is aware of it but he can still force
1131
# the push with --no-strict
1132
raise errors.OutOfDateTree(
1133
tree, more='Use --no-strict to force the push.')
1352
1135
# Get the stacked_on branch, if any
1353
1136
if stacked_on is not None:
1354
1137
stacked_on = urlutils.normalize_url(stacked_on)
1364
1147
# error by the feedback given to them. RBC 20080227.
1365
1148
stacked_on = parent_url
1366
1149
if not stacked_on:
1367
raise errors.BzrCommandError(gettext(
1368
"Could not determine branch to refer to."))
1150
raise errors.BzrCommandError(
1151
"Could not determine branch to refer to.")
1370
1153
# Get the destination location
1371
1154
if location is None:
1372
1155
stored_loc = br_from.get_push_location()
1373
1156
if stored_loc is None:
1374
parent_loc = br_from.get_parent()
1376
raise errors.BzrCommandError(gettext(
1377
"No push location known or specified. To push to the "
1378
"parent branch (at %s), use 'brz push :parent'." %
1379
urlutils.unescape_for_display(parent_loc,
1380
self.outf.encoding)))
1382
raise errors.BzrCommandError(gettext(
1383
"No push location known or specified."))
1157
raise errors.BzrCommandError(
1158
"No push location known or specified.")
1385
1160
display_url = urlutils.unescape_for_display(stored_loc,
1386
1161
self.outf.encoding)
1387
note(gettext("Using saved push location: %s") % display_url)
1162
self.outf.write("Using saved push location: %s\n" % display_url)
1388
1163
location = stored_loc
1390
1165
_show_push_branch(br_from, revision_id, location, self.outf,
1391
1166
verbose=verbose, overwrite=overwrite, remember=remember,
1392
1167
stacked_on=stacked_on, create_prefix=create_prefix,
1393
use_existing_dir=use_existing_dir, no_tree=no_tree,
1168
use_existing_dir=use_existing_dir)
1397
1171
class cmd_branch(Command):
1398
__doc__ = """Create a new branch that is a copy of an existing branch.
1172
"""Create a new branch that is a copy of an existing branch.
1400
1174
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1401
1175
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
1434
1206
help="Bind new branch to from location."),
1208
aliases = ['get', 'clone']
1437
1210
def run(self, from_location, to_location=None, revision=None,
1438
1211
hardlink=False, stacked=False, standalone=False, no_tree=False,
1439
use_existing_dir=False, switch=False, bind=False,
1441
from breezy import switch as _mod_switch
1442
accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1212
use_existing_dir=False, switch=False, bind=False):
1213
from bzrlib import switch as _mod_switch
1214
from bzrlib.tag import _merge_tags_if_possible
1215
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1444
if not (hardlink or files_from):
1445
# accelerator_tree is usually slower because you have to read N
1446
# files (no readahead, lots of seeks, etc), but allow the user to
1447
# explicitly request it
1448
accelerator_tree = None
1449
if files_from is not None and files_from != from_location:
1450
accelerator_tree = WorkingTree.open(files_from)
1451
1217
revision = _get_one_revision('branch', revision)
1452
self.add_cleanup(br_from.lock_read().unlock)
1219
self.add_cleanup(br_from.unlock)
1453
1220
if revision is not None:
1454
1221
revision_id = revision.as_revision_id(br_from)
1459
1226
revision_id = br_from.last_revision()
1460
1227
if to_location is None:
1461
to_location = getattr(br_from, "name", None)
1463
to_location = urlutils.derive_to_location(from_location)
1228
to_location = urlutils.derive_to_location(from_location)
1464
1229
to_transport = transport.get_transport(to_location)
1466
1231
to_transport.mkdir('.')
1467
1232
except errors.FileExists:
1469
to_dir = controldir.ControlDir.open_from_transport(
1471
except errors.NotBranchError:
1472
if not use_existing_dir:
1473
raise errors.BzrCommandError(gettext('Target directory "%s" '
1474
'already exists.') % to_location)
1233
if not use_existing_dir:
1234
raise errors.BzrCommandError('Target directory "%s" '
1235
'already exists.' % to_location)
1479
to_dir.open_branch()
1238
bzrdir.BzrDir.open_from_transport(to_transport)
1480
1239
except errors.NotBranchError:
1483
1242
raise errors.AlreadyBranchError(to_location)
1484
1243
except errors.NoSuchFile:
1485
raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
1244
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1491
# preserve whatever source format we have.
1492
to_dir = br_from.controldir.sprout(
1493
to_transport.base, revision_id,
1494
possible_transports=[to_transport],
1495
accelerator_tree=accelerator_tree, hardlink=hardlink,
1496
stacked=stacked, force_new_repo=standalone,
1497
create_tree_if_local=not no_tree, source_branch=br_from)
1498
branch = to_dir.open_branch(
1499
possible_transports=[
1500
br_from.controldir.root_transport, to_transport])
1501
except errors.NoSuchRevision:
1502
to_transport.delete_tree('.')
1503
msg = gettext("The branch {0} has no revision {1}.").format(
1504
from_location, revision)
1505
raise errors.BzrCommandError(msg)
1508
to_repo = to_dir.open_repository()
1509
except errors.NoRepositoryPresent:
1510
to_repo = to_dir.create_repository()
1511
to_repo.fetch(br_from.repository, revision_id=revision_id)
1512
branch = br_from.sprout(to_dir, revision_id=revision_id)
1513
br_from.tags.merge_to(branch.tags)
1247
# preserve whatever source format we have.
1248
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1249
possible_transports=[to_transport],
1250
accelerator_tree=accelerator_tree,
1251
hardlink=hardlink, stacked=stacked,
1252
force_new_repo=standalone,
1253
create_tree_if_local=not no_tree,
1254
source_branch=br_from)
1255
branch = dir.open_branch()
1256
except errors.NoSuchRevision:
1257
to_transport.delete_tree('.')
1258
msg = "The branch %s has no revision %s." % (from_location,
1260
raise errors.BzrCommandError(msg)
1261
_merge_tags_if_possible(br_from, branch)
1515
1262
# If the source branch is stacked, the new branch may
1516
1263
# be stacked whether we asked for that explicitly or not.
1517
1264
# We therefore need a try/except here and not just 'if stacked:'
1519
note(gettext('Created new stacked branch referring to %s.') %
1266
note('Created new stacked branch referring to %s.' %
1520
1267
branch.get_stacked_on_url())
1521
except (errors.NotStacked, _mod_branch.UnstackableBranchFormat,
1522
errors.UnstackableRepositoryFormat) as e:
1523
note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
1268
except (errors.NotStacked, errors.UnstackableBranchFormat,
1269
errors.UnstackableRepositoryFormat), e:
1270
note('Branched %d revision(s).' % branch.revno())
1525
1272
# Bind to the parent
1526
1273
parent_branch = Branch.open(from_location)
1527
1274
branch.bind(parent_branch)
1528
note(gettext('New branch bound to %s') % from_location)
1275
note('New branch bound to %s' % from_location)
1530
1277
# Switch to the new branch
1531
1278
wt, _ = WorkingTree.open_containing('.')
1532
_mod_switch.switch(wt.controldir, branch)
1533
note(gettext('Switched to branch: %s'),
1279
_mod_switch.switch(wt.bzrdir, branch)
1280
note('Switched to branch: %s',
1534
1281
urlutils.unescape_for_display(branch.base, 'utf-8'))
1537
class cmd_branches(Command):
1538
__doc__ = """List the branches available at the current location.
1540
This command will print the names of all the branches at the current
1544
takes_args = ['location?']
1546
Option('recursive', short_name='R',
1547
help='Recursively scan for branches rather than '
1548
'just looking in the specified location.')]
1550
def run(self, location=".", recursive=False):
1552
t = transport.get_transport(location)
1553
if not t.listable():
1554
raise errors.BzrCommandError(
1555
"Can't scan this type of location.")
1556
for b in controldir.ControlDir.find_branches(t):
1557
self.outf.write("%s\n" % urlutils.unescape_for_display(
1558
urlutils.relative_url(t.base, b.base),
1559
self.outf.encoding).rstrip("/"))
1561
dir = controldir.ControlDir.open_containing(location)[0]
1563
active_branch = dir.open_branch(name="")
1564
except errors.NotBranchError:
1565
active_branch = None
1567
for name, branch in iter_sibling_branches(dir):
1570
active = (active_branch is not None and
1571
active_branch.user_url == branch.user_url)
1572
names[name] = active
1573
# Only mention the current branch explicitly if it's not
1574
# one of the colocated branches
1575
if not any(viewvalues(names)) and active_branch is not None:
1576
self.outf.write("* %s\n" % gettext("(default)"))
1577
for name in sorted(names):
1578
active = names[name]
1583
self.outf.write("%s %s\n" % (
1584
prefix, name.encode(self.outf.encoding)))
1587
1284
class cmd_checkout(Command):
1588
__doc__ = """Create a new checkout of an existing branch.
1285
"""Create a new checkout of an existing branch.
1590
1287
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1591
1288
the branch found in '.'. This is useful if you have removed the working tree
1689
1385
class cmd_update(Command):
1690
__doc__ = """Update a working tree to a new revision.
1692
This will perform a merge of the destination revision (the tip of the
1693
branch, or the specified revision) into the working tree, and then make
1694
that revision the basis revision for the working tree.
1696
You can use this to visit an older revision, or to update a working tree
1697
that is out of date from its branch.
1699
If there are any uncommitted changes in the tree, they will be carried
1700
across and remain as uncommitted changes after the update. To discard
1701
these changes, use 'brz revert'. The uncommitted changes may conflict
1702
with the changes brought in by the change in basis revision.
1704
If the tree's branch is bound to a master branch, brz will also update
1386
"""Update a tree to have the latest code committed to its branch.
1388
This will perform a merge into the working tree, and may generate
1389
conflicts. If you have any local changes, you will still
1390
need to commit them after the update for the update to be complete.
1392
If you want to discard your local changes, you can just do a
1393
'bzr revert' instead of 'bzr commit' after the update.
1395
If the tree's branch is bound to a master branch, it will also update
1705
1396
the branch from the master.
1707
You cannot update just a single file or directory, because each Bazaar
1708
working tree has just a single basis revision. If you want to restore a
1709
file that has been removed locally, use 'brz revert' instead of 'brz
1710
update'. If you want to restore a file to its state in a previous
1711
revision, use 'brz revert' with a '-r' option, or use 'brz cat' to write
1712
out the old content of that file to a new location.
1714
The 'dir' argument, if given, must be the location of the root of a
1715
working tree to update. By default, the working tree that contains the
1716
current working directory is used.
1719
1399
_see_also = ['pull', 'working-trees', 'status-flags']
1720
1400
takes_args = ['dir?']
1721
takes_options = ['revision',
1723
help="Show base revision text in conflicts."),
1401
takes_options = ['revision']
1725
1402
aliases = ['up']
1727
def run(self, dir=None, revision=None, show_base=None):
1404
def run(self, dir='.', revision=None):
1728
1405
if revision is not None and len(revision) != 1:
1729
raise errors.BzrCommandError(gettext(
1730
"brz update --revision takes exactly one revision"))
1732
tree = WorkingTree.open_containing('.')[0]
1734
tree, relpath = WorkingTree.open_containing(dir)
1737
raise errors.BzrCommandError(gettext(
1738
"brz update can only update a whole tree, "
1739
"not a file or subdirectory"))
1406
raise errors.BzrCommandError(
1407
"bzr update --revision takes exactly one revision")
1408
tree = WorkingTree.open_containing(dir)[0]
1740
1409
branch = tree.branch
1741
1410
possible_transports = []
1742
1411
master = branch.get_master_branch(
1743
1412
possible_transports=possible_transports)
1744
1413
if master is not None:
1745
1415
branch_location = master.base
1417
tree.lock_tree_write()
1748
1418
branch_location = tree.branch.base
1749
tree.lock_tree_write()
1750
1419
self.add_cleanup(tree.unlock)
1751
1420
# get rid of the final '/' and be ready for display
1752
branch_location = urlutils.unescape_for_display(
1753
branch_location.rstrip('/'),
1421
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1755
1423
existing_pending_merges = tree.get_parent_ids()[1:]
1756
1424
if master is None:
1778
1446
change_reporter,
1779
1447
possible_transports=possible_transports,
1780
1448
revision=revision_id,
1782
show_base=show_base)
1783
except errors.NoSuchRevision as e:
1784
raise errors.BzrCommandError(gettext(
1450
except errors.NoSuchRevision, e:
1451
raise errors.BzrCommandError(
1785
1452
"branch has no revision %s\n"
1786
"brz update --revision only works"
1787
" for a revision in the branch history")
1453
"bzr update --revision only works"
1454
" for a revision in the branch history"
1788
1455
% (e.revision))
1789
revno = tree.branch.revision_id_to_dotted_revno(
1456
revno = tree.branch.revision_id_to_revno(
1790
1457
_mod_revision.ensure_null(tree.last_revision()))
1791
note(gettext('Updated to revision {0} of branch {1}').format(
1792
'.'.join(map(str, revno)), branch_location))
1793
parent_ids = tree.get_parent_ids()
1794
if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1795
note(gettext('Your local commits will now show as pending merges with '
1796
"'brz status', and can be committed with 'brz commit'."))
1458
note('Updated to revision %d of branch %s' %
1459
(revno, branch_location))
1460
if tree.get_parent_ids()[1:] != existing_pending_merges:
1461
note('Your local commits will now show as pending merges with '
1462
"'bzr status', and can be committed with 'bzr commit'.")
1797
1463
if conflicts != 0:
1859
1524
RegistryOption.from_kwargs('file-deletion-strategy',
1860
1525
'The file deletion mode to be used.',
1861
1526
title='Deletion Strategy', value_switches=True, enum_switch=False,
1862
safe='Backup changed files (default).',
1863
keep='Delete from brz but leave the working copy.',
1864
no_backup='Don\'t backup changed files.'),
1527
safe='Only delete files if they can be'
1528
' safely recovered (default).',
1529
keep='Delete from bzr but leave the working copy.',
1530
force='Delete all the specified files, even if they can not be '
1531
'recovered and even if they are non-empty directories.')]
1866
1532
aliases = ['rm', 'del']
1867
1533
encoding_type = 'replace'
1869
1535
def run(self, file_list, verbose=False, new=False,
1870
1536
file_deletion_strategy='safe'):
1872
tree, file_list = WorkingTree.open_containing_paths(file_list)
1537
tree, file_list = tree_files(file_list)
1874
1539
if file_list is not None:
1875
1540
file_list = [f for f in file_list]
1877
self.add_cleanup(tree.lock_write().unlock)
1543
self.add_cleanup(tree.unlock)
1878
1544
# Heuristics should probably all move into tree.remove_smart or
2086
1736
to_transport.ensure_base()
2087
1737
except errors.NoSuchFile:
2088
1738
if not create_prefix:
2089
raise errors.BzrCommandError(gettext("Parent directory of %s"
1739
raise errors.BzrCommandError("Parent directory of %s"
2090
1740
" does not exist."
2091
1741
"\nYou may supply --create-prefix to create all"
2092
" leading parent directories.")
1742
" leading parent directories."
2094
1744
to_transport.create_prefix()
2097
a_controldir = controldir.ControlDir.open_from_transport(to_transport)
1747
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
2098
1748
except errors.NotBranchError:
2099
1749
# really a NotBzrDir error...
2100
create_branch = controldir.ControlDir.create_branch_convenience
2102
force_new_tree = False
2104
force_new_tree = None
1750
create_branch = bzrdir.BzrDir.create_branch_convenience
2105
1751
branch = create_branch(to_transport.base, format=format,
2106
possible_transports=[to_transport],
2107
force_new_tree=force_new_tree)
2108
a_controldir = branch.controldir
1752
possible_transports=[to_transport])
1753
a_bzrdir = branch.bzrdir
2110
from .transport.local import LocalTransport
2111
if a_controldir.has_branch():
1755
from bzrlib.transport.local import LocalTransport
1756
if a_bzrdir.has_branch():
2112
1757
if (isinstance(to_transport, LocalTransport)
2113
and not a_controldir.has_workingtree()):
1758
and not a_bzrdir.has_workingtree()):
2114
1759
raise errors.BranchExistsWithoutWorkingTree(location)
2115
1760
raise errors.AlreadyBranchError(location)
2116
branch = a_controldir.create_branch()
2117
if not no_tree and not a_controldir.has_workingtree():
2118
a_controldir.create_workingtree()
1761
branch = a_bzrdir.create_branch()
1762
a_bzrdir.create_workingtree()
2119
1763
if append_revisions_only:
2121
1765
branch.set_append_revisions_only(True)
2122
1766
except errors.UpgradeRequired:
2123
raise errors.BzrCommandError(gettext('This branch format cannot be set'
2124
' to append-revisions-only. Try --default.'))
1767
raise errors.BzrCommandError('This branch format cannot be set'
1768
' to append-revisions-only. Try --default.')
2125
1769
if not is_quiet():
2126
from .info import describe_layout, describe_format
1770
from bzrlib.info import describe_layout, describe_format
2128
tree = a_controldir.open_workingtree(recommend_upgrade=False)
1772
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
2129
1773
except (errors.NoWorkingTree, errors.NotLocalUrl):
2131
1775
repository = branch.repository
2132
1776
layout = describe_layout(repository, branch, tree).lower()
2133
format = describe_format(a_controldir, repository, branch, tree)
2134
self.outf.write(gettext("Created a {0} (format: {1})\n").format(
1777
format = describe_format(a_bzrdir, repository, branch, tree)
1778
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
2136
1779
if repository.is_shared():
2137
1780
#XXX: maybe this can be refactored into transport.path_or_url()
2138
url = repository.controldir.root_transport.external_url()
1781
url = repository.bzrdir.root_transport.external_url()
2140
1783
url = urlutils.local_path_from_url(url)
2141
except urlutils.InvalidURL:
1784
except errors.InvalidURL:
2143
self.outf.write(gettext("Using shared repository: %s\n") % url)
1786
self.outf.write("Using shared repository: %s\n" % url)
2146
1789
class cmd_init_repository(Command):
2147
__doc__ = """Create a shared repository for branches to share storage space.
1790
"""Create a shared repository for branches to share storage space.
2149
1792
New branches created under the repository directory will store their
2150
1793
revisions in the repository, not in the branch directory. For branches
2188
1831
def run(self, location, format=None, no_trees=False):
2189
1832
if format is None:
2190
format = controldir.format_registry.make_controldir('default')
1833
format = bzrdir.format_registry.make_bzrdir('default')
2192
1835
if location is None:
2195
1838
to_transport = transport.get_transport(location)
2197
if format.fixed_components:
2198
repo_format_name = None
2200
repo_format_name = format.repository_format.get_format_string()
2202
(repo, newdir, require_stacking, repository_policy) = (
2203
format.initialize_on_transport_ex(to_transport,
2204
create_prefix=True, make_working_trees=not no_trees,
2205
shared_repo=True, force_new_repo=True,
2206
use_existing_dir=True,
2207
repo_format_name=repo_format_name))
1839
to_transport.ensure_base()
1841
newdir = format.initialize_on_transport(to_transport)
1842
repo = newdir.create_repository(shared=True)
1843
repo.set_make_working_trees(not no_trees)
2208
1844
if not is_quiet():
2209
from .info import show_bzrdir_info
2210
show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
1845
from bzrlib.info import show_bzrdir_info
1846
show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
2213
1849
class cmd_diff(Command):
2214
__doc__ = """Show differences in the working tree, between revisions or branches.
1850
"""Show differences in the working tree, between revisions or branches.
2216
1852
If no arguments are given, all changes for the current tree are listed.
2217
1853
If files are given, only the changes in those files are listed.
2240
1869
Shows the difference in the working tree versus the last commit::
2244
1873
Difference between the working tree and revision 1::
2248
1877
Difference between revision 3 and revision 1::
2252
1881
Difference between revision 3 and revision 1 for branch xxx::
2256
The changes introduced by revision 2 (equivalent to -r1..2)::
2260
To see the changes introduced by revision X::
1885
To see the changes introduced in revision X::
2264
1889
Note that in the case of a merge, the -c option shows the changes
2265
1890
compared to the left hand parent. To see the changes against
2266
1891
another parent, use::
2268
brz diff -r<chosen_parent>..X
2270
The changes between the current revision and the previous revision
2271
(equivalent to -c-1 and -r-2..-1)
1893
bzr diff -r<chosen_parent>..X
1895
The changes introduced by revision 2 (equivalent to -r1..2)::
2275
1899
Show just the differences for file NEWS::
2279
1903
Show the differences in working tree xxx for file NEWS::
2283
1907
Show the differences from branch xxx to this working tree:
2287
1911
Show the differences between two branches for file NEWS::
2289
brz diff --old xxx --new yyy NEWS
2291
Same as 'brz diff' but prefix paths with old/ and new/::
2293
brz diff --prefix old/:new/
2295
Show the differences using a custom diff program with options::
2297
brz diff --using /usr/bin/diff --diff-options -wu
1913
bzr diff --old xxx --new yyy NEWS
1915
Same as 'bzr diff' but prefix paths with old/ and new/::
1917
bzr diff --prefix old/:new/
2299
1919
_see_also = ['status']
2300
1920
takes_args = ['file*']
2301
1921
takes_options = [
2302
Option('diff-options', type=text_type,
1922
Option('diff-options', type=str,
2303
1923
help='Pass these options to the external diff program.'),
2304
Option('prefix', type=text_type,
1924
Option('prefix', type=str,
2305
1925
short_name='p',
2306
1926
help='Set prefixes added to old and new filenames, as '
2307
1927
'two values separated by a colon. (eg "old/:new/").'),
2309
1929
help='Branch/tree to compare from.',
2313
1933
help='Branch/tree to compare to.',
2318
1938
Option('using',
2319
1939
help='Use this command to compare files.',
2322
RegistryOption('format',
2324
help='Diff format to use.',
2325
lazy_registry=('breezy.diff', 'format_registry'),
2326
title='Diff format'),
2328
help='How many lines of context to show.',
2332
1943
aliases = ['di', 'dif']
2335
1946
@display_command
2336
1947
def run(self, revision=None, file_list=None, diff_options=None,
2337
prefix=None, old=None, new=None, using=None, format=None,
2339
from .diff import (get_trees_and_branches_to_diff_locked,
1948
prefix=None, old=None, new=None, using=None):
1949
from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1951
if (prefix is None) or (prefix == '0'):
2343
1952
# diff -p0 format
2346
elif prefix == u'1' or prefix is None:
2347
1956
old_label = 'old/'
2348
1957
new_label = 'new/'
2349
elif u':' in prefix:
2350
old_label, new_label = prefix.split(u":")
1959
old_label, new_label = prefix.split(":")
2352
raise errors.BzrCommandError(gettext(
1961
raise errors.BzrCommandError(
2353
1962
'--prefix expects two values separated by a colon'
2354
' (eg "old/:new/")'))
1963
' (eg "old/:new/")')
2356
1965
if revision and len(revision) > 2:
2357
raise errors.BzrCommandError(gettext('brz diff --revision takes exactly'
2358
' one or two revision specifiers'))
2360
if using is not None and format is not None:
2361
raise errors.BzrCommandError(gettext(
2362
'{0} and {1} are mutually exclusive').format(
2363
'--using', '--format'))
1966
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1967
' one or two revision specifiers')
2365
1969
(old_tree, new_tree,
2366
1970
old_branch, new_branch,
2367
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
2368
file_list, revision, old, new, self.add_cleanup, apply_view=True)
2369
# GNU diff on Windows uses ANSI encoding for filenames
2370
path_encoding = osutils.get_diff_header_encoding()
2371
return show_diff_trees(old_tree, new_tree, self.outf,
1971
specific_files, extra_trees) = get_trees_and_branches_to_diff(
1972
file_list, revision, old, new, apply_view=True)
1973
return show_diff_trees(old_tree, new_tree, sys.stdout,
2372
1974
specific_files=specific_files,
2373
1975
external_diff_options=diff_options,
2374
1976
old_label=old_label, new_label=new_label,
2375
extra_trees=extra_trees,
2376
path_encoding=path_encoding,
2377
using=using, context=context,
1977
extra_trees=extra_trees, using=using)
2381
1980
class cmd_deleted(Command):
2382
__doc__ = """List files deleted in the working tree.
1981
"""List files deleted in the working tree.
2384
1983
# TODO: Show files deleted since a previous revision, or
2385
1984
# between two revisions.
2429
2032
class cmd_added(Command):
2430
__doc__ = """List files added in working tree.
2033
"""List files added in working tree.
2434
2037
_see_also = ['status', 'ls']
2435
takes_options = ['directory', 'null']
2040
help='Write an ascii NUL (\\0) separator '
2041
'between files rather than a newline.')
2437
2044
@display_command
2438
def run(self, null=False, directory=u'.'):
2439
wt = WorkingTree.open_containing(directory)[0]
2440
self.add_cleanup(wt.lock_read().unlock)
2045
def run(self, null=False):
2046
wt = WorkingTree.open_containing(u'.')[0]
2048
self.add_cleanup(wt.unlock)
2441
2049
basis = wt.basis_tree()
2442
self.add_cleanup(basis.lock_read().unlock)
2443
root_id = wt.get_root_id()
2444
for path in wt.all_versioned_paths():
2445
if basis.has_filename(path):
2449
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2051
self.add_cleanup(basis.unlock)
2052
basis_inv = basis.inventory
2055
if file_id in basis_inv:
2057
if inv.is_root(file_id) and len(basis_inv) == 0:
2059
path = inv.id2path(file_id)
2060
if not os.access(osutils.abspath(path), os.F_OK):
2452
2063
self.outf.write(path + '\0')
2597
2208
:Other filtering:
2599
The --match option can be used for finding revisions that match a
2600
regular expression in a commit message, committer, author or bug.
2601
Specifying the option several times will match any of the supplied
2602
expressions. --match-author, --match-bugs, --match-committer and
2603
--match-message can be used to only match a specific field.
2210
The --message option can be used for finding revisions that match a
2211
regular expression in a commit message.
2605
2213
:Tips & tricks:
2607
2215
GUI tools and IDEs are often better at exploring history than command
2608
2216
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2609
bzr-explorer shell, or the Loggerhead web interface. See the Bazaar
2610
Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2217
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2218
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2611
2219
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2613
You may find it useful to add the aliases below to ``breezy.conf``::
2221
You may find it useful to add the aliases below to ``bazaar.conf``::
2617
2225
top = log -l10 --line
2618
2226
show = log -v -p
2620
``brz tip`` will then show the latest revision while ``brz top``
2228
``bzr tip`` will then show the latest revision while ``bzr top``
2621
2229
will show the last 10 mainline revisions. To see the details of a
2622
particular revision X, ``brz show -rX``.
2230
particular revision X, ``bzr show -rX``.
2624
2232
If you are interested in looking deeper into a particular merge X,
2625
use ``brz log -n0 -rX``.
2233
use ``bzr log -n0 -rX``.
2627
``brz log -v`` on a branch with lots of history is currently
2235
``bzr log -v`` on a branch with lots of history is currently
2628
2236
very slow. A fix for this issue is currently under development.
2629
2237
With or without that fix, it is recommended that a revision range
2630
2238
be given when using the -v option.
2632
brz has a generic full-text matching plugin, brz-search, that can be
2240
bzr has a generic full-text matching plugin, bzr-search, that can be
2633
2241
used to find revisions matching user names, commit messages, etc.
2634
2242
Among other features, this plugin can find all revisions containing
2635
2243
a list of words but not others.
2965
2496
help='Recurse into subdirectories.'),
2966
2497
Option('from-root',
2967
2498
help='Print paths relative to the root of the branch.'),
2968
Option('unknown', short_name='u',
2969
help='Print unknown files.'),
2499
Option('unknown', help='Print unknown files.'),
2970
2500
Option('versioned', help='Print versioned files.',
2971
2501
short_name='V'),
2972
Option('ignored', short_name='i',
2973
help='Print ignored files.'),
2974
Option('kind', short_name='k',
2502
Option('ignored', help='Print ignored files.'),
2504
help='Write an ascii NUL (\\0) separator '
2505
'between files rather than a newline.'),
2975
2507
help='List entries of a particular kind: file, directory, symlink.',
2981
2511
@display_command
2982
2512
def run(self, revision=None, verbose=False,
2983
2513
recursive=False, from_root=False,
2984
2514
unknown=False, versioned=False, ignored=False,
2985
null=False, kind=None, show_ids=False, path=None, directory=None):
2515
null=False, kind=None, show_ids=False, path=None):
2987
if kind and kind not in ('file', 'directory', 'symlink', 'tree-reference'):
2988
raise errors.BzrCommandError(gettext('invalid kind specified'))
2517
if kind and kind not in ('file', 'directory', 'symlink'):
2518
raise errors.BzrCommandError('invalid kind specified')
2990
2520
if verbose and null:
2991
raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
2521
raise errors.BzrCommandError('Cannot set both --verbose and --null')
2992
2522
all = not (unknown or versioned or ignored)
2994
2524
selection = {'I':ignored, '?':unknown, 'V':versioned}
3112
2636
Patterns prefixed with '!!' act as regular ignore patterns, but have
3113
2637
precedence over the '!' exception patterns.
3117
* Ignore patterns containing shell wildcards must be quoted from
3120
* Ignore patterns starting with "#" act as comments in the ignore file.
3121
To ignore patterns that begin with that character, use the "RE:" prefix.
2639
Note: ignore patterns containing shell wildcards must be quoted from
3124
2643
Ignore the top level Makefile::
3126
brz ignore ./Makefile
2645
bzr ignore ./Makefile
3128
2647
Ignore .class files in all directories...::
3130
brz ignore "*.class"
2649
bzr ignore "*.class"
3132
2651
...but do not ignore "special.class"::
3134
brz ignore "!special.class"
3136
Ignore files whose name begins with the "#" character::
3140
Ignore .o files under the lib directory::
3142
brz ignore "lib/**/*.o"
3144
Ignore .o files under the lib directory::
3146
brz ignore "RE:lib/.*\\.o"
2653
bzr ignore "!special.class"
2655
Ignore .o files under the lib directory::
2657
bzr ignore "lib/**/*.o"
2659
Ignore .o files under the lib directory::
2661
bzr ignore "RE:lib/.*\.o"
3148
2663
Ignore everything but the "debian" toplevel directory::
3150
brz ignore "RE:(?!debian/).*"
2665
bzr ignore "RE:(?!debian/).*"
3152
2667
Ignore everything except the "local" toplevel directory,
3153
but always ignore autosave files ending in ~, even under local/::
2668
but always ignore "*~" autosave files, even under local/::
3156
brz ignore "!./local"
2671
bzr ignore "!./local"
3160
2675
_see_also = ['status', 'ignored', 'patterns']
3161
2676
takes_args = ['name_pattern*']
3162
takes_options = ['directory',
3163
Option('default-rules',
3164
help='Display the default ignore rules that brz uses.')
2678
Option('old-default-rules',
2679
help='Write out the ignore rules bzr < 0.9 always used.')
3167
def run(self, name_pattern_list=None, default_rules=None,
3169
from breezy import ignores
3170
if default_rules is not None:
3171
# dump the default rules and exit
3172
for pattern in ignores.USER_DEFAULTS:
3173
self.outf.write("%s\n" % pattern)
2682
def run(self, name_pattern_list=None, old_default_rules=None):
2683
from bzrlib import ignores
2684
if old_default_rules is not None:
2685
# dump the rules and exit
2686
for pattern in ignores.OLD_DEFAULTS:
3175
2689
if not name_pattern_list:
3176
raise errors.BzrCommandError(gettext("ignore requires at least one "
3177
"NAME_PATTERN or --default-rules."))
2690
raise errors.BzrCommandError("ignore requires at least one "
2691
"NAME_PATTERN or --old-default-rules")
3178
2692
name_pattern_list = [globbing.normalize_pattern(p)
3179
2693
for p in name_pattern_list]
3181
bad_patterns_count = 0
3182
for p in name_pattern_list:
3183
if not globbing.Globster.is_pattern_valid(p):
3184
bad_patterns_count += 1
3185
bad_patterns += ('\n %s' % p)
3187
msg = (ngettext('Invalid ignore pattern found. %s',
3188
'Invalid ignore patterns found. %s',
3189
bad_patterns_count) % bad_patterns)
3190
ui.ui_factory.show_error(msg)
3191
raise lazy_regex.InvalidPattern('')
3192
2694
for name_pattern in name_pattern_list:
3193
2695
if (name_pattern[0] == '/' or
3194
2696
(len(name_pattern) > 1 and name_pattern[1] == ':')):
3195
raise errors.BzrCommandError(gettext(
3196
"NAME_PATTERN should not be an absolute path"))
3197
tree, relpath = WorkingTree.open_containing(directory)
2697
raise errors.BzrCommandError(
2698
"NAME_PATTERN should not be an absolute path")
2699
tree, relpath = WorkingTree.open_containing(u'.')
3198
2700
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
3199
2701
ignored = globbing.Globster(name_pattern_list)
3201
self.add_cleanup(tree.lock_read().unlock)
3202
2704
for entry in tree.list_files():
3204
2706
if id is not None:
3205
2707
filename = entry[0]
3206
2708
if ignored.match(filename):
3207
matches.append(filename)
2709
matches.append(filename.encode('utf-8'))
3208
2711
if len(matches) > 0:
3209
self.outf.write(gettext("Warning: the following files are version "
3210
"controlled and match your ignore pattern:\n%s"
3211
"\nThese files will continue to be version controlled"
3212
" unless you 'brz remove' them.\n") % ("\n".join(matches),))
2712
print "Warning: the following files are version controlled and" \
2713
" match your ignore pattern:\n%s" \
2714
"\nThese files will continue to be version controlled" \
2715
" unless you 'bzr remove' them." % ("\n".join(matches),)
3215
2718
class cmd_ignored(Command):
3216
__doc__ = """List ignored files and the patterns that matched them.
2719
"""List ignored files and the patterns that matched them.
3218
2721
List all the ignored files and the ignore pattern that caused the file to
3221
2724
Alternatively, to list just the files::
3226
2729
encoding_type = 'replace'
3227
2730
_see_also = ['ignore', 'ls']
3228
takes_options = ['directory']
3230
2732
@display_command
3231
def run(self, directory=u'.'):
3232
tree = WorkingTree.open_containing(directory)[0]
3233
self.add_cleanup(tree.lock_read().unlock)
2734
tree = WorkingTree.open_containing(u'.')[0]
2736
self.add_cleanup(tree.unlock)
3234
2737
for path, file_class, kind, file_id, entry in tree.list_files():
3235
2738
if file_class != 'I':
3289
2790
================= =========================
3292
encoding_type = 'exact'
3293
2792
takes_args = ['dest', 'branch_or_subdir?']
3294
takes_options = ['directory',
3295
2794
Option('format',
3296
2795
help="Type of file to export to.",
3299
2798
Option('filters', help='Apply content filters to export the '
3300
2799
'convenient form.'),
3303
2802
help="Name of the root directory inside the exported file."),
3304
Option('per-file-timestamps',
3305
help='Set modification time of files to that of the last '
3306
'revision in which it was changed.'),
3307
Option('uncommitted',
3308
help='Export the working tree contents rather than that of the '
3311
2804
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3312
root=None, filters=False, per_file_timestamps=False, uncommitted=False,
3314
from .export import export, guess_format, get_root_name
2805
root=None, filters=False):
2806
from bzrlib.export import export
3316
2808
if branch_or_subdir is None:
3317
branch_or_subdir = directory
3319
(tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
3321
if tree is not None:
3322
self.add_cleanup(tree.lock_read().unlock)
3326
raise errors.BzrCommandError(
3327
gettext("--uncommitted requires a working tree"))
3330
export_tree = _get_one_revision_tree(
3331
'export', revision, branch=b,
3335
format = guess_format(dest)
3338
root = get_root_name(dest)
3340
if not per_file_timestamps:
3341
force_mtime = time.time()
3346
from breezy.filter_tree import ContentFilterTree
3347
export_tree = ContentFilterTree(
3348
export_tree, export_tree._content_filter_stack)
2809
tree = WorkingTree.open_containing(u'.')[0]
2813
b, subdir = Branch.open_containing(branch_or_subdir)
2816
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3351
export(export_tree, dest, format, root, subdir,
3352
per_file_timestamps=per_file_timestamps)
3353
except errors.NoSuchExportFormat as e:
3354
raise errors.BzrCommandError(
3355
gettext('Unsupported export format: %s') % e.format)
2818
export(rev_tree, dest, format, root, subdir, filtered=filters)
2819
except errors.NoSuchExportFormat, e:
2820
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3358
2823
class cmd_cat(Command):
3359
__doc__ = """Write the contents of a file as of a given revision to standard output.
2824
"""Write the contents of a file as of a given revision to standard output.
3361
2826
If no revision is nominated, the last revision is used.
3377
2842
@display_command
3378
2843
def run(self, filename, revision=None, name_from_revision=False,
3379
filters=False, directory=None):
3380
2845
if revision is not None and len(revision) != 1:
3381
raise errors.BzrCommandError(gettext("brz cat --revision takes exactly"
3382
" one revision specifier"))
2846
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2847
" one revision specifier")
3383
2848
tree, branch, relpath = \
3384
_open_directory_or_containing_tree_or_branch(filename, directory)
3385
self.add_cleanup(branch.lock_read().unlock)
2849
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2851
self.add_cleanup(branch.unlock)
3386
2852
return self._run(tree, branch, relpath, filename, revision,
3387
2853
name_from_revision, filters)
3389
2855
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3392
2857
if tree is None:
3393
2858
tree = b.basis_tree()
3394
2859
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3395
self.add_cleanup(rev_tree.lock_read().unlock)
2860
rev_tree.lock_read()
2861
self.add_cleanup(rev_tree.unlock)
3397
2863
old_file_id = rev_tree.path2id(relpath)
3399
# TODO: Split out this code to something that generically finds the
3400
# best id for a path across one or more trees; it's like
3401
# find_ids_across_trees but restricted to find just one. -- mbp
3403
2865
if name_from_revision:
3404
2866
# Try in revision if requested
3405
2867
if old_file_id is None:
3406
raise errors.BzrCommandError(gettext(
3407
"{0!r} is not present in revision {1}").format(
2868
raise errors.BzrCommandError(
2869
"%r is not present in revision %s" % (
3408
2870
filename, rev_tree.get_revision_id()))
3410
actual_file_id = old_file_id
2872
content = rev_tree.get_file_text(old_file_id)
3412
2874
cur_file_id = tree.path2id(relpath)
3413
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3414
actual_file_id = cur_file_id
3415
elif old_file_id is not None:
3416
actual_file_id = old_file_id
3418
raise errors.BzrCommandError(gettext(
3419
"{0!r} is not present in revision {1}").format(
2876
if cur_file_id is not None:
2877
# Then try with the actual file id
2879
content = rev_tree.get_file_text(cur_file_id)
2881
except errors.NoSuchId:
2882
# The actual file id didn't exist at that time
2884
if not found and old_file_id is not None:
2885
# Finally try with the old file id
2886
content = rev_tree.get_file_text(old_file_id)
2889
# Can't be found anywhere
2890
raise errors.BzrCommandError(
2891
"%r is not present in revision %s" % (
3420
2892
filename, rev_tree.get_revision_id()))
3421
relpath = rev_tree.id2path(actual_file_id)
3423
from .filter_tree import ContentFilterTree
3424
filter_tree = ContentFilterTree(rev_tree,
3425
rev_tree._content_filter_stack)
3426
fileobj = filter_tree.get_file(relpath, actual_file_id)
2894
from bzrlib.filters import (
2895
ContentFilterContext,
2896
filtered_output_bytes,
2898
filters = rev_tree._content_filter_stack(relpath)
2899
chunks = content.splitlines(True)
2900
content = filtered_output_bytes(chunks, filters,
2901
ContentFilterContext(relpath, rev_tree))
2903
self.outf.writelines(content)
3428
fileobj = rev_tree.get_file(relpath, actual_file_id)
3429
shutil.copyfileobj(fileobj, self.outf)
2906
self.outf.write(content)
3433
2909
class cmd_local_time_offset(Command):
3434
__doc__ = """Show the offset in seconds from GMT to local time."""
2910
"""Show the offset in seconds from GMT to local time."""
3436
2912
@display_command
3438
self.outf.write("%s\n" % osutils.local_time_offset())
2914
print osutils.local_time_offset()
3442
2918
class cmd_commit(Command):
3443
__doc__ = """Commit changes into a new revision.
2919
"""Commit changes into a new revision.
3445
2921
An explanatory message needs to be given for each commit. This is
3446
2922
often done by using the --message option (getting the message from the
3481
2957
A common mistake is to forget to add a new file or directory before
3482
2958
running the commit command. The --strict option checks for unknown
3483
2959
files and aborts the commit if any are found. More advanced pre-commit
3484
checks can be implemented by defining hooks. See ``brz help hooks``
2960
checks can be implemented by defining hooks. See ``bzr help hooks``
3487
2963
:Things to note:
3489
2965
If you accidentially commit the wrong changes or make a spelling
3490
2966
mistake in the commit message say, you can use the uncommit command
3491
to undo it. See ``brz help uncommit`` for details.
2967
to undo it. See ``bzr help uncommit`` for details.
3493
2969
Hooks can also be configured to run after a commit. This allows you
3494
2970
to trigger updates to external systems like bug trackers. The --fixes
3495
2971
option can be used to record the association between a revision and
3496
one or more bugs. See ``brz help bugs`` for details.
2972
one or more bugs. See ``bzr help bugs`` for details.
2974
A selective commit may fail in some cases where the committed
2975
tree would be invalid. Consider::
2980
bzr commit foo -m "committing foo"
2981
bzr mv foo/bar foo/baz
2984
bzr commit foo/bar -m "committing bar but not baz"
2986
In the example above, the last commit will fail by design. This gives
2987
the user the opportunity to decide whether they want to commit the
2988
rename at the same time, separately first, or not at all. (As a general
2989
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2991
# TODO: Run hooks on tree to-be-committed, and after commit.
2993
# TODO: Strict commit that fails if there are deleted files.
2994
# (what does "deleted files" mean ??)
2996
# TODO: Give better message for -s, --summary, used by tla people
2998
# XXX: verbose currently does nothing
3499
3000
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
3500
3001
takes_args = ['selected*']
3501
3002
takes_options = [
3502
ListOption('exclude', type=text_type, short_name='x',
3003
ListOption('exclude', type=str, short_name='x',
3503
3004
help="Do not consider changes made to a given path."),
3504
Option('message', type=text_type,
3005
Option('message', type=unicode,
3505
3006
short_name='m',
3506
3007
help="Description of the new revision."),
3508
3009
Option('unchanged',
3509
3010
help='Commit even if nothing has changed.'),
3510
Option('file', type=text_type,
3011
Option('file', type=str,
3511
3012
short_name='F',
3512
3013
argname='msgfile',
3513
3014
help='Take commit message from this file.'),
3514
3015
Option('strict',
3515
3016
help="Refuse to commit if there are unknown "
3516
3017
"files in the working tree."),
3517
Option('commit-time', type=text_type,
3018
Option('commit-time', type=str,
3518
3019
help="Manually set a commit time using commit date "
3519
3020
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3520
ListOption('fixes', type=text_type,
3021
ListOption('fixes', type=str,
3521
3022
help="Mark a bug as being fixed by this revision "
3522
"(see \"brz help bugs\")."),
3523
ListOption('author', type=text_type,
3023
"(see \"bzr help bugs\")."),
3024
ListOption('author', type=unicode,
3524
3025
help="Set the author's name, if it's different "
3525
3026
"from the committer."),
3526
3027
Option('local',
3529
3030
"the master branch until a normal commit "
3530
3031
"is performed."
3532
Option('show-diff', short_name='p',
3533
3034
help='When no message is supplied, show the diff along'
3534
3035
' with the status summary in the message editor.'),
3536
help='When committing to a foreign version control '
3537
'system do not push data that can not be natively '
3540
3037
aliases = ['ci', 'checkin']
3542
3039
def _iter_bug_fix_urls(self, fixes, branch):
3543
default_bugtracker = None
3544
3040
# Configure the properties for bug fixing attributes.
3545
3041
for fixed_bug in fixes:
3546
3042
tokens = fixed_bug.split(':')
3547
if len(tokens) == 1:
3548
if default_bugtracker is None:
3549
branch_config = branch.get_config_stack()
3550
default_bugtracker = branch_config.get(
3552
if default_bugtracker is None:
3553
raise errors.BzrCommandError(gettext(
3554
"No tracker specified for bug %s. Use the form "
3555
"'tracker:id' or specify a default bug tracker "
3556
"using the `bugtracker` option.\nSee "
3557
"\"brz help bugs\" for more information on this "
3558
"feature. Commit refused.") % fixed_bug)
3559
tag = default_bugtracker
3561
elif len(tokens) != 2:
3562
raise errors.BzrCommandError(gettext(
3043
if len(tokens) != 2:
3044
raise errors.BzrCommandError(
3563
3045
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3564
"See \"brz help bugs\" for more information on this "
3565
"feature.\nCommit refused.") % fixed_bug)
3567
tag, bug_id = tokens
3046
"See \"bzr help bugs\" for more information on this "
3047
"feature.\nCommit refused." % fixed_bug)
3048
tag, bug_id = tokens
3569
3050
yield bugtracker.get_bug_url(tag, branch, bug_id)
3570
except bugtracker.UnknownBugTrackerAbbreviation:
3571
raise errors.BzrCommandError(gettext(
3572
'Unrecognized bug %s. Commit refused.') % fixed_bug)
3573
except bugtracker.MalformedBugIdentifier as e:
3574
raise errors.BzrCommandError(gettext(
3575
u"%s\nCommit refused.") % (e,))
3051
except errors.UnknownBugTrackerAbbreviation:
3052
raise errors.BzrCommandError(
3053
'Unrecognized bug %s. Commit refused.' % fixed_bug)
3054
except errors.MalformedBugIdentifier, e:
3055
raise errors.BzrCommandError(
3056
"%s\nCommit refused." % (str(e),))
3577
3058
def run(self, message=None, file=None, verbose=False, selected_list=None,
3578
3059
unchanged=False, strict=False, local=False, fixes=None,
3579
author=None, show_diff=False, exclude=None, commit_time=None,
3581
from .commit import (
3060
author=None, show_diff=False, exclude=None, commit_time=None):
3061
from bzrlib.errors import (
3582
3062
PointlessCommit,
3584
from .errors import (
3585
3063
ConflictsInTree,
3586
3064
StrictCommitFailed
3588
from .msgeditor import (
3066
from bzrlib.msgeditor import (
3589
3067
edit_commit_message_encoded,
3590
3068
generate_commit_message_template,
3591
make_commit_message_template_encoded,
3069
make_commit_message_template_encoded
3595
3072
commit_stamp = offset = None
3596
3073
if commit_time is not None:
3598
3075
commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3599
except ValueError as e:
3600
raise errors.BzrCommandError(gettext(
3601
"Could not parse --commit-time: " + str(e)))
3076
except ValueError, e:
3077
raise errors.BzrCommandError(
3078
"Could not parse --commit-time: " + str(e))
3080
# TODO: Need a blackbox test for invoking the external editor; may be
3081
# slightly problematic to run this cross-platform.
3083
# TODO: do more checks that the commit will succeed before
3084
# spending the user's valuable time typing a commit message.
3603
3086
properties = {}
3605
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3088
tree, selected_list = tree_files(selected_list)
3606
3089
if selected_list == ['']:
3607
3090
# workaround - commit of root of tree should be exactly the same
3608
3091
# as just default commit in that tree, and succeed even though
3633
3116
'(use --file "%(f)s" to take commit message from that file)'
3634
3117
% { 'f': message })
3635
3118
ui.ui_factory.show_warning(warning_msg)
3637
message = message.replace('\r\n', '\n')
3638
message = message.replace('\r', '\n')
3640
raise errors.BzrCommandError(gettext(
3641
"please specify either --message or --file"))
3643
3120
def get_message(commit_obj):
3644
3121
"""Callback to get commit message"""
3646
with open(file) as f:
3647
my_message = f.read().decode(osutils.get_user_encoding())
3648
elif message is not None:
3649
my_message = message
3651
# No message supplied: make one up.
3652
# text is the status of the tree
3653
text = make_commit_message_template_encoded(tree,
3122
my_message = message
3123
if my_message is not None and '\r' in my_message:
3124
my_message = my_message.replace('\r\n', '\n')
3125
my_message = my_message.replace('\r', '\n')
3126
if my_message is None and not file:
3127
t = make_commit_message_template_encoded(tree,
3654
3128
selected_list, diff=show_diff,
3655
3129
output_encoding=osutils.get_user_encoding())
3656
# start_message is the template generated from hooks
3657
# XXX: Warning - looks like hooks return unicode,
3658
# make_commit_message_template_encoded returns user encoding.
3659
# We probably want to be using edit_commit_message instead to
3661
my_message = set_commit_message(commit_obj)
3662
if my_message is None:
3663
start_message = generate_commit_message_template(commit_obj)
3664
my_message = edit_commit_message_encoded(text,
3665
start_message=start_message)
3666
if my_message is None:
3667
raise errors.BzrCommandError(gettext("please specify a commit"
3668
" message with either --message or --file"))
3669
if my_message == "":
3670
raise errors.BzrCommandError(gettext("Empty commit message specified."
3671
" Please specify a commit message with either"
3672
" --message or --file or leave a blank message"
3673
" with --message \"\"."))
3130
start_message = generate_commit_message_template(commit_obj)
3131
my_message = edit_commit_message_encoded(t,
3132
start_message=start_message)
3133
if my_message is None:
3134
raise errors.BzrCommandError("please specify a commit"
3135
" message with either --message or --file")
3136
elif my_message and file:
3137
raise errors.BzrCommandError(
3138
"please specify either --message or --file")
3140
my_message = codecs.open(file, 'rt',
3141
osutils.get_user_encoding()).read()
3142
if my_message == "":
3143
raise errors.BzrCommandError("empty commit message specified")
3674
3144
return my_message
3676
3146
# The API permits a commit with a filter of [] to mean 'select nothing'
3684
3154
reporter=None, verbose=verbose, revprops=properties,
3685
3155
authors=author, timestamp=commit_stamp,
3686
3156
timezone=offset,
3687
exclude=tree.safe_relpath_files(exclude),
3157
exclude=safe_relpath_files(tree, exclude))
3689
3158
except PointlessCommit:
3690
raise errors.BzrCommandError(gettext("No changes to commit."
3691
" Please 'brz add' the files you want to commit, or use"
3692
" --unchanged to force an empty commit."))
3159
# FIXME: This should really happen before the file is read in;
3160
# perhaps prepare the commit; get the message; then actually commit
3161
raise errors.BzrCommandError("No changes to commit."
3162
" Use --unchanged to commit anyhow.")
3693
3163
except ConflictsInTree:
3694
raise errors.BzrCommandError(gettext('Conflicts detected in working '
3695
'tree. Use "brz conflicts" to list, "brz resolve FILE" to'
3164
raise errors.BzrCommandError('Conflicts detected in working '
3165
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
3697
3167
except StrictCommitFailed:
3698
raise errors.BzrCommandError(gettext("Commit refused because there are"
3699
" unknown files in the working tree."))
3700
except errors.BoundBranchOutOfDate as e:
3701
e.extra_help = (gettext("\n"
3702
'To commit to master branch, run update and then commit.\n'
3703
'You can also pass --local to commit to continue working '
3168
raise errors.BzrCommandError("Commit refused because there are"
3169
" unknown files in the working tree.")
3170
except errors.BoundBranchOutOfDate, e:
3171
raise errors.BzrCommandError(str(e) + "\n"
3172
'To commit to master branch, run update and then commit.\n'
3173
'You can also pass --local to commit to continue working '
3708
3177
class cmd_check(Command):
3709
__doc__ = """Validate working tree structure, branch consistency and repository history.
3178
"""Validate working tree structure, branch consistency and repository history.
3711
3180
This command checks various invariants about branch and repository storage
3712
to detect data corruption or brz bugs.
3181
to detect data corruption or bzr bugs.
3714
3183
The working tree and branch checks will only give output if a problem is
3715
3184
detected. The output fields of the repository check are:
3778
3247
class cmd_upgrade(Command):
3779
__doc__ = """Upgrade a repository, branch or working tree to a newer format.
3781
When the default format has changed after a major new release of
3782
Bazaar, you may be informed during certain operations that you
3783
should upgrade. Upgrading to a newer format may improve performance
3784
or make new features available. It may however limit interoperability
3785
with older repositories or with older versions of Bazaar.
3787
If you wish to upgrade to a particular format rather than the
3788
current default, that can be specified using the --format option.
3789
As a consequence, you can use the upgrade command this way to
3790
"downgrade" to an earlier format, though some conversions are
3791
a one way process (e.g. changing from the 1.x default to the
3792
2.x default) so downgrading is not always possible.
3794
A backup.bzr.~#~ directory is created at the start of the conversion
3795
process (where # is a number). By default, this is left there on
3796
completion. If the conversion fails, delete the new .bzr directory
3797
and rename this one back in its place. Use the --clean option to ask
3798
for the backup.bzr directory to be removed on successful conversion.
3799
Alternatively, you can delete it by hand if everything looks good
3802
If the location given is a shared repository, dependent branches
3803
are also converted provided the repository converts successfully.
3804
If the conversion of a branch fails, remaining branches are still
3807
For more information on upgrades, see the Bazaar Upgrade Guide,
3808
http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
3248
"""Upgrade branch storage to current format.
3250
The check command or bzr developers may sometimes advise you to run
3251
this command. When the default format has changed you may also be warned
3252
during other operations to upgrade.
3811
_see_also = ['check', 'reconcile', 'formats']
3255
_see_also = ['check']
3812
3256
takes_args = ['url?']
3813
3257
takes_options = [
3814
RegistryOption('format',
3815
help='Upgrade to a specific format. See "brz help'
3816
' formats" for details.',
3817
lazy_registry=('breezy.controldir', 'format_registry'),
3818
converter=lambda name: controldir.format_registry.make_controldir(name),
3819
value_switches=True, title='Branch format'),
3821
help='Remove the backup.bzr directory if successful.'),
3823
help="Show what would be done, but don't actually do anything."),
3258
RegistryOption('format',
3259
help='Upgrade to a specific format. See "bzr help'
3260
' formats" for details.',
3261
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3262
converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3263
value_switches=True, title='Branch format'),
3826
def run(self, url='.', format=None, clean=False, dry_run=False):
3827
from .upgrade import upgrade
3828
exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3830
if len(exceptions) == 1:
3831
# Compatibility with historical behavior
3266
def run(self, url='.', format=None):
3267
from bzrlib.upgrade import upgrade
3268
upgrade(url, format)
3837
3271
class cmd_whoami(Command):
3838
__doc__ = """Show or set brz user id.
3272
"""Show or set bzr user id.
3841
3275
Show the email of the current user::
3845
3279
Set the current user::
3847
brz whoami "Frank Chu <fchu@example.com>"
3281
bzr whoami "Frank Chu <fchu@example.com>"
3849
takes_options = [ 'directory',
3283
takes_options = [ Option('email',
3851
3284
help='Display email address only.'),
3852
3285
Option('branch',
3853
3286
help='Set identity for the current branch instead of '
3857
3290
encoding_type = 'replace'
3859
3292
@display_command
3860
def run(self, email=False, branch=False, name=None, directory=None):
3293
def run(self, email=False, branch=False, name=None):
3861
3294
if name is None:
3862
if directory is None:
3863
# use branch if we're inside one; otherwise global config
3865
c = Branch.open_containing(u'.')[0].get_config_stack()
3866
except errors.NotBranchError:
3867
c = _mod_config.GlobalStack()
3869
c = Branch.open(directory).get_config_stack()
3870
identity = c.get('email')
3295
# use branch if we're inside one; otherwise global config
3297
c = Branch.open_containing('.')[0].get_config()
3298
except errors.NotBranchError:
3299
c = config.GlobalConfig()
3872
self.outf.write(_mod_config.extract_email_address(identity)
3301
self.outf.write(c.user_email() + '\n')
3875
self.outf.write(identity + '\n')
3303
self.outf.write(c.username() + '\n')
3879
raise errors.BzrCommandError(gettext("--email can only be used to display existing "
3882
3306
# display a warning if an email address isn't included in the given name.
3884
_mod_config.extract_email_address(name)
3885
except _mod_config.NoEmailInUsername as e:
3308
config.extract_email_address(name)
3309
except errors.NoEmailInUsername, e:
3886
3310
warning('"%s" does not seem to contain an email address. '
3887
3311
'This is allowed, but not recommended.', name)
3889
3313
# use global config unless --branch given
3891
if directory is None:
3892
c = Branch.open_containing(u'.')[0].get_config_stack()
3894
b = Branch.open(directory)
3895
self.add_cleanup(b.lock_write().unlock)
3896
c = b.get_config_stack()
3315
c = Branch.open_containing('.')[0].get_config()
3898
c = _mod_config.GlobalStack()
3899
c.set('email', name)
3317
c = config.GlobalConfig()
3318
c.set_user_option('email', name)
3902
3321
class cmd_nick(Command):
3903
__doc__ = """Print or set the branch nickname.
3322
"""Print or set the branch nickname.
3905
If unset, the colocated branch name is used for colocated branches, and
3906
the branch directory name is used for other branches. To print the
3907
current nickname, execute with no argument.
3324
If unset, the tree root directory name is used as the nickname.
3325
To print the current nickname, execute with no argument.
3909
3327
Bound branches use the nickname of its master branch unless it is set
3966
3383
def remove_alias(self, alias_name):
3967
3384
if alias_name is None:
3968
raise errors.BzrCommandError(gettext(
3969
'brz alias --remove expects an alias to remove.'))
3385
raise errors.BzrCommandError(
3386
'bzr alias --remove expects an alias to remove.')
3970
3387
# If alias is not found, print something like:
3971
3388
# unalias: foo: not found
3972
c = _mod_config.GlobalConfig()
3389
c = config.GlobalConfig()
3973
3390
c.unset_alias(alias_name)
3975
3392
@display_command
3976
3393
def print_aliases(self):
3977
3394
"""Print out the defined aliases in a similar format to bash."""
3978
aliases = _mod_config.GlobalConfig().get_aliases()
3979
for key, value in sorted(viewitems(aliases)):
3980
self.outf.write('brz alias %s="%s"\n' % (key, value))
3395
aliases = config.GlobalConfig().get_aliases()
3396
for key, value in sorted(aliases.iteritems()):
3397
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3982
3399
@display_command
3983
3400
def print_alias(self, alias_name):
3984
from .commands import get_alias
3401
from bzrlib.commands import get_alias
3985
3402
alias = get_alias(alias_name)
3986
3403
if alias is None:
3987
self.outf.write("brz alias: %s: not found\n" % alias_name)
3404
self.outf.write("bzr alias: %s: not found\n" % alias_name)
3989
3406
self.outf.write(
3990
'brz alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3407
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3992
3409
def set_alias(self, alias_name, alias_command):
3993
3410
"""Save the alias in the global config."""
3994
c = _mod_config.GlobalConfig()
3411
c = config.GlobalConfig()
3995
3412
c.set_alias(alias_name, alias_command)
3998
3415
class cmd_selftest(Command):
3999
__doc__ = """Run internal test suite.
3416
"""Run internal test suite.
4001
3418
If arguments are given, they are regular expressions that say which tests
4002
3419
should run. Tests matching any expression are run, and other tests are
4029
3446
Tests that need working space on disk use a common temporary directory,
4030
3447
typically inside $TMPDIR or /tmp.
4032
If you set BRZ_TEST_PDB=1 when running selftest, failing tests will drop
3449
If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
4033
3450
into a pdb postmortem session.
4035
The --coverage=DIRNAME global option produces a report with covered code
4039
3453
Run only tests relating to 'ignore'::
4043
3457
Disable plugins and list tests as they're run::
4045
brz --no-plugins selftest -v
3459
bzr --no-plugins selftest -v
4047
3461
# NB: this is used from the class without creating an instance, which is
4048
3462
# why it does not have a self parameter.
4049
3463
def get_transport_type(typestring):
4050
3464
"""Parse and return a transport specifier."""
4051
3465
if typestring == "sftp":
4052
from .tests import stub_sftp
3466
from bzrlib.tests import stub_sftp
4053
3467
return stub_sftp.SFTPAbsoluteServer
4054
elif typestring == "memory":
4055
from .tests import test_server
3468
if typestring == "memory":
3469
from bzrlib.tests import test_server
4056
3470
return memory.MemoryServer
4057
elif typestring == "fakenfs":
4058
from .tests import test_server
3471
if typestring == "fakenfs":
3472
from bzrlib.tests import test_server
4059
3473
return test_server.FakeNFSServer
4060
3474
msg = "No known transport type %s. Supported types are: sftp\n" %\
4088
3504
help='List the tests instead of running them.'),
4089
3505
RegistryOption('parallel',
4090
3506
help="Run the test suite in parallel.",
4091
lazy_registry=('breezy.tests', 'parallel_registry'),
3507
lazy_registry=('bzrlib.tests', 'parallel_registry'),
4092
3508
value_switches=False,
4094
Option('randomize', type=text_type, argname="SEED",
3510
Option('randomize', type=str, argname="SEED",
4095
3511
help='Randomize the order of tests using the given'
4096
3512
' seed or "now" for the current time.'),
4097
ListOption('exclude', type=text_type, argname="PATTERN",
4099
help='Exclude tests that match this regular'
4102
help='Output test progress via subunit v1.'),
4104
help='Output test progress via subunit v2.'),
3513
Option('exclude', type=str, argname="PATTERN",
3515
help='Exclude tests that match this regular'
3518
help='Output test progress via subunit.'),
4105
3519
Option('strict', help='Fail on missing dependencies or '
4106
3520
'known failures.'),
4107
Option('load-list', type=text_type, argname='TESTLISTFILE',
3521
Option('load-list', type=str, argname='TESTLISTFILE',
4108
3522
help='Load a test id list from a text file.'),
4109
ListOption('debugflag', type=text_type, short_name='E',
3523
ListOption('debugflag', type=str, short_name='E',
4110
3524
help='Turn on a selftest debug flag.'),
4111
ListOption('starting-with', type=text_type, argname='TESTID',
3525
ListOption('starting-with', type=str, argname='TESTID',
4112
3526
param_name='starting_with', short_name='s',
4114
3528
'Load only the tests starting with TESTID.'),
4116
help="By default we disable fsync and fdatasync"
4117
" while running the test suite.")
4119
3530
encoding_type = 'replace'
4125
3536
def run(self, testspecs_list=None, verbose=False, one=False,
4126
3537
transport=None, benchmark=None,
3538
lsprof_timed=None, cache_dir=None,
4128
3539
first=False, list_only=False,
4129
3540
randomize=None, exclude=None, strict=False,
4130
load_list=None, debugflag=None, starting_with=None, subunit1=False,
4131
subunit2=False, parallel=None, lsprof_tests=False, sync=False):
4133
# During selftest, disallow proxying, as it can cause severe
4134
# performance penalties and is only needed for thread
4135
# safety. The selftest command is assumed to not use threads
4136
# too heavily. The call should be as early as possible, as
4137
# error reporting for past duplicate imports won't have useful
4139
if sys.version_info[0] < 3:
4140
# TODO(pad.lv/1696545): Allow proxying on Python 3, since
4141
# disallowing it currently leads to failures in many places.
4142
lazy_import.disallow_proxying()
4147
raise errors.BzrCommandError("tests not available. Install the "
4148
"breezy tests to run the breezy testsuite.")
3541
load_list=None, debugflag=None, starting_with=None, subunit=False,
3542
parallel=None, lsprof_tests=False):
3543
from bzrlib.tests import selftest
3544
import bzrlib.benchmarks as benchmarks
3545
from bzrlib.benchmarks import tree_creator
3547
# Make deprecation warnings visible, unless -Werror is set
3548
symbol_versioning.activate_deprecation_warnings(override=False)
3550
if cache_dir is not None:
3551
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
4150
3552
if testspecs_list is not None:
4151
3553
pattern = '|'.join(testspecs_list)
4156
from .tests import SubUnitBzrRunnerv1
4158
raise errors.BzrCommandError(gettext(
4159
"subunit not available. subunit needs to be installed "
4160
"to use --subunit."))
4161
self.additional_selftest_args['runner_class'] = SubUnitBzrRunnerv1
4162
# On Windows, disable automatic conversion of '\n' to '\r\n' in
4163
# stdout, which would corrupt the subunit stream.
4164
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
4165
# following code can be deleted when it's sufficiently deployed
4166
# -- vila/mgz 20100514
4167
if (sys.platform == "win32"
4168
and getattr(sys.stdout, 'fileno', None) is not None):
4170
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
4173
from .tests import SubUnitBzrRunnerv2
4175
raise errors.BzrCommandError(gettext(
4176
"subunit not available. subunit "
4177
"needs to be installed to use --subunit2."))
4178
self.additional_selftest_args['runner_class'] = SubUnitBzrRunnerv2
3558
from bzrlib.tests import SubUnitBzrRunner
3560
raise errors.BzrCommandError("subunit not available. subunit "
3561
"needs to be installed to use --subunit.")
3562
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
4181
3564
self.additional_selftest_args.setdefault(
4182
3565
'suite_decorators', []).append(parallel)
4184
raise errors.BzrCommandError(gettext(
4185
"--benchmark is no longer supported from brz 2.2; "
4186
"use bzr-usertest instead"))
4187
test_suite_factory = None
4189
exclude_pattern = None
3567
test_suite_factory = benchmarks.test_suite
3568
# Unless user explicitly asks for quiet, be verbose in benchmarks
3569
verbose = not is_quiet()
3570
# TODO: should possibly lock the history file...
3571
benchfile = open(".perf_history", "at", buffering=1)
3572
self.add_cleanup(benchfile.close)
4191
exclude_pattern = '(' + '|'.join(exclude) + ')'
4193
self._disable_fsync()
3574
test_suite_factory = None
4194
3576
selftest_kwargs = {"verbose": verbose,
4195
3577
"pattern": pattern,
4196
3578
"stop_on_failure": one,
4198
3580
"test_suite_factory": test_suite_factory,
4199
3581
"lsprof_timed": lsprof_timed,
4200
3582
"lsprof_tests": lsprof_tests,
3583
"bench_history": benchfile,
4201
3584
"matching_tests_first": first,
4202
3585
"list_only": list_only,
4203
3586
"random_seed": randomize,
4204
"exclude_pattern": exclude_pattern,
3587
"exclude_pattern": exclude,
4205
3588
"strict": strict,
4206
3589
"load_list": load_list,
4207
3590
"debug_flags": debugflag,
4208
3591
"starting_with": starting_with
4210
3593
selftest_kwargs.update(self.additional_selftest_args)
4212
# Make deprecation warnings visible, unless -Werror is set
4213
cleanup = symbol_versioning.activate_deprecation_warnings(
4216
result = tests.selftest(**selftest_kwargs)
3594
result = selftest(**selftest_kwargs)
4219
3595
return int(not result)
4221
def _disable_fsync(self):
4222
"""Change the 'os' functionality to not synchronize."""
4223
self._orig_fsync = getattr(os, 'fsync', None)
4224
if self._orig_fsync is not None:
4225
os.fsync = lambda filedes: None
4226
self._orig_fdatasync = getattr(os, 'fdatasync', None)
4227
if self._orig_fdatasync is not None:
4228
os.fdatasync = lambda filedes: None
4231
3598
class cmd_version(Command):
4232
__doc__ = """Show version of brz."""
3599
"""Show version of bzr."""
4234
3601
encoding_type = 'replace'
4235
3602
takes_options = [
4265
3632
@display_command
4266
3633
def run(self, branch, other):
4267
from .revision import ensure_null
3634
from bzrlib.revision import ensure_null
4269
3636
branch1 = Branch.open_containing(branch)[0]
4270
3637
branch2 = Branch.open_containing(other)[0]
4271
self.add_cleanup(branch1.lock_read().unlock)
4272
self.add_cleanup(branch2.lock_read().unlock)
3639
self.add_cleanup(branch1.unlock)
3641
self.add_cleanup(branch2.unlock)
4273
3642
last1 = ensure_null(branch1.last_revision())
4274
3643
last2 = ensure_null(branch2.last_revision())
4276
3645
graph = branch1.repository.get_graph(branch2.repository)
4277
3646
base_rev_id = graph.find_unique_lca(last1, last2)
4279
self.outf.write(gettext('merge base is revision %s\n') % base_rev_id)
3648
print 'merge base is revision %s' % base_rev_id
4282
3651
class cmd_merge(Command):
4283
__doc__ = """Perform a three-way merge.
3652
"""Perform a three-way merge.
4285
3654
The source of the merge can be specified either in the form of a branch,
4286
3655
or in the form of a path to a file containing a merge directive generated
4287
with brz send. If neither is specified, the default is the upstream branch
4288
or the branch most recently merged using --remember. The source of the
4289
merge may also be specified in the form of a path to a file in another
4290
branch: in this case, only the modifications to that file are merged into
4291
the current working tree.
4293
When merging from a branch, by default brz will try to merge in all new
4294
work from the other branch, automatically determining an appropriate base
4295
revision. If this fails, you may need to give an explicit base.
4297
To pick a different ending revision, pass "--revision OTHER". brz will
4298
try to merge in all new work up to and including revision OTHER.
4300
If you specify two values, "--revision BASE..OTHER", only revisions BASE
4301
through OTHER, excluding BASE but including OTHER, will be merged. If this
4302
causes some revisions to be skipped, i.e. if the destination branch does
4303
not already contain revision BASE, such a merge is commonly referred to as
4304
a "cherrypick". Unlike a normal merge, Bazaar does not currently track
4305
cherrypicks. The changes look like a normal commit, and the history of the
4306
changes from the other branch is not stored in the commit.
4308
Revision numbers are always relative to the source branch.
3656
with bzr send. If neither is specified, the default is the upstream branch
3657
or the branch most recently merged using --remember.
3659
When merging a branch, by default the tip will be merged. To pick a different
3660
revision, pass --revision. If you specify two values, the first will be used as
3661
BASE and the second one as OTHER. Merging individual revisions, or a subset of
3662
available revisions, like this is commonly referred to as "cherrypicking".
3664
Revision numbers are always relative to the branch being merged.
3666
By default, bzr will try to merge in all new work from the other
3667
branch, automatically determining an appropriate base. If this
3668
fails, you may need to give an explicit base.
4310
3670
Merge will do its best to combine the changes in two branches, but there
4311
3671
are some kinds of problems only a human can fix. When it encounters those,
4312
3672
it will mark a conflict. A conflict means that you need to fix something,
4313
before you can commit.
4315
Use brz resolve when you have fixed a problem. See also brz conflicts.
4317
If there is no default branch set, the first merge will set it (use
4318
--no-remember to avoid setting it). After that, you can omit the branch
4319
to use the default. To change the default, use --remember. The value will
4320
only be saved if the remote location can be accessed.
3673
before you should commit.
3675
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
3677
If there is no default branch set, the first merge will set it. After
3678
that, you can omit the branch to use the default. To change the
3679
default, use --remember. The value will only be saved if the remote
3680
location can be accessed.
4322
3682
The results of the merge are placed into the destination working
4323
directory, where they can be reviewed (with brz diff), tested, and then
3683
directory, where they can be reviewed (with bzr diff), tested, and then
4324
3684
committed to record the result of the merge.
4326
3686
merge refuses to run if there are any uncommitted changes, unless
4327
--force is given. If --force is given, then the changes from the source
4328
will be merged with the current working tree, including any uncommitted
4329
changes in the tree. The --force option can also be used to create a
3687
--force is given. The --force option can also be used to create a
4330
3688
merge revision which has more than two parents.
4332
3690
If one would like to merge changes from the working tree of the other
4460
3818
self.sanity_check_merger(merger)
4461
3819
if (merger.base_rev_id == merger.other_rev_id and
4462
3820
merger.other_rev_id is not None):
4463
# check if location is a nonexistent file (and not a branch) to
4464
# disambiguate the 'Nothing to do'
4465
if merger.interesting_files:
4466
if not merger.other_tree.has_filename(
4467
merger.interesting_files[0]):
4468
note(gettext("merger: ") + str(merger))
4469
raise errors.PathsDoNotExist([location])
4470
note(gettext('Nothing to do.'))
3821
note('Nothing to do.')
4472
if pull and not preview:
4473
3824
if merger.interesting_files is not None:
4474
raise errors.BzrCommandError(gettext('Cannot pull individual files'))
3825
raise errors.BzrCommandError('Cannot pull individual files')
4475
3826
if (merger.base_rev_id == tree.last_revision()):
4476
3827
result = tree.pull(merger.other_branch, False,
4477
3828
merger.other_rev_id)
4478
3829
result.report(self.outf)
4480
3831
if merger.this_basis is None:
4481
raise errors.BzrCommandError(gettext(
3832
raise errors.BzrCommandError(
4482
3833
"This branch has no commits."
4483
" (perhaps you would prefer 'brz pull')"))
3834
" (perhaps you would prefer 'bzr pull')")
4485
3836
return self._do_preview(merger)
4486
3837
elif interactive:
4546
3895
# Use reprocess if the merger supports it
4547
3896
merger.reprocess = merger.merge_type.supports_reprocess
4548
3897
if merger.reprocess and not merger.merge_type.supports_reprocess:
4549
raise errors.BzrCommandError(gettext("Conflict reduction is not supported"
4550
" for merge type %s.") %
3898
raise errors.BzrCommandError("Conflict reduction is not supported"
3899
" for merge type %s." %
4551
3900
merger.merge_type)
4552
3901
if merger.reprocess and merger.show_base:
4553
raise errors.BzrCommandError(gettext("Cannot do conflict reduction and"
4556
if (merger.merge_type.requires_file_merge_plan and
4557
(not getattr(merger.this_tree, 'plan_file_merge', None) or
4558
not getattr(merger.other_tree, 'plan_file_merge', None) or
4559
(merger.base_tree is not None and
4560
not getattr(merger.base_tree, 'plan_file_merge', None)))):
4561
raise errors.BzrCommandError(
4562
gettext('Plan file merge unsupported: '
4563
'Merge type incompatible with tree formats.'))
3902
raise errors.BzrCommandError("Cannot do conflict reduction and"
4565
3905
def _get_merger_from_branch(self, tree, location, revision, remember,
4566
3906
possible_transports, pb):
4567
3907
"""Produce a merger from a location, assuming it refers to a branch."""
3908
from bzrlib.tag import _merge_tags_if_possible
4568
3909
# find the branch locations
4569
3910
other_loc, user_location = self._select_branch_location(tree, location,
4592
3933
if other_revision_id is None:
4593
3934
other_revision_id = _mod_revision.ensure_null(
4594
3935
other_branch.last_revision())
4595
# Remember where we merge from. We need to remember if:
4596
# - user specify a location (and we don't merge from the parent
4598
# - user ask to remember or there is no previous location set to merge
4599
# from and user didn't ask to *not* remember
4600
if (user_location is not None
4602
or (remember is None
4603
and tree.branch.get_submit_branch() is None)))):
3936
# Remember where we merge from
3937
if ((remember or tree.branch.get_submit_branch() is None) and
3938
user_location is not None):
4604
3939
tree.branch.set_submit_branch(other_branch.base)
4605
# Merge tags (but don't set them in the master branch yet, the user
4606
# might revert this merge). Commit will propagate them.
4607
other_branch.tags.merge_to(tree.branch.tags, ignore_master=True)
4608
merger = _mod_merge.Merger.from_revision_ids(tree,
3940
_merge_tags_if_possible(other_branch, tree.branch)
3941
merger = _mod_merge.Merger.from_revision_ids(pb, tree,
4609
3942
other_revision_id, base_revision_id, other_branch, base_branch)
4610
3943
if other_path != '':
4611
3944
allow_pending = False
4709
4042
def run(self, file_list=None, merge_type=None, show_base=False,
4710
4043
reprocess=False):
4711
from .conflicts import restore
4712
4044
if merge_type is None:
4713
4045
merge_type = _mod_merge.Merge3Merger
4714
tree, file_list = WorkingTree.open_containing_paths(file_list)
4715
self.add_cleanup(tree.lock_write().unlock)
4046
tree, file_list = tree_files(file_list)
4048
self.add_cleanup(tree.unlock)
4716
4049
parents = tree.get_parent_ids()
4717
4050
if len(parents) != 2:
4718
raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4051
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4719
4052
" merges. Not cherrypicking or"
4721
4054
repository = tree.branch.repository
4722
interesting_files = None
4055
interesting_ids = None
4723
4056
new_conflicts = []
4724
4057
conflicts = tree.conflicts()
4725
4058
if file_list is not None:
4726
interesting_files = set()
4059
interesting_ids = set()
4727
4060
for filename in file_list:
4728
if not tree.is_versioned(filename):
4061
file_id = tree.path2id(filename)
4729
4063
raise errors.NotVersionedError(filename)
4730
interesting_files.add(filename)
4731
if tree.kind(filename) != "directory":
4064
interesting_ids.add(file_id)
4065
if tree.kind(file_id) != "directory":
4734
for path, ie in tree.iter_entries_by_dir(specific_files=[filename]):
4735
interesting_files.add(path)
4068
for name, ie in tree.inventory.iter_entries(file_id):
4069
interesting_ids.add(ie.file_id)
4736
4070
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4738
4072
# Remerge only supports resolving contents conflicts
4739
4073
allowed_conflicts = ('text conflict', 'contents conflict')
4740
4074
restore_files = [c.path for c in conflicts
4741
4075
if c.typestring in allowed_conflicts]
4742
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_files)
4076
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4743
4077
tree.set_conflicts(ConflictList(new_conflicts))
4744
4078
if file_list is not None:
4745
4079
restore_files = file_list
4772
4106
class cmd_revert(Command):
4774
Set files in the working tree back to the contents of a previous revision.
4107
"""Revert files to a previous revision.
4776
4109
Giving a list of files will revert only those files. Otherwise, all files
4777
4110
will be reverted. If the revision is not specified with '--revision', the
4778
working tree basis revision is used. A revert operation affects only the
4779
working tree, not any revision history like the branch and repository or
4780
the working tree basis revision.
4111
last committed revision is used.
4782
4113
To remove only some changes, without reverting to a prior version, use
4783
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4784
will remove the changes introduced by the second last commit (-2), without
4785
affecting the changes introduced by the last commit (-1). To remove
4786
certain changes on a hunk-by-hunk basis, see the shelve command.
4787
To update the branch to a specific revision or the latest revision and
4788
update the working tree accordingly while preserving local changes, see the
4114
merge instead. For example, "merge . --revision -2..-3" will remove the
4115
changes introduced by -2, without affecting the changes introduced by -1.
4116
Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
4791
Uncommitted changes to files that are reverted will be discarded.
4792
Howver, by default, any files that have been manually changed will be
4793
backed up first. (Files changed only by merge are not backed up.) Backup
4794
files have '.~#~' appended to their name, where # is a number.
4118
By default, any files that have been manually changed will be backed up
4119
first. (Files changed only by merge are not backed up.) Backup files have
4120
'.~#~' appended to their name, where # is a number.
4796
4122
When you provide files, you can use their current pathname or the pathname
4797
4123
from the target revision. So you can use revert to "undelete" a file by
5046
4361
if remote_extra and not mine_only:
5047
4362
if printed_local is True:
5048
4363
message("\n\n\n")
5049
message(ngettext("You are missing %d revision:\n",
5050
"You are missing %d revisions:\n",
5051
len(remote_extra)) %
4364
message("You are missing %d revision(s):\n" %
5052
4365
len(remote_extra))
5053
if remote_branch.supports_tags():
5054
rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
5055
4366
for revision in iter_log_revisions(remote_extra,
5056
4367
remote_branch.repository,
5059
4369
lf.log_revision(revision)
5060
4370
status_code = 1
5062
4372
if mine_only and not local_extra:
5063
4373
# We checked local, and found nothing extra
5064
message(gettext('This branch has no new revisions.\n'))
4374
message('This branch is up to date.\n')
5065
4375
elif theirs_only and not remote_extra:
5066
4376
# We checked remote, and found nothing extra
5067
message(gettext('Other branch has no new revisions.\n'))
4377
message('Other branch is up to date.\n')
5068
4378
elif not (mine_only or theirs_only or local_extra or
5070
4380
# We checked both branches, and neither one had extra
5072
message(gettext("Branches are up to date.\n"))
4382
message("Branches are up to date.\n")
5073
4383
self.cleanup_now()
5074
4384
if not status_code and parent is None and other_branch is not None:
5075
self.add_cleanup(local_branch.lock_write().unlock)
4385
local_branch.lock_write()
4386
self.add_cleanup(local_branch.unlock)
5076
4387
# handle race conditions - a parent might be set while we run.
5077
4388
if local_branch.get_parent() is None:
5078
4389
local_branch.set_parent(remote_branch.base)
5082
4393
class cmd_pack(Command):
5083
__doc__ = """Compress the data within a repository.
5085
This operation compresses the data within a bazaar repository. As
5086
bazaar supports automatic packing of repository, this operation is
5087
normally not required to be done manually.
5089
During the pack operation, bazaar takes a backup of existing repository
5090
data, i.e. pack files. This backup is eventually removed by bazaar
5091
automatically when it is safe to do so. To save disk space by removing
5092
the backed up pack files, the --clean-obsolete-packs option may be
5095
Warning: If you use --clean-obsolete-packs and your machine crashes
5096
during or immediately after repacking, you may be left with a state
5097
where the deletion has been written to disk but the new packs have not
5098
been. In this case the repository may be unusable.
4394
"""Compress the data within a repository."""
5101
4396
_see_also = ['repositories']
5102
4397
takes_args = ['branch_or_repo?']
5104
Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
5107
def run(self, branch_or_repo='.', clean_obsolete_packs=False):
5108
dir = controldir.ControlDir.open_containing(branch_or_repo)[0]
4399
def run(self, branch_or_repo='.'):
4400
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
5110
4402
branch = dir.open_branch()
5111
4403
repository = branch.repository
5112
4404
except errors.NotBranchError:
5113
4405
repository = dir.open_repository()
5114
repository.pack(clean_obsolete_packs=clean_obsolete_packs)
5117
4409
class cmd_plugins(Command):
5118
__doc__ = """List the installed plugins.
4410
"""List the installed plugins.
5120
4412
This command displays the list of installed plugins including
5121
4413
version of plugin and a short description of each.
5138
4430
@display_command
5139
4431
def run(self, verbose=False):
5140
from . import plugin
5141
# Don't give writelines a generator as some codecs don't like that
5142
self.outf.writelines(
5143
list(plugin.describe_plugins(show_paths=verbose)))
4432
import bzrlib.plugin
4433
from inspect import getdoc
4435
for name, plugin in bzrlib.plugin.plugins().items():
4436
version = plugin.__version__
4437
if version == 'unknown':
4439
name_ver = '%s %s' % (name, version)
4440
d = getdoc(plugin.module)
4442
doc = d.split('\n')[0]
4444
doc = '(no description)'
4445
result.append((name_ver, doc, plugin.path()))
4446
for name_ver, doc, path in sorted(result):
5146
4454
class cmd_testament(Command):
5147
__doc__ = """Show testament (signing-form) of a revision."""
4455
"""Show testament (signing-form) of a revision."""
5148
4456
takes_options = [
5150
4458
Option('long', help='Produce long-format testament.'),
5151
4459
Option('strict',
5152
4460
help='Produce a strict-format testament.')]
5153
4461
takes_args = ['branch?']
5154
encoding_type = 'exact'
5155
4462
@display_command
5156
4463
def run(self, branch=u'.', revision=None, long=False, strict=False):
5157
from .testament import Testament, StrictTestament
4464
from bzrlib.testament import Testament, StrictTestament
5158
4465
if strict is True:
5159
4466
testament_class = StrictTestament
5193
4501
Option('long', help='Show commit date in annotations.'),
5198
4505
encoding_type = 'exact'
5200
4507
@display_command
5201
4508
def run(self, filename, all=False, long=False, revision=None,
5202
show_ids=False, directory=None):
5203
from .annotate import (
4510
from bzrlib.annotate import annotate_file, annotate_file_tree
5206
4511
wt, branch, relpath = \
5207
_open_directory_or_containing_tree_or_branch(filename, directory)
4512
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
5208
4513
if wt is not None:
5209
self.add_cleanup(wt.lock_read().unlock)
4515
self.add_cleanup(wt.unlock)
5211
self.add_cleanup(branch.lock_read().unlock)
4518
self.add_cleanup(branch.unlock)
5212
4519
tree = _get_one_revision_tree('annotate', revision, branch=branch)
5213
self.add_cleanup(tree.lock_read().unlock)
5214
if wt is not None and revision is None:
4521
self.add_cleanup(tree.unlock)
5215
4523
file_id = wt.path2id(relpath)
5217
4525
file_id = tree.path2id(relpath)
5218
4526
if file_id is None:
5219
4527
raise errors.NotVersionedError(filename)
4528
file_version = tree.inventory[file_id].revision
5220
4529
if wt is not None and revision is None:
5221
4530
# If there is a tree and we're not annotating historical
5222
4531
# versions, annotate the working tree's content.
5223
annotate_file_tree(wt, relpath, self.outf, long, all,
5224
show_ids=show_ids, file_id=file_id)
4532
annotate_file_tree(wt, file_id, self.outf, long, all,
5226
annotate_file_tree(tree, relpath, self.outf, long, all,
5227
show_ids=show_ids, branch=branch, file_id=file_id)
4535
annotate_file(branch, file_version, file_id, long, all, self.outf,
5230
4539
class cmd_re_sign(Command):
5231
__doc__ = """Create a digital signature for an existing revision."""
4540
"""Create a digital signature for an existing revision."""
5232
4541
# TODO be able to replace existing ones.
5234
4543
hidden = True # is this right ?
5235
4544
takes_args = ['revision_id*']
5236
takes_options = ['directory', 'revision']
4545
takes_options = ['revision']
5238
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4547
def run(self, revision_id_list=None, revision=None):
5239
4548
if revision_id_list is not None and revision is not None:
5240
raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
4549
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
5241
4550
if revision_id_list is None and revision is None:
5242
raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
5243
b = WorkingTree.open_containing(directory)[0].branch
5244
self.add_cleanup(b.lock_write().unlock)
4551
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4552
b = WorkingTree.open_containing(u'.')[0].branch
4554
self.add_cleanup(b.unlock)
5245
4555
return self._run(b, revision_id_list, revision)
5247
4557
def _run(self, b, revision_id_list, revision):
5248
gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
4558
import bzrlib.gpg as gpg
4559
gpg_strategy = gpg.GPGStrategy(b.get_config())
5249
4560
if revision_id_list is not None:
5250
4561
b.repository.start_write_group()
5252
4563
for revision_id in revision_id_list:
5253
revision_id = cache_utf8.encode(revision_id)
5254
4564
b.repository.sign_revision(revision_id, gpg_strategy)
5256
4566
b.repository.abort_write_group()
5307
4616
_see_also = ['checkouts', 'unbind']
5308
4617
takes_args = ['location?']
5309
takes_options = ['directory']
5311
def run(self, location=None, directory=u'.'):
5312
b, relpath = Branch.open_containing(directory)
4620
def run(self, location=None):
4621
b, relpath = Branch.open_containing(u'.')
5313
4622
if location is None:
5315
4624
location = b.get_old_bound_location()
5316
4625
except errors.UpgradeRequired:
5317
raise errors.BzrCommandError(gettext('No location supplied. '
5318
'This format does not remember old locations.'))
4626
raise errors.BzrCommandError('No location supplied. '
4627
'This format does not remember old locations.')
5320
4629
if location is None:
5321
4630
if b.get_bound_location() is not None:
5322
raise errors.BzrCommandError(
5323
gettext('Branch is already bound'))
4631
raise errors.BzrCommandError('Branch is already bound')
5325
raise errors.BzrCommandError(
5326
gettext('No location supplied'
5327
' and no previous location known'))
4633
raise errors.BzrCommandError('No location supplied '
4634
'and no previous location known')
5328
4635
b_other = Branch.open(location)
5330
4637
b.bind(b_other)
5331
4638
except errors.DivergedBranches:
5332
raise errors.BzrCommandError(gettext('These branches have diverged.'
5333
' Try merging, and then bind again.'))
4639
raise errors.BzrCommandError('These branches have diverged.'
4640
' Try merging, and then bind again.')
5334
4641
if b.get_config().has_explicit_nickname():
5335
4642
b.nick = b_other.nick
5338
4645
class cmd_unbind(Command):
5339
__doc__ = """Convert the current checkout into a regular branch.
4646
"""Convert the current checkout into a regular branch.
5341
4648
After unbinding, the local branch is considered independent and subsequent
5342
4649
commits will be local only.
5400
4706
b = control.open_branch()
5402
4708
if tree is not None:
5403
self.add_cleanup(tree.lock_write().unlock)
4710
self.add_cleanup(tree.unlock)
5405
self.add_cleanup(b.lock_write().unlock)
5406
return self._run(b, tree, dry_run, verbose, revision, force,
4713
self.add_cleanup(b.unlock)
4714
return self._run(b, tree, dry_run, verbose, revision, force, local=local)
5409
def _run(self, b, tree, dry_run, verbose, revision, force, local,
5411
from .log import log_formatter, show_log
5412
from .uncommit import uncommit
4716
def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4717
from bzrlib.log import log_formatter, show_log
4718
from bzrlib.uncommit import uncommit
5414
4720
last_revno, last_rev_id = b.last_revision_info()
5443
4750
end_revision=last_revno)
5446
self.outf.write(gettext('Dry-run, pretending to remove'
5447
' the above revisions.\n'))
4753
ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
5449
self.outf.write(gettext('The above revision(s) will be removed.\n'))
4755
ui.ui_factory.note('The above revision(s) will be removed.')
5452
if not ui.ui_factory.confirm_action(
5453
gettext(u'Uncommit these revisions'),
5454
'breezy.builtins.uncommit',
5456
self.outf.write(gettext('Canceled\n'))
4758
if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4759
ui.ui_factory.note('Canceled')
5459
4762
mutter('Uncommitting from {%s} to {%s}',
5460
4763
last_rev_id, rev_id)
5461
4764
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
5462
revno=revno, local=local, keep_tags=keep_tags)
5463
self.outf.write(gettext('You can restore the old tip by running:\n'
5464
' brz pull . -r revid:%s\n') % last_rev_id)
4765
revno=revno, local=local)
4766
ui.ui_factory.note('You can restore the old tip by running:\n'
4767
' bzr pull . -r revid:%s' % last_rev_id)
5467
4770
class cmd_break_lock(Command):
5468
__doc__ = """Break a dead lock.
5470
This command breaks a lock on a repository, branch, working directory or
4771
"""Break a dead lock on a repository, branch or working directory.
5473
4773
CAUTION: Locks should only be broken when you are sure that the process
5474
4774
holding the lock has been stopped.
5476
You can get information on what locks are open via the 'brz info
4776
You can get information on what locks are open via the 'bzr info
5477
4777
[location]' command.
5481
brz break-lock brz+ssh://example.com/brz/foo
5482
brz break-lock --conf ~/.bazaar
4781
bzr break-lock bzr+ssh://example.com/bzr/foo
5485
4783
takes_args = ['location?']
5488
help='LOCATION is the directory where the config lock is.'),
5490
help='Do not ask for confirmation before breaking the lock.'),
5493
def run(self, location=None, config=False, force=False):
4785
def run(self, location=None, show=False):
5494
4786
if location is None:
5495
4787
location = u'.'
5497
ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
5499
{'breezy.lockdir.break': True})
5501
conf = _mod_config.LockableConfig(file_name=location)
5504
control, relpath = controldir.ControlDir.open_containing(location)
5506
control.break_lock()
5507
except NotImplementedError:
4788
control, relpath = bzrdir.BzrDir.open_containing(location)
4790
control.break_lock()
4791
except NotImplementedError:
5511
4795
class cmd_wait_until_signalled(Command):
5512
__doc__ = """Test helper for test_start_and_stop_brz_subprocess_send_signal.
4796
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
5514
4798
This just prints a line to signal when it is ready, then blocks on stdin.
5532
4816
help='Serve on stdin/out for use from inetd or sshd.'),
5533
4817
RegistryOption('protocol',
5534
4818
help="Protocol to serve.",
5535
lazy_registry=('breezy.transport', 'transport_server_registry'),
4819
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5536
4820
value_switches=True),
5538
help='Listen for connections on nominated address.', type=text_type),
5540
help='Listen for connections on nominated port. Passing 0 as '
5541
'the port number will result in a dynamically allocated '
5542
'port. The default port depends on the protocol.',
5544
custom_help('directory',
5545
help='Serve contents of this directory.'),
4822
help='Listen for connections on nominated port of the form '
4823
'[hostname:]portnumber. Passing 0 as the port number will '
4824
'result in a dynamically allocated port. The default port '
4825
'depends on the protocol.',
4828
help='Serve contents of this directory.',
5546
4830
Option('allow-writes',
5547
4831
help='By default the server is a readonly server. Supplying '
5548
4832
'--allow-writes enables write access to the contents of '
5549
'the served directory and below. Note that ``brz serve`` '
4833
'the served directory and below. Note that ``bzr serve`` '
5550
4834
'does not perform authentication, so unless some form of '
5551
4835
'external authentication is arranged supplying this '
5552
4836
'option leads to global uncontrolled write access to your '
5555
Option('client-timeout', type=float,
5556
help='Override the default idle client timeout (5min).'),
5559
def run(self, listen=None, port=None, inet=False, directory=None,
5560
allow_writes=False, protocol=None, client_timeout=None):
5561
from . import transport
4841
def get_host_and_port(self, port):
4842
"""Return the host and port to run the smart server on.
4844
If 'port' is None, None will be returned for the host and port.
4846
If 'port' has a colon in it, the string before the colon will be
4847
interpreted as the host.
4849
:param port: A string of the port to run the server on.
4850
:return: A tuple of (host, port), where 'host' is a host name or IP,
4851
and port is an integer TCP/IP port.
4854
if port is not None:
4856
host, port = port.split(':')
4860
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4862
from bzrlib.transport import get_transport, transport_server_registry
5562
4863
if directory is None:
5563
directory = osutils.getcwd()
4864
directory = os.getcwd()
5564
4865
if protocol is None:
5565
protocol = transport.transport_server_registry.get()
5566
url = transport.location_to_url(directory)
4866
protocol = transport_server_registry.get()
4867
host, port = self.get_host_and_port(port)
4868
url = urlutils.local_path_to_url(directory)
5567
4869
if not allow_writes:
5568
4870
url = 'readonly+' + url
5569
t = transport.get_transport_from_url(url)
5570
protocol(t, listen, port, inet, client_timeout)
4871
transport = get_transport(url)
4872
protocol(transport, host, port, inet)
5573
4875
class cmd_join(Command):
5574
__doc__ = """Combine a tree into its containing tree.
4876
"""Combine a tree into its containing tree.
5576
4878
This command requires the target tree to be in a rich-root format.
5578
4880
The TREE argument should be an independent tree, inside another tree, but
5579
not part of it. (Such trees can be produced by "brz split", but also by
5580
running "brz branch" with the target inside a tree.)
4881
not part of it. (Such trees can be produced by "bzr split", but also by
4882
running "bzr branch" with the target inside a tree.)
5582
The result is a combined tree, with the subtree no longer an independent
4884
The result is a combined tree, with the subtree no longer an independant
5583
4885
part. This is marked as a merge of the subtree into the containing tree,
5584
4886
and all history is preserved.
5593
4895
def run(self, tree, reference=False):
5594
from breezy.mutabletree import BadReferenceTarget
5595
4896
sub_tree = WorkingTree.open(tree)
5596
4897
parent_dir = osutils.dirname(sub_tree.basedir)
5597
4898
containing_tree = WorkingTree.open_containing(parent_dir)[0]
5598
4899
repo = containing_tree.branch.repository
5599
4900
if not repo.supports_rich_root():
5600
raise errors.BzrCommandError(gettext(
4901
raise errors.BzrCommandError(
5601
4902
"Can't join trees because %s doesn't support rich root data.\n"
5602
"You can use brz upgrade on the repository.")
4903
"You can use bzr upgrade on the repository."
5606
4907
containing_tree.add_reference(sub_tree)
5607
except BadReferenceTarget as e:
4908
except errors.BadReferenceTarget, e:
5608
4909
# XXX: Would be better to just raise a nicely printable
5609
4910
# exception from the real origin. Also below. mbp 20070306
5610
raise errors.BzrCommandError(
5611
gettext("Cannot join {0}. {1}").format(tree, e.reason))
4911
raise errors.BzrCommandError("Cannot join %s. %s" %
5614
4915
containing_tree.subsume(sub_tree)
5615
except errors.BadSubsumeSource as e:
5616
raise errors.BzrCommandError(
5617
gettext("Cannot join {0}. {1}").format(tree, e.reason))
4916
except errors.BadSubsumeSource, e:
4917
raise errors.BzrCommandError("Cannot join %s. %s" %
5620
4921
class cmd_split(Command):
5621
__doc__ = """Split a subdirectory of a tree into a separate tree.
4922
"""Split a subdirectory of a tree into a separate tree.
5623
4924
This command will produce a target tree in a format that supports
5624
4925
rich roots, like 'rich-root' or 'rich-root-pack'. These formats cannot be
5677
4977
diff='Normal unified diff.',
5678
4978
plain='No patch, just directive.'),
5679
4979
Option('sign', help='GPG-sign the directive.'), 'revision',
5680
Option('mail-to', type=text_type,
4980
Option('mail-to', type=str,
5681
4981
help='Instead of printing the directive, email to this address.'),
5682
Option('message', type=text_type, short_name='m',
4982
Option('message', type=str, short_name='m',
5683
4983
help='Message to use when committing this merge.')
5686
4986
encoding_type = 'exact'
5688
4988
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5689
sign=False, revision=None, mail_to=None, message=None,
5691
from .revision import ensure_null, NULL_REVISION
4989
sign=False, revision=None, mail_to=None, message=None):
4990
from bzrlib.revision import ensure_null, NULL_REVISION
5692
4991
include_patch, include_bundle = {
5693
4992
'plain': (False, False),
5694
4993
'diff': (True, False),
5695
4994
'bundle': (True, True),
5697
branch = Branch.open(directory)
4996
branch = Branch.open('.')
5698
4997
stored_submit_branch = branch.get_submit_branch()
5699
4998
if submit_branch is None:
5700
4999
submit_branch = stored_submit_branch
5838
5130
help='Branch to generate the submission from, '
5839
5131
'rather than the one containing the working directory.',
5840
5132
short_name='f',
5842
5134
Option('output', short_name='o',
5843
help='Write merge directive to this file or directory; '
5135
help='Write merge directive to this file; '
5844
5136
'use - for stdout.',
5846
5138
Option('strict',
5847
5139
help='Refuse to send if there are uncommitted changes in'
5848
5140
' the working tree, --no-strict disables the check.'),
5849
5141
Option('mail-to', help='Mail the request to this address.',
5853
Option('body', help='Body for the email.', type=text_type),
5145
Option('body', help='Body for the email.', type=unicode),
5854
5146
RegistryOption('format',
5855
5147
help='Use the specified output format.',
5856
lazy_registry=('breezy.send', 'format_registry')),
5148
lazy_registry=('bzrlib.send', 'format_registry')),
5859
5151
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5860
no_patch=False, revision=None, remember=None, output=None,
5152
no_patch=False, revision=None, remember=False, output=None,
5861
5153
format=None, mail_to=None, message=None, body=None,
5862
5154
strict=None, **kwargs):
5863
from .send import send
5155
from bzrlib.send import send
5864
5156
return send(submit_branch, revision, public_branch, remember,
5865
5157
format, no_bundle, no_patch, output,
5866
5158
kwargs.get('from', '.'), mail_to, message, body,
5954
5246
It is an error to give a tag name that already exists unless you pass
5955
5247
--force, in which case the tag is moved to point to the new revision.
5957
To rename a tag (change the name but keep it on the same revsion), run ``brz
5958
tag new-name -r tag:old-name`` and then ``brz tag --delete oldname``.
5960
If no tag name is specified it will be determined through the
5961
'automatic_tag_name' hook. This can e.g. be used to automatically tag
5962
upstream releases by reading configure.ac. See ``brz help hooks`` for
5249
To rename a tag (change the name but keep it on the same revsion), run ``bzr
5250
tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
5966
5253
_see_also = ['commit', 'tags']
5967
takes_args = ['tag_name?']
5254
takes_args = ['tag_name']
5968
5255
takes_options = [
5969
5256
Option('delete',
5970
5257
help='Delete this tag rather than placing it.',
5972
custom_help('directory',
5973
help='Branch in which to place the tag.'),
5260
help='Branch in which to place the tag.',
5974
5264
Option('force',
5975
5265
help='Replace existing tags.',
5980
def run(self, tag_name=None,
5270
def run(self, tag_name,
5986
5276
branch, relpath = Branch.open_containing(directory)
5987
self.add_cleanup(branch.lock_write().unlock)
5278
self.add_cleanup(branch.unlock)
5989
if tag_name is None:
5990
raise errors.BzrCommandError(gettext("No tag specified to delete."))
5991
5280
branch.tags.delete_tag(tag_name)
5992
note(gettext('Deleted tag %s.') % tag_name)
5281
self.outf.write('Deleted tag %s.\n' % tag_name)
5995
5284
if len(revision) != 1:
5996
raise errors.BzrCommandError(gettext(
5285
raise errors.BzrCommandError(
5997
5286
"Tags can only be placed on a single revision, "
5999
5288
revision_id = revision[0].as_revision_id(branch)
6001
5290
revision_id = branch.last_revision()
6002
if tag_name is None:
6003
tag_name = branch.automatic_tag_name(revision_id)
6004
if tag_name is None:
6005
raise errors.BzrCommandError(gettext(
6006
"Please specify a tag name."))
6008
existing_target = branch.tags.lookup_tag(tag_name)
6009
except errors.NoSuchTag:
6010
existing_target = None
6011
if not force and existing_target not in (None, revision_id):
5291
if (not force) and branch.tags.has_tag(tag_name):
6012
5292
raise errors.TagAlreadyExists(tag_name)
6013
if existing_target == revision_id:
6014
note(gettext('Tag %s already exists for that revision.') % tag_name)
6016
branch.tags.set_tag(tag_name, revision_id)
6017
if existing_target is None:
6018
note(gettext('Created tag %s.') % tag_name)
6020
note(gettext('Updated tag %s.') % tag_name)
5293
branch.tags.set_tag(tag_name, revision_id)
5294
self.outf.write('Created tag %s.\n' % tag_name)
6023
5297
class cmd_tags(Command):
6024
__doc__ = """List tags.
6026
5300
This command shows a table of tag names and the revisions they reference.
6029
5303
_see_also = ['tag']
6030
5304
takes_options = [
6031
custom_help('directory',
6032
help='Branch whose tags should be displayed.'),
6033
RegistryOption('sort',
5306
help='Branch whose tags should be displayed.',
5310
RegistryOption.from_kwargs('sort',
6034
5311
'Sort tags by different criteria.', title='Sorting',
6035
lazy_registry=('breezy.tag', 'tag_sort_methods')
5312
alpha='Sort tags lexicographically (default).',
5313
time='Sort tags chronologically.',
6041
5319
@display_command
6042
def run(self, directory='.', sort=None, show_ids=False, revision=None):
6043
from .tag import tag_sort_methods
6044
5326
branch, relpath = Branch.open_containing(directory)
6046
tags = list(viewitems(branch.tags.get_tag_dict()))
5328
tags = branch.tags.get_tag_dict().items()
6050
self.add_cleanup(branch.lock_read().unlock)
5333
self.add_cleanup(branch.unlock)
6052
# Restrict to the specified range
6053
tags = self._tags_for_range(branch, revision)
6055
sort = tag_sort_methods.get()
5335
graph = branch.repository.get_graph()
5336
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5337
revid1, revid2 = rev1.rev_id, rev2.rev_id
5338
# only show revisions between revid1 and revid2 (inclusive)
5339
tags = [(tag, revid) for tag, revid in tags if
5340
graph.is_between(revid, revid1, revid2)]
5343
elif sort == 'time':
5345
for tag, revid in tags:
5347
revobj = branch.repository.get_revision(revid)
5348
except errors.NoSuchRevision:
5349
timestamp = sys.maxint # place them at the end
5351
timestamp = revobj.timestamp
5352
timestamps[revid] = timestamp
5353
tags.sort(key=lambda x: timestamps[x[1]])
6057
5354
if not show_ids:
6058
5355
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
6059
5356
for index, (tag, revid) in enumerate(tags):
6072
5367
for tag, revspec in tags:
6073
5368
self.outf.write('%-20s %s\n' % (tag, revspec))
6075
def _tags_for_range(self, branch, revision):
6077
rev1, rev2 = _get_revision_range(revision, branch, self.name())
6078
revid1, revid2 = rev1.rev_id, rev2.rev_id
6079
# _get_revision_range will always set revid2 if it's not specified.
6080
# If revid1 is None, it means we want to start from the branch
6081
# origin which is always a valid ancestor. If revid1 == revid2, the
6082
# ancestry check is useless.
6083
if revid1 and revid1 != revid2:
6084
# FIXME: We really want to use the same graph than
6085
# branch.iter_merge_sorted_revisions below, but this is not
6086
# easily available -- vila 2011-09-23
6087
if branch.repository.get_graph().is_ancestor(revid2, revid1):
6088
# We don't want to output anything in this case...
6090
# only show revisions between revid1 and revid2 (inclusive)
6091
tagged_revids = branch.tags.get_reverse_tag_dict()
6093
for r in branch.iter_merge_sorted_revisions(
6094
start_revision_id=revid2, stop_revision_id=revid1,
6095
stop_rule='include'):
6096
revid_tags = tagged_revids.get(r[0], None)
6098
found.extend([(tag, r[0]) for tag in revid_tags])
6102
5371
class cmd_reconfigure(Command):
6103
__doc__ = """Reconfigure the type of a brz directory.
5372
"""Reconfigure the type of a bzr directory.
6105
5374
A target configuration must be specified.
6117
5386
takes_args = ['location?']
6118
5387
takes_options = [
6119
5388
RegistryOption.from_kwargs(
6122
help='The relation between branch and tree.',
5390
title='Target type',
5391
help='The type to reconfigure the directory to.',
6123
5392
value_switches=True, enum_switch=False,
6124
5393
branch='Reconfigure to be an unbound branch with no working tree.',
6125
5394
tree='Reconfigure to be an unbound branch with a working tree.',
6126
5395
checkout='Reconfigure to be a bound branch with a working tree.',
6127
5396
lightweight_checkout='Reconfigure to be a lightweight'
6128
5397
' checkout (with no local history).',
6130
RegistryOption.from_kwargs(
6132
title='Repository type',
6133
help='Location fo the repository.',
6134
value_switches=True, enum_switch=False,
6135
5398
standalone='Reconfigure to be a standalone branch '
6136
5399
'(i.e. stop using shared repository).',
6137
5400
use_shared='Reconfigure to use a shared repository.',
6139
RegistryOption.from_kwargs(
6141
title='Trees in Repository',
6142
help='Whether new branches in the repository have trees.',
6143
value_switches=True, enum_switch=False,
6144
5401
with_trees='Reconfigure repository to create '
6145
5402
'working trees on branches by default.',
6146
5403
with_no_trees='Reconfigure repository to not create '
6147
5404
'working trees on branches by default.'
6149
Option('bind-to', help='Branch to bind checkout to.', type=text_type),
5406
Option('bind-to', help='Branch to bind checkout to.', type=str),
6150
5407
Option('force',
6151
5408
help='Perform reconfiguration even if local changes'
6152
5409
' will be lost.'),
6153
5410
Option('stacked-on',
6154
5411
help='Reconfigure a branch to be stacked on another branch.',
6157
5414
Option('unstacked',
6158
5415
help='Reconfigure a branch to be unstacked. This '
6173
5430
# At the moment you can use --stacked-on and a different
6174
5431
# reconfiguration shape at the same time; there seems no good reason
6176
if (tree_type is None and
6177
repository_type is None and
6178
repository_trees is None):
5433
if target_type is None:
6179
5434
if stacked_on or unstacked:
6182
raise errors.BzrCommandError(gettext('No target configuration '
6184
reconfiguration = None
6185
if tree_type == 'branch':
5437
raise errors.BzrCommandError('No target configuration '
5439
elif target_type == 'branch':
6186
5440
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
6187
elif tree_type == 'tree':
5441
elif target_type == 'tree':
6188
5442
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
6189
elif tree_type == 'checkout':
5443
elif target_type == 'checkout':
6190
5444
reconfiguration = reconfigure.Reconfigure.to_checkout(
6191
5445
directory, bind_to)
6192
elif tree_type == 'lightweight-checkout':
5446
elif target_type == 'lightweight-checkout':
6193
5447
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
6194
5448
directory, bind_to)
6196
reconfiguration.apply(force)
6197
reconfiguration = None
6198
if repository_type == 'use-shared':
5449
elif target_type == 'use-shared':
6199
5450
reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
6200
elif repository_type == 'standalone':
5451
elif target_type == 'standalone':
6201
5452
reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
6203
reconfiguration.apply(force)
6204
reconfiguration = None
6205
if repository_trees == 'with-trees':
5453
elif target_type == 'with-trees':
6206
5454
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
6207
5455
directory, True)
6208
elif repository_trees == 'with-no-trees':
5456
elif target_type == 'with-no-trees':
6209
5457
reconfiguration = reconfigure.Reconfigure.set_repository_trees(
6210
5458
directory, False)
6212
reconfiguration.apply(force)
6213
reconfiguration = None
5459
reconfiguration.apply(force)
6216
5462
class cmd_switch(Command):
6217
__doc__ = """Set the branch of a checkout and update.
5463
"""Set the branch of a checkout and update.
6219
5465
For lightweight checkouts, this changes the branch being referenced.
6220
5466
For heavyweight checkouts, this checks that there are no local commits
6239
5485
takes_args = ['to_location?']
6240
takes_options = ['directory',
5486
takes_options = [Option('force',
6242
5487
help='Switch even if local commits will be lost.'),
6244
5489
Option('create-branch', short_name='b',
6245
5490
help='Create the target branch from this one before'
6246
5491
' switching to it.'),
6248
help='Store and restore uncommitted changes in the'
6252
5494
def run(self, to_location=None, force=False, create_branch=False,
6253
revision=None, directory=u'.', store=False):
6254
from . import switch
6255
tree_location = directory
5496
from bzrlib import switch
6256
5498
revision = _get_one_revision('switch', revision)
6257
possible_transports = []
6258
control_dir = controldir.ControlDir.open_containing(tree_location,
6259
possible_transports=possible_transports)[0]
5499
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
6260
5500
if to_location is None:
6261
5501
if revision is None:
6262
raise errors.BzrCommandError(gettext('You must supply either a'
6263
' revision or a location'))
6264
to_location = tree_location
5502
raise errors.BzrCommandError('You must supply either a'
5503
' revision or a location')
6266
branch = control_dir.open_branch(
6267
possible_transports=possible_transports)
5506
branch = control_dir.open_branch()
6268
5507
had_explicit_nick = branch.get_config().has_explicit_nickname()
6269
5508
except errors.NotBranchError:
6271
5510
had_explicit_nick = False
6272
5511
if create_branch:
6273
5512
if branch is None:
6274
raise errors.BzrCommandError(
6275
gettext('cannot create branch without source branch'))
6276
to_location = lookup_new_sibling_branch(control_dir, to_location,
6277
possible_transports=possible_transports)
6278
to_branch = branch.controldir.sprout(to_location,
6279
possible_transports=possible_transports,
6280
source_branch=branch).open_branch()
5513
raise errors.BzrCommandError('cannot create branch without'
5515
to_location = directory_service.directories.dereference(
5517
if '/' not in to_location and '\\' not in to_location:
5518
# This path is meant to be relative to the existing branch
5519
this_url = self._get_branch_location(control_dir)
5520
to_location = urlutils.join(this_url, '..', to_location)
5521
to_branch = branch.bzrdir.sprout(to_location,
5522
possible_transports=[branch.bzrdir.root_transport],
5523
source_branch=branch).open_branch()
6283
to_branch = Branch.open(to_location,
6284
possible_transports=possible_transports)
5526
to_branch = Branch.open(to_location)
6285
5527
except errors.NotBranchError:
6286
to_branch = open_sibling_branch(control_dir, to_location,
6287
possible_transports=possible_transports)
5528
this_url = self._get_branch_location(control_dir)
5529
to_branch = Branch.open(
5530
urlutils.join(this_url, '..', to_location))
6288
5531
if revision is not None:
6289
5532
revision = revision.as_revision_id(to_branch)
6291
switch.switch(control_dir, to_branch, force, revision_id=revision,
6292
store_uncommitted=store)
6293
except controldir.BranchReferenceLoop:
6294
raise errors.BzrCommandError(
6295
gettext('switching would create a branch reference loop. '
6296
'Use the "bzr up" command to switch to a '
6297
'different revision.'))
5533
switch.switch(control_dir, to_branch, force, revision_id=revision)
6298
5534
if had_explicit_nick:
6299
5535
branch = control_dir.open_branch() #get the new branch!
6300
5536
branch.nick = to_branch.nick
6301
note(gettext('Switched to branch: %s'),
5537
note('Switched to branch: %s',
6302
5538
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5540
def _get_branch_location(self, control_dir):
5541
"""Return location of branch for this control dir."""
5543
this_branch = control_dir.open_branch()
5544
# This may be a heavy checkout, where we want the master branch
5545
master_location = this_branch.get_bound_location()
5546
if master_location is not None:
5547
return master_location
5548
# If not, use a local sibling
5549
return this_branch.base
5550
except errors.NotBranchError:
5551
format = control_dir.find_branch_format()
5552
if getattr(format, 'get_reference', None) is not None:
5553
return format.get_reference(control_dir)
5555
return control_dir.root_transport.base
6306
5558
class cmd_view(Command):
6307
__doc__ = """Manage filtered views.
5559
"""Manage filtered views.
6309
5561
Views provide a mask over the tree so that users can focus on
6310
5562
a subset of a tree when doing their work. After creating a view,
6393
tree, file_list = WorkingTree.open_containing_paths(file_list,
5645
tree, file_list = tree_files(file_list, apply_view=False)
6395
5646
current_view, view_dict = tree.views.get_view_info()
6396
5647
if name is None:
6397
5648
name = current_view
6400
raise errors.BzrCommandError(gettext(
6401
"Both --delete and a file list specified"))
5651
raise errors.BzrCommandError(
5652
"Both --delete and a file list specified")
6403
raise errors.BzrCommandError(gettext(
6404
"Both --delete and --switch specified"))
5654
raise errors.BzrCommandError(
5655
"Both --delete and --switch specified")
6406
5657
tree.views.set_view_info(None, {})
6407
self.outf.write(gettext("Deleted all views.\n"))
5658
self.outf.write("Deleted all views.\n")
6408
5659
elif name is None:
6409
raise errors.BzrCommandError(gettext("No current view to delete"))
5660
raise errors.BzrCommandError("No current view to delete")
6411
5662
tree.views.delete_view(name)
6412
self.outf.write(gettext("Deleted '%s' view.\n") % name)
5663
self.outf.write("Deleted '%s' view.\n" % name)
6415
raise errors.BzrCommandError(gettext(
6416
"Both --switch and a file list specified"))
5666
raise errors.BzrCommandError(
5667
"Both --switch and a file list specified")
6418
raise errors.BzrCommandError(gettext(
6419
"Both --switch and --all specified"))
5669
raise errors.BzrCommandError(
5670
"Both --switch and --all specified")
6420
5671
elif switch == 'off':
6421
5672
if current_view is None:
6422
raise errors.BzrCommandError(gettext("No current view to disable"))
5673
raise errors.BzrCommandError("No current view to disable")
6423
5674
tree.views.set_view_info(None, view_dict)
6424
self.outf.write(gettext("Disabled '%s' view.\n") % (current_view))
5675
self.outf.write("Disabled '%s' view.\n" % (current_view))
6426
5677
tree.views.set_view_info(switch, view_dict)
6427
5678
view_str = views.view_display_str(tree.views.lookup_view())
6428
self.outf.write(gettext("Using '{0}' view: {1}\n").format(switch, view_str))
5679
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
6431
self.outf.write(gettext('Views defined:\n'))
5682
self.outf.write('Views defined:\n')
6432
5683
for view in sorted(view_dict):
6433
5684
if view == current_view:
6437
5688
view_str = views.view_display_str(view_dict[view])
6438
5689
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
6440
self.outf.write(gettext('No views defined.\n'))
5691
self.outf.write('No views defined.\n')
6441
5692
elif file_list:
6442
5693
if name is None:
6443
5694
# No name given and no current view set
6445
5696
elif name == 'off':
6446
raise errors.BzrCommandError(gettext(
6447
"Cannot change the 'off' pseudo view"))
5697
raise errors.BzrCommandError(
5698
"Cannot change the 'off' pseudo view")
6448
5699
tree.views.set_view(name, sorted(file_list))
6449
5700
view_str = views.view_display_str(tree.views.lookup_view())
6450
self.outf.write(gettext("Using '{0}' view: {1}\n").format(name, view_str))
5701
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
6452
5703
# list the files
6453
5704
if name is None:
6454
5705
# No name given and no current view set
6455
self.outf.write(gettext('No current view.\n'))
5706
self.outf.write('No current view.\n')
6457
5708
view_str = views.view_display_str(tree.views.lookup_view(name))
6458
self.outf.write(gettext("'{0}' view is: {1}\n").format(name, view_str))
5709
self.outf.write("'%s' view is: %s\n" % (name, view_str))
6461
5712
class cmd_hooks(Command):
6462
__doc__ = """Show hooks."""
6475
5726
self.outf.write(" %s\n" %
6476
5727
(some_hooks.get_hook_name(hook),))
6478
self.outf.write(gettext(" <no hooks installed>\n"))
6481
class cmd_remove_branch(Command):
6482
__doc__ = """Remove a branch.
6484
This will remove the branch from the specified location but
6485
will keep any working tree or repository in place.
6489
Remove the branch at repo/trunk::
6491
brz remove-branch repo/trunk
6495
takes_args = ["location?"]
6497
takes_options = ['directory',
6498
Option('force', help='Remove branch even if it is the active branch.')]
6500
aliases = ["rmbranch"]
6502
def run(self, directory=None, location=None, force=False):
6503
br = open_nearby_branch(near=directory, location=location)
6504
if not force and br.controldir.has_workingtree():
6506
active_branch = br.controldir.open_branch(name="")
6507
except errors.NotBranchError:
6508
active_branch = None
6509
if (active_branch is not None and
6510
br.control_url == active_branch.control_url):
6511
raise errors.BzrCommandError(
6512
gettext("Branch is active. Use --force to remove it."))
6513
br.controldir.destroy_branch(br.name)
5729
self.outf.write(" <no hooks installed>\n")
6516
5732
class cmd_shelve(Command):
6517
__doc__ = """Temporarily set aside some changes from the current tree.
5733
"""Temporarily set aside some changes from the current tree.
6519
5735
Shelve allows you to temporarily put changes you've made "on the shelf",
6520
5736
ie. out of the way, until a later time when you can bring them back from
6537
5753
You can put multiple items on the shelf, and by default, 'unshelve' will
6538
5754
restore the most recently shelved changes.
6540
For complicated changes, it is possible to edit the changes in a separate
6541
editor program to decide what the file remaining in the working copy
6542
should look like. To do this, add the configuration option
6544
change_editor = PROGRAM @new_path @old_path
6546
where @new_path is replaced with the path of the new version of the
6547
file and @old_path is replaced with the path of the old version of
6548
the file. The PROGRAM should save the new file with the desired
6549
contents of the file in the working tree.
6553
5757
takes_args = ['file*']
6555
5759
takes_options = [
6558
5761
Option('all', help='Shelve all changes.'),
6560
5763
RegistryOption('writer', 'Method to use for writing diffs.',
6561
breezy.option.diff_writer_registry,
5764
bzrlib.option.diff_writer_registry,
6562
5765
value_switches=True, enum_switch=False),
6564
5767
Option('list', help='List shelved changes.'),
6565
5768
Option('destroy',
6566
5769
help='Destroy removed changes instead of shelving them.'),
6568
_see_also = ['unshelve', 'configuration']
5771
_see_also = ['unshelve']
6570
5773
def run(self, revision=None, all=False, file_list=None, message=None,
6571
writer=None, list=False, destroy=False, directory=None):
5774
writer=None, list=False, destroy=False):
6573
return self.run_for_list(directory=directory)
6574
from .shelf_ui import Shelver
5776
return self.run_for_list()
5777
from bzrlib.shelf_ui import Shelver
6575
5778
if writer is None:
6576
writer = breezy.option.diff_writer_registry.get()
5779
writer = bzrlib.option.diff_writer_registry.get()
6578
shelver = Shelver.from_args(writer(self.outf), revision, all,
6579
file_list, message, destroy=destroy, directory=directory)
5781
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5782
file_list, message, destroy=destroy)
6651
5852
To check what clean-tree will do, use --dry-run.
6653
takes_options = ['directory',
6654
Option('ignored', help='Delete all ignored files.'),
6655
Option('detritus', help='Delete conflict files, merge and revert'
5854
takes_options = [Option('ignored', help='Delete all ignored files.'),
5855
Option('detritus', help='Delete conflict files, merge'
6656
5856
' backups, and failed selftest dirs.'),
6657
5857
Option('unknown',
6658
help='Delete files unknown to brz (default).'),
5858
help='Delete files unknown to bzr (default).'),
6659
5859
Option('dry-run', help='Show files to delete instead of'
6660
5860
' deleting them.'),
6661
5861
Option('force', help='Do not prompt before deleting.')]
6662
5862
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6663
force=False, directory=u'.'):
6664
from .clean_tree import clean_tree
5864
from bzrlib.clean_tree import clean_tree
6665
5865
if not (unknown or ignored or detritus):
6669
clean_tree(directory, unknown=unknown, ignored=ignored,
6670
detritus=detritus, dry_run=dry_run, no_prompt=force)
5869
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5870
dry_run=dry_run, no_prompt=force)
6673
5873
class cmd_reference(Command):
6674
__doc__ = """list, view and set branch locations for nested trees.
5874
"""list, view and set branch locations for nested trees.
6676
5876
If no arguments are provided, lists the branch locations for nested trees.
6677
5877
If one argument is provided, display the branch location for that tree.
6687
5887
if path is not None:
6688
5888
branchdir = path
6689
5889
tree, branch, relpath =(
6690
controldir.ControlDir.open_containing_tree_or_branch(branchdir))
5890
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
6691
5891
if path is not None:
6693
5893
if tree is None:
6694
5894
tree = branch.basis_tree()
6695
5895
if path is None:
6696
info = viewitems(branch._get_all_reference_info())
5896
info = branch._get_all_reference_info().iteritems()
6697
5897
self._display_reference_info(tree, branch, info)
6699
if not tree.is_versioned(path):
5899
file_id = tree.path2id(path)
6700
5901
raise errors.NotVersionedError(path)
6701
5902
if location is None:
6702
info = [(path, branch.get_reference_info(path))]
5903
info = [(file_id, branch.get_reference_info(file_id))]
6703
5904
self._display_reference_info(tree, branch, info)
6705
branch.set_reference_info(
6706
path, location, file_id=tree.path2id(path))
5906
branch.set_reference_info(file_id, path, location)
6708
5908
def _display_reference_info(self, tree, branch, info):
6710
for path, (location, file_id) in info:
5910
for file_id, (path, location) in info:
5912
path = tree.id2path(file_id)
5913
except errors.NoSuchId:
6711
5915
ref_list.append((path, location))
6712
5916
for path, location in sorted(ref_list):
6713
5917
self.outf.write('%s %s\n' % (path, location))
6716
class cmd_export_pot(Command):
6717
__doc__ = """Export command helps and error messages in po format."""
6720
takes_options = [Option('plugin',
6721
help='Export help text from named command '\
6722
'(defaults to all built in commands).',
6724
Option('include-duplicates',
6725
help='Output multiple copies of the same msgid '
6726
'string if it appears more than once.'),
6729
def run(self, plugin=None, include_duplicates=False):
6730
from .export_pot import export_pot
6731
export_pot(self.outf, plugin, include_duplicates)
6734
class cmd_import(Command):
6735
__doc__ = """Import sources from a directory, tarball or zip file
6737
This command will import a directory, tarball or zip file into a bzr
6738
tree, replacing any versioned files already present. If a directory is
6739
specified, it is used as the target. If the directory does not exist, or
6740
is not versioned, it is created.
6742
Tarballs may be gzip or bzip2 compressed. This is autodetected.
6744
If the tarball or zip has a single root directory, that directory is
6745
stripped when extracting the tarball. This is not done for directories.
6748
takes_args = ['source', 'tree?']
6750
def run(self, source, tree=None):
6751
from .upstream_import import do_import
6752
do_import(source, tree)
6755
class cmd_link_tree(Command):
6756
__doc__ = """Hardlink matching files to another tree.
6758
Only files with identical content and execute bit will be linked.
6761
takes_args = ['location']
6763
def run(self, location):
6764
from .transform import link_tree
6765
target_tree = WorkingTree.open_containing(".")[0]
6766
source_tree = WorkingTree.open(location)
6767
with target_tree.lock_write(), source_tree.lock_read():
6768
link_tree(target_tree, source_tree)
6771
class cmd_fetch_ghosts(Command):
6772
__doc__ = """Attempt to retrieve ghosts from another branch.
6774
If the other branch is not supplied, the last-pulled branch is used.
6778
aliases = ['fetch-missing']
6779
takes_args = ['branch?']
6780
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
6782
def run(self, branch=None, no_fix=False):
6783
from .fetch_ghosts import GhostFetcher
6784
installed, failed = GhostFetcher.from_cmdline(branch).run()
6785
if len(installed) > 0:
6786
self.outf.write("Installed:\n")
6787
for rev in installed:
6788
self.outf.write(rev + "\n")
6790
self.outf.write("Still missing:\n")
6792
self.outf.write(rev + "\n")
6793
if not no_fix and len(installed) > 0:
6794
cmd_reconcile().run(".")
6797
def _register_lazy_builtins():
6798
# register lazy builtins from other modules; called at startup and should
6799
# be only called once.
6800
for (name, aliases, module_name) in [
6801
('cmd_bisect', [], 'breezy.bisect'),
6802
('cmd_bundle_info', [], 'breezy.bundle.commands'),
6803
('cmd_config', [], 'breezy.config'),
6804
('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
6805
('cmd_version_info', [], 'breezy.cmd_version_info'),
6806
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
6807
('cmd_conflicts', [], 'breezy.conflicts'),
6808
('cmd_ping', [], 'breezy.bzr.smart.ping'),
6809
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
6810
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
6811
('cmd_test_script', [], 'breezy.cmd_test_script'),
6813
builtin_command_registry.register_lazy(name, aliases, module_name)
5920
# these get imported and then picked up by the scan for cmd_*
5921
# TODO: Some more consistent way to split command definitions across files;
5922
# we do need to load at least some information about them to know of
5923
# aliases. ideally we would avoid loading the implementation until the
5924
# details were needed.
5925
from bzrlib.cmd_version_info import cmd_version_info
5926
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
5927
from bzrlib.bundle.commands import (
5930
from bzrlib.foreign import cmd_dpush
5931
from bzrlib.sign_my_commits import cmd_sign_my_commits