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])
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
65
33
from errors import CommandError, NoPyBaz
66
34
from patchsource import BzrPatchSource
67
from shelf import Shelf
71
38
import bzrlib.builtins
72
39
import bzrlib.commands
40
from bzrlib.branch import Branch
41
from bzrlib.bzrdir import BzrDir
73
42
from bzrlib.commands import get_cmd_object
74
43
from bzrlib.errors import BzrCommandError
75
from bzrlib.help import command_usage
76
44
import bzrlib.ignores
45
from bzrlib.trace import note
77
46
from bzrlib.option import Option
78
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__),
47
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__),
51
from command import BzrToolsCommand
83
53
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
86
class cmd_clean_tree(bzrlib.commands.Command):
56
class cmd_clean_tree(BzrToolsCommand):
87
57
"""Remove unwanted files from working tree.
89
59
By default, only unknown files, not ignored files, are deleted. Versioned
99
69
To check what clean-tree will do, use --dry-run.
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'
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'
107
77
' deleting them.')]
108
78
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False):
109
79
from clean_tree import clean_tree
148
118
If available, rsvg is used to antialias PNG and JPEG output, but this can
149
119
be disabled with --no-antialias.
151
takes_args = ['branch', 'file']
152
takes_options = [Option('no-collapse', help="Do not skip simple nodes"),
121
takes_args = ['file', 'merge_branch?']
122
takes_options = [Option('no-collapse', help="Do not skip simple nodes."),
153
123
Option('no-antialias',
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"),
157
Option('cluster', help="Use clustered output.")]
158
def run(self, branch, file, no_collapse=False, no_antialias=False,
159
merge_branch=None, cluster=False):
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."),
127
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:
162
143
ranking = "cluster"
164
145
ranking = "forced"
165
graph.write_ancestry_file(branch, file, not no_collapse,
166
not no_antialias, merge_branch, ranking)
169
class cmd_fetch_ghosts(bzrlib.commands.Command):
146
graph.write_ancestry_file(directory, file, not no_collapse,
147
not no_antialias, merge_branch, ranking,
148
max_distance=max_distance)
151
class cmd_fetch_ghosts(BzrToolsCommand):
170
152
"""Attempt to retrieve ghosts from another branch.
171
153
If the other branch is not supplied, the last-pulled branch is used.
173
155
aliases = ['fetch-missing']
174
156
takes_args = ['branch?']
175
takes_options = [Option('no-fix')]
157
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
176
158
def run(self, branch=None, no_fix=False):
177
159
from fetch_ghosts import fetch_ghosts
178
160
fetch_ghosts(branch, no_fix)
180
162
strip_help="""Strip the smallest prefix containing num leading slashes from \
181
163
each file name found in the patch file."""
182
Option.OPTIONS['bzrdiff'] = Option('bzrdiff',type=None,
183
help="""Handle extra bzr tags""")
186
class cmd_patch(bzrlib.commands.Command):
166
class cmd_patch(BzrToolsCommand):
187
167
"""Apply a named patch to the current tree.
189
169
takes_args = ['filename?']
190
takes_options = [Option('strip', type=int, help=strip_help)]
191
def run(self, filename=None, strip=-1, bzrdiff=0):
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):
192
173
from patch import patch
193
174
from bzrlib.workingtree import WorkingTree
194
175
wt = WorkingTree.open_containing('.')[0]
196
if bzrdiff: strip = 0
199
return patch(wt, filename, strip, legacy= not bzrdiff)
202
class cmd_shelve(bzrlib.commands.Command):
178
return patch(wt, filename, strip, silent)
181
class cmd_shelve(BzrToolsCommand):
203
182
"""Temporarily set aside some changes from the current tree.
205
184
Shelve allows you to temporarily put changes you've made "on the shelf",
363
348
See 'shelve' for more information.
365
350
takes_options = [
366
Option('all', help='Unshelve all changes without prompting'),
367
Option('force', help='Force unshelving even if errors occur'),
368
Option('no-color', help='Never display changes in color')
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.')
370
355
takes_args = ['patch?']
371
356
def run(self, patch=None, all=False, force=False, no_color=False):
372
357
source = BzrPatchSource()
373
s = Shelf(source.base)
358
s = shelf.Shelf(source.base)
374
359
s.unshelve(source, patch, all, force, no_color)
378
class cmd_shell(bzrlib.commands.Command):
363
class cmd_shell(BzrToolsCommand):
379
364
"""Begin an interactive shell tailored for bzr.
380
365
Bzr commands can be used without typing bzr first, and will be run natively
381
366
when possible. Tab completion is tailored for bzr. The shell prompt shows
423
408
If --branch is specified, the branch will be deleted too, but only if the
424
409
the branch has no new commits (relative to its parent).
426
takes_options = [Option("branch", help="Remove associtated branch from"
411
takes_options = [Option("branch", help="Remove associated branch from"
413
Option('force', help='Delete tree even if contents are'
428
415
takes_args = ["checkout"]
429
def run(self, checkout, branch=False):
416
def run(self, checkout, branch=False, force=False):
430
417
from zap import zap
431
return zap(checkout, remove_branch=branch)
434
class cmd_cbranch(bzrlib.commands.Command):
418
return zap(checkout, remove_branch=branch, allow_modified=force)
421
class cmd_cbranch(BzrToolsCommand):
436
423
Create a new checkout, associated with a new repository branch.
438
When you cbranch, bzr looks up the repository associated with your current
439
directory in locations.conf. It creates a new branch in that repository
440
with the same name and relative path as the checkout you request.
442
The locations.conf parameter is "cbranch_root". So if you want
443
cbranch operations in /home/jrandom/bigproject to produce branches in
444
/home/jrandom/bigproject/repository, you'd add this:
446
[/home/jrandom/bigproject]
447
cbranch_root = /home/jrandom/bigproject/repository
449
Note that if "/home/jrandom/bigproject/repository" isn't a repository,
450
standalone branches will be produced. Standalone branches will also
451
be produced if the source branch is in 0.7 format (or earlier).
425
When you cbranch, bzr looks up a target location in locations.conf, and
426
creates the branch there.
428
In your locations.conf, add the following lines:
429
[/working_directory_root]
430
cbranch_target = /branch_root
431
cbranch_target:policy = appendpath
433
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
435
"/branch_root/foo/baz"
437
NOTE: cbranch also supports "cbranch_root", but that behaviour is
453
takes_options = [Option("lightweight",
454
help="Create a lightweight checkout"), 'revision']
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'
446
help='Hard-link files from source/files-from tree'
455
448
takes_args = ["source", "target?"]
456
def run(self, source, target=None, lightweight=False, revision=None):
449
def run(self, source, target=None, lightweight=False, revision=None,
450
files_from=None, hardlink=False):
457
451
from cbranch import cbranch
458
return cbranch(source, target, lightweight=lightweight,
462
class cmd_branches(bzrlib.commands.Command):
452
return cbranch(source, target, lightweight=lightweight,
453
revision=revision, files_from=files_from,
457
class cmd_branches(BzrToolsCommand):
463
458
"""Scan a location for branches"""
464
459
takes_args = ["location?"]
465
460
def run(self, location=None):
466
461
from branches import branches
467
462
return branches(location)
464
class cmd_trees(BzrToolsCommand):
465
"""Scan a location for trees"""
466
takes_args = ['location?']
467
def run(self, location='.'):
468
from bzrlib.workingtree import WorkingTree
469
from bzrlib.transport import get_transport
470
t = get_transport(location)
471
for tree in WorkingTree.find_trees(location):
472
self.outf.write('%s\n' % t.relpath(
473
tree.bzrdir.root_transport.base))
470
class cmd_multi_pull(bzrlib.commands.Command):
475
class cmd_multi_pull(BzrToolsCommand):
471
476
"""Pull all the branches under a location, e.g. a repository.
473
478
Both branches present in the directory and the branches of checkouts are
476
481
takes_args = ["location?"]
477
482
def run(self, location=None):
478
from bzrlib.branch import Branch
479
483
from bzrlib.transport import get_transport
480
484
from bzrtools import iter_branch_tree
481
485
if location is None:
483
487
t = get_transport(location)
488
possible_transports = []
484
489
if not t.listable():
485
490
print "Can't list this type of location."
503
508
print "Pulling %s from %s" % (relpath, parent)
505
pullable.pull(Branch.open(parent))
510
branch_t = get_transport(parent, possible_transports)
511
pullable.pull(Branch.open_from_transport(branch_t))
506
512
except Exception, e:
510
class cmd_branch_mark(bzrlib.commands.Command):
512
Add, view or list branch markers <EXPERIMENTAL>
514
To add a mark, do 'bzr branch-mark MARK'.
515
To list marks, do 'bzr branch-mark' (this lists all marks for the branch's
517
To delete a mark, do 'bzr branch-mark --delete MARK'
519
These marks can be used to track a branch's status.
521
takes_args = ['mark?', 'branch?']
522
takes_options = [Option('delete', help='Delete this mark')]
523
def run(self, mark=None, branch=None, delete=False):
524
from branch_mark import branch_mark
525
branch_mark(mark, branch, delete)
528
class cmd_import(bzrlib.commands.Command):
529
"""Import sources from a tarball
531
This command will import a tarball into a bzr tree, replacing any versioned
532
files already present. If a directory is specified, it is used as the
533
target. If the directory does not exist, or is not versioned, it is
517
class cmd_import(BzrToolsCommand):
518
"""Import sources from a directory, tarball or zip file
520
This command will import a directory, tarball or zip file into a bzr
521
tree, replacing any versioned files already present. If a directory is
522
specified, it is used as the target. If the directory does not exist, or
523
is not versioned, it is created.
536
525
Tarballs may be gzip or bzip2 compressed. This is autodetected.
538
If the tarball has a single root directory, that directory is stripped
539
when extracting the tarball.
527
If the tarball or zip has a single root directory, that directory is
528
stripped when extracting the tarball. This is not done for directories.
542
531
takes_args = ['source', 'tree?']
543
532
def run(self, source, tree=None):
544
533
from upstream_import import do_import
545
534
do_import(source, tree)
548
class cmd_cdiff(bzrlib.commands.Command):
537
class cmd_cdiff(BzrToolsCommand):
549
538
"""A color version of bzr's diff"""
550
539
takes_args = property(lambda x: get_cmd_object('diff').takes_args)
551
takes_options = property(lambda x: get_cmd_object('diff').takes_options)
552
def run(*args, **kwargs):
540
takes_options = list(get_cmd_object('diff').takes_options) + [
541
Option('check-style',
542
help='Warn if trailing whitespace or spurious changes have been'
545
def run(self, check_style=False, *args, **kwargs):
553
546
from colordiff import colordiff
554
colordiff(*args, **kwargs)
557
class cmd_baz_import(bzrlib.commands.Command):
547
colordiff(check_style, *args, **kwargs)
550
class cmd_baz_import(BzrToolsCommand):
558
551
"""Import an Arch or Baz archive into a bzr repository.
560
553
This command should be used on local archives (or mirrors) only. It is
561
554
quite slow on remote archives.
563
reuse_history allows you to specify any previous imports you
556
reuse_history allows you to specify any previous imports you
564
557
have done of different archives, which this archive has branches
565
tagged from. This will dramatically reduce the time to convert
558
tagged from. This will dramatically reduce the time to convert
566
559
the archive as it will not have to convert the history already
567
560
converted in that other branch.
607
600
are incompatible.
609
602
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
610
takes_options = ['verbose', Option('max-count', type=int),
611
Option('encoding', type=str,
603
takes_options = ['verbose',
604
Option('max-count', type=int,
605
help='Maximim revisions to import at once.'),
606
Option('encoding', type=str,
612
607
help='Force encoding to specified value. See WARNING.')]
614
609
def run(self, to_location, from_branch=None, fast=False, max_count=None,
617
612
from errors import NoPyBaz
619
614
import baz_import
620
baz_import.baz_import_branch(to_location, from_branch, fast,
615
baz_import.baz_import_branch(to_location, from_branch, fast,
621
616
max_count, verbose, encoding, dry_run,
622
617
reuse_history_list)
624
619
print "This command is disabled. Please install PyBaz."
627
class cmd_rspush(bzrlib.commands.Command):
622
class cmd_rspush(BzrToolsCommand):
628
623
"""Upload this branch to another location using rsync.
630
If no location is specified, the last-used location will be used. To
631
prevent dirty trees from being uploaded, rspush will error out if there are
632
unknown files or local changes. It will also error out if the upstream
633
directory is non-empty and not an earlier version of the branch.
625
If no location is specified, the last-used location will be used. To
626
prevent dirty trees from being uploaded, rspush will error out if there are
627
unknown files or local changes. It will also error out if the upstream
628
directory is non-empty and not an earlier version of the branch.
635
630
takes_args = ['location?']
636
631
takes_options = [Option('overwrite', help='Ignore differences between'
637
' branches and overwrite unconditionally'),
632
' branches and overwrite unconditionally.'),
638
633
Option('no-tree', help='Do not push the working tree,'
639
634
' just the .bzr.')]