25
from bzrlib.lazy_import import lazy_import
26
lazy_import(globals(), """
27
from bzrlib import help, urlutils
31
from version import version_info, __version__
32
from command import BzrToolsCommand
26
__version__ = '0.14.0'
29
version_info = tuple(int(n) for n in __version__.split('.'))
32
def check_bzrlib_version(desired):
33
"""Check that bzrlib is compatible.
35
If version is < bzrtools version, assume incompatible.
36
If version == bzrtools version, assume completely compatible
37
If version == bzrtools version + 1, assume compatible, with deprecations
38
Otherwise, assume incompatible.
40
desired_plus = (desired[0], desired[1]+1)
41
bzrlib_version = bzrlib.version_info[:2]
42
if bzrlib_version == desired:
45
from bzrlib.trace import warning
47
# get the message out any way we can
48
from warnings import warn as warning
49
if bzrlib_version < desired:
50
warning('Installed bzr version %s is too old to be used with bzrtools'
51
' %s.' % (bzrlib.__version__, __version__))
52
# Not using BzrNewError, because it may not exist.
53
raise Exception, ('Version mismatch', version_info)
55
warning('Bzrtools is not up to date with installed bzr version %s.'
56
' \nThere should be a newer version available, e.g. %i.%i.'
57
% (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
58
if bzrlib_version != desired_plus:
59
raise Exception, 'Version mismatch'
62
check_bzrlib_version(version_info[:2])
33
65
from errors import CommandError, NoPyBaz
34
66
from patchsource import BzrPatchSource
67
from shelf import Shelf
38
71
import bzrlib.builtins
39
72
import bzrlib.commands
40
from bzrlib.branch import Branch
41
from bzrlib.bzrdir import BzrDir
42
73
from bzrlib.commands import get_cmd_object
43
74
from bzrlib.errors import BzrCommandError
75
from bzrlib.help import command_usage
44
76
import bzrlib.ignores
45
from bzrlib.trace import note
46
77
from bzrlib.option import Option
47
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__),
78
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__),
51
from command import BzrToolsCommand
53
83
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
56
class cmd_clean_tree(BzrToolsCommand):
86
class cmd_clean_tree(bzrlib.commands.Command):
57
87
"""Remove unwanted files from working tree.
59
89
By default, only unknown files, not ignored files, are deleted. Versioned
69
99
To check what clean-tree will do, use --dry-run.
71
takes_options = [Option('ignored', help='Delete all ignored files.'),
72
Option('detritus', help='Delete conflict files, merge'
73
' backups, and failed selftest dirs.'),
75
help='Delete files unknown to bzr (default).'),
76
Option('dry-run', help='Show files to delete instead of'
101
takes_options = [Option('ignored', help='delete all ignored files.'),
102
Option('detritus', help='delete conflict files, merge'
103
' backups, and failed selftest dirs.'),
105
help='delete files unknown to bzr. (default)'),
106
Option('dry-run', help='show files to delete instead of'
77
107
' deleting them.')]
78
108
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False):
79
109
from clean_tree import clean_tree
118
148
If available, rsvg is used to antialias PNG and JPEG output, but this can
119
149
be disabled with --no-antialias.
121
takes_args = ['file', 'merge_branch?']
122
takes_options = [Option('no-collapse', help="Do not skip simple nodes."),
151
takes_args = ['branch', 'file']
152
takes_options = [Option('no-collapse', help="Do not skip simple nodes"),
123
153
Option('no-antialias',
124
help="Do not use rsvg to produce antialiased output."),
125
Option('merge-branch', type=str,
126
help="Use this branch to calcuate a merge base."),
154
help="Do not use rsvg to produce antialiased output"),
155
Option('merge-branch', type=str,
156
help="Use this branch to calcuate a merge base"),
127
157
Option('cluster', help="Use clustered output."),
128
Option('max-distance',
129
help="Show no nodes farther than this.", type=int),
131
help='Source branch to use (default is current'
136
def run(self, file, merge_branch=None, no_collapse=False,
137
no_antialias=False, cluster=False, max_distance=100,
139
if max_distance == -1:
158
Option('max-distance', help="Show no nodes farther than this",
160
def run(self, branch, file, no_collapse=False, no_antialias=False,
161
merge_branch=None, cluster=False, max_distance=None):
143
164
ranking = "cluster"
145
166
ranking = "forced"
146
graph.write_ancestry_file(directory, file, not no_collapse,
147
not no_antialias, merge_branch, ranking,
167
graph.write_ancestry_file(branch, file, not no_collapse,
168
not no_antialias, merge_branch, ranking,
148
169
max_distance=max_distance)
151
class cmd_fetch_ghosts(BzrToolsCommand):
172
class cmd_fetch_ghosts(bzrlib.commands.Command):
152
173
"""Attempt to retrieve ghosts from another branch.
153
174
If the other branch is not supplied, the last-pulled branch is used.
155
176
aliases = ['fetch-missing']
156
177
takes_args = ['branch?']
157
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
178
takes_options = [Option('no-fix')]
158
179
def run(self, branch=None, no_fix=False):
159
180
from fetch_ghosts import fetch_ghosts
160
181
fetch_ghosts(branch, no_fix)
163
184
each file name found in the patch file."""
166
class cmd_patch(BzrToolsCommand):
187
class cmd_patch(bzrlib.commands.Command):
167
188
"""Apply a named patch to the current tree.
169
190
takes_args = ['filename?']
170
takes_options = [Option('strip', type=int, help=strip_help),
171
Option('silent', help='Suppress chatter.')]
172
def run(self, filename=None, strip=None, silent=False):
191
takes_options = [Option('strip', type=int, help=strip_help)]
192
def run(self, filename=None, strip=None):
173
193
from patch import patch
174
194
from bzrlib.workingtree import WorkingTree
175
195
wt = WorkingTree.open_containing('.')[0]
176
196
if strip is None:
178
return patch(wt, filename, strip, silent)
181
class cmd_shelve(BzrToolsCommand):
198
return patch(wt, filename, strip)
201
class cmd_shelve(bzrlib.commands.Command):
182
202
"""Temporarily set aside some changes from the current tree.
184
204
Shelve allows you to temporarily put changes you've made "on the shelf",
211
231
takes_args = ['file*']
212
takes_options = [Option('message',
213
help='A message to associate with the shelved changes.',
214
short_name='m', type=unicode),
216
Option('all', help='Shelve all changes without prompting.'),
217
Option('no-color', help='Never display changes in color.')]
232
takes_options = ['message', 'revision',
233
Option('all', help='Shelve all changes without prompting'),
234
Option('no-color', help='Never display changes in color')]
219
236
def run(self, all=False, file_list=None, message=None, revision=None,
348
362
See 'shelve' for more information.
350
364
takes_options = [
351
Option('all', help='Unshelve all changes without prompting.'),
352
Option('force', help='Force unshelving even if errors occur.'),
353
Option('no-color', help='Never display changes in color.')
365
Option('all', help='Unshelve all changes without prompting'),
366
Option('force', help='Force unshelving even if errors occur'),
367
Option('no-color', help='Never display changes in color')
355
369
takes_args = ['patch?']
356
370
def run(self, patch=None, all=False, force=False, no_color=False):
357
371
source = BzrPatchSource()
358
s = shelf.Shelf(source.base)
372
s = Shelf(source.base)
359
373
s.unshelve(source, patch, all, force, no_color)
363
class cmd_shell(BzrToolsCommand):
377
class cmd_shell(bzrlib.commands.Command):
364
378
"""Begin an interactive shell tailored for bzr.
365
379
Bzr commands can be used without typing bzr first, and will be run natively
366
380
when possible. Tab completion is tailored for bzr. The shell prompt shows
408
422
If --branch is specified, the branch will be deleted too, but only if the
409
423
the branch has no new commits (relative to its parent).
411
takes_options = [Option("branch", help="Remove associated branch from"
413
Option('force', help='Delete tree even if contents are'
425
takes_options = [Option("branch", help="Remove associtated branch from"
415
427
takes_args = ["checkout"]
416
def run(self, checkout, branch=False, force=False):
428
def run(self, checkout, branch=False):
417
429
from zap import zap
418
return zap(checkout, remove_branch=branch, allow_modified=force)
421
class cmd_cbranch(BzrToolsCommand):
430
return zap(checkout, remove_branch=branch)
433
class cmd_cbranch(bzrlib.commands.Command):
423
435
Create a new checkout, associated with a new repository branch.
425
437
When you cbranch, bzr looks up a target location in locations.conf, and
426
438
creates the branch there.
431
443
cbranch_target:policy = appendpath
433
445
This will mean that if you run "bzr cbranch foo/bar foo/baz" in the
434
working directory root, the branch will be created in
446
working directory root, the branch will be created in
435
447
"/branch_root/foo/baz"
437
449
NOTE: cbranch also supports "cbranch_root", but that behaviour is
440
takes_options = [Option("lightweight",
441
help="Create a lightweight checkout."), 'revision',
442
Option('files-from', type=unicode,
443
help='Accelerate checkout using files from this'
452
takes_options = [Option("lightweight",
453
help="Create a lightweight checkout"), 'revision']
445
454
takes_args = ["source", "target?"]
446
def run(self, source, target=None, lightweight=False, revision=None,
455
def run(self, source, target=None, lightweight=False, revision=None):
448
456
from cbranch import cbranch
449
return cbranch(source, target, lightweight=lightweight,
450
revision=revision, files_from=files_from)
453
class cmd_branches(BzrToolsCommand):
457
return cbranch(source, target, lightweight=lightweight,
461
class cmd_branches(bzrlib.commands.Command):
454
462
"""Scan a location for branches"""
455
463
takes_args = ["location?"]
456
464
def run(self, location=None):
457
465
from branches import branches
458
466
return branches(location)
460
class cmd_trees(BzrToolsCommand):
461
"""Scan a location for trees"""
462
takes_args = ['location?']
463
def run(self, location='.'):
464
from bzrlib.workingtree import WorkingTree
465
from bzrlib.transport import get_transport
466
t = get_transport(location)
467
for tree in WorkingTree.find_trees(location):
468
self.outf.write('%s\n' % t.relpath(
469
tree.bzrdir.root_transport.base))
471
class cmd_multi_pull(BzrToolsCommand):
469
class cmd_multi_pull(bzrlib.commands.Command):
472
470
"""Pull all the branches under a location, e.g. a repository.
474
472
Both branches present in the directory and the branches of checkouts are
477
475
takes_args = ["location?"]
478
476
def run(self, location=None):
477
from bzrlib.branch import Branch
479
478
from bzrlib.transport import get_transport
480
479
from bzrtools import iter_branch_tree
481
480
if location is None:
483
482
t = get_transport(location)
484
possible_transports = []
485
483
if not t.listable():
486
484
print "Can't list this type of location."
504
502
print "Pulling %s from %s" % (relpath, parent)
506
branch_t = get_transport(parent, possible_transports)
507
pullable.pull(Branch.open_from_transport(branch_t))
504
pullable.pull(Branch.open(parent))
508
505
except Exception, e:
513
class cmd_import(BzrToolsCommand):
509
class cmd_branch_mark(bzrlib.commands.Command):
511
Add, view or list branch markers <EXPERIMENTAL>
513
To add a mark, do 'bzr branch-mark MARK'.
514
To list marks, do 'bzr branch-mark' (this lists all marks for the branch's
516
To delete a mark, do 'bzr branch-mark --delete MARK'
518
These marks can be used to track a branch's status.
520
takes_args = ['mark?', 'branch?']
521
takes_options = [Option('delete', help='Delete this mark')]
522
def run(self, mark=None, branch=None, delete=False):
523
from branch_mark import branch_mark
524
branch_mark(mark, branch, delete)
527
class cmd_import(bzrlib.commands.Command):
514
528
"""Import sources from a directory, tarball or zip file
516
530
This command will import a directory, tarball or zip file into a bzr
517
531
tree, replacing any versioned files already present. If a directory is
518
532
specified, it is used as the target. If the directory does not exist, or
523
537
If the tarball or zip has a single root directory, that directory is
524
538
stripped when extracting the tarball. This is not done for directories.
527
541
takes_args = ['source', 'tree?']
528
542
def run(self, source, tree=None):
529
543
from upstream_import import do_import
530
544
do_import(source, tree)
533
class cmd_cdiff(BzrToolsCommand):
547
class cmd_cdiff(bzrlib.commands.Command):
534
548
"""A color version of bzr's diff"""
535
549
takes_args = property(lambda x: get_cmd_object('diff').takes_args)
536
takes_options = list(get_cmd_object('diff').takes_options) + [
537
Option('check-style',
538
help='Warn if trailing whitespace or spurious changes have been'
541
def run(self, check_style=False, *args, **kwargs):
550
takes_options = property(lambda x: get_cmd_object('diff').takes_options)
551
def run(*args, **kwargs):
542
552
from colordiff import colordiff
543
colordiff(check_style, *args, **kwargs)
546
class cmd_baz_import(BzrToolsCommand):
553
colordiff(*args, **kwargs)
556
class cmd_baz_import(bzrlib.commands.Command):
547
557
"""Import an Arch or Baz archive into a bzr repository.
549
559
This command should be used on local archives (or mirrors) only. It is
550
560
quite slow on remote archives.
552
reuse_history allows you to specify any previous imports you
562
reuse_history allows you to specify any previous imports you
553
563
have done of different archives, which this archive has branches
554
tagged from. This will dramatically reduce the time to convert
564
tagged from. This will dramatically reduce the time to convert
555
565
the archive as it will not have to convert the history already
556
566
converted in that other branch.
571
581
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
572
582
takes_options = ['verbose', Option('prefixes', type=str,
573
help="Prefixes of branches to import, colon-separated."),
574
Option('encoding', type=str,
583
help="Prefixes of branches to import, colon-separated"),
584
Option('encoding', type=str,
575
585
help='Force encoding to specified value. See WARNING.')]
577
587
def run(self, to_root_dir, from_archive, encoding=None, verbose=False,
596
606
are incompatible.
598
608
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
599
takes_options = ['verbose',
600
Option('max-count', type=int,
601
help='Maximim revisions to import at once.'),
602
Option('encoding', type=str,
609
takes_options = ['verbose', Option('max-count', type=int),
610
Option('encoding', type=str,
603
611
help='Force encoding to specified value. See WARNING.')]
605
613
def run(self, to_location, from_branch=None, fast=False, max_count=None,
608
616
from errors import NoPyBaz
610
618
import baz_import
611
baz_import.baz_import_branch(to_location, from_branch, fast,
619
baz_import.baz_import_branch(to_location, from_branch, fast,
612
620
max_count, verbose, encoding, dry_run,
613
621
reuse_history_list)
615
623
print "This command is disabled. Please install PyBaz."
618
class cmd_rspush(BzrToolsCommand):
626
class cmd_rspush(bzrlib.commands.Command):
619
627
"""Upload this branch to another location using rsync.
621
If no location is specified, the last-used location will be used. To
622
prevent dirty trees from being uploaded, rspush will error out if there are
623
unknown files or local changes. It will also error out if the upstream
624
directory is non-empty and not an earlier version of the branch.
629
If no location is specified, the last-used location will be used. To
630
prevent dirty trees from being uploaded, rspush will error out if there are
631
unknown files or local changes. It will also error out if the upstream
632
directory is non-empty and not an earlier version of the branch.
626
634
takes_args = ['location?']
627
635
takes_options = [Option('overwrite', help='Ignore differences between'
628
' branches and overwrite unconditionally.'),
636
' branches and overwrite unconditionally'),
629
637
Option('no-tree', help='Do not push the working tree,'
630
638
' just the .bzr.')]
633
641
from bzrlib import workingtree
635
643
cur_branch = workingtree.WorkingTree.open_containing(".")[0]
636
bzrtools.rspush(cur_branch, location, overwrite=overwrite,
644
bzrtools.rspush(cur_branch, location, overwrite=overwrite,
637
645
working_tree=not no_tree)
648
class cmd_switch(bzrlib.commands.Command):
649
"""Set the branch of a lightweight checkout and update."""
651
takes_args = ['to_location']
653
def run(self, to_location):
654
from switch import cmd_switch
655
cmd_switch().run(to_location)
642
660
cmd_baz_import_branch,
645
662
cmd_branch_history,
649
667
cmd_fetch_ghosts,