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])
65
from errors import CommandError, NoPyBaz
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
33
from errors import CommandError
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__),
48
from command import BzrToolsCommand
83
50
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
86
class cmd_clean_tree(bzrlib.commands.Command):
53
class cmd_clean_tree(BzrToolsCommand):
87
54
"""Remove unwanted files from working tree.
89
56
By default, only unknown files, not ignored files, are deleted. Versioned
148
115
If available, rsvg is used to antialias PNG and JPEG output, but this can
149
116
be disabled with --no-antialias.
151
takes_args = ['branch', 'file']
152
takes_options = [Option('no-collapse', help="Do not skip simple nodes"),
118
takes_args = ['file', 'merge_branch?']
119
takes_options = [Option('no-collapse', help="Do not skip simple nodes."),
153
120
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):
121
help="Do not use rsvg to produce antialiased output."),
122
Option('merge-branch', type=str,
123
help="Use this branch to calcuate a merge base."),
124
Option('cluster', help="Use clustered output."),
125
Option('max-distance',
126
help="Show no nodes farther than this.", type=int),
128
help='Source branch to use (default is current'
133
def run(self, file, merge_branch=None, no_collapse=False,
134
no_antialias=False, cluster=False, max_distance=100,
136
if max_distance == -1:
162
140
ranking = "cluster"
164
142
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):
143
graph.write_ancestry_file(directory, file, not no_collapse,
144
not no_antialias, merge_branch, ranking,
145
max_distance=max_distance)
148
class cmd_fetch_ghosts(BzrToolsCommand):
170
149
"""Attempt to retrieve ghosts from another branch.
171
150
If the other branch is not supplied, the last-pulled branch is used.
173
152
aliases = ['fetch-missing']
174
153
takes_args = ['branch?']
175
takes_options = [Option('no-fix')]
154
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
176
155
def run(self, branch=None, no_fix=False):
177
156
from fetch_ghosts import fetch_ghosts
178
157
fetch_ghosts(branch, no_fix)
180
159
strip_help="""Strip the smallest prefix containing num leading slashes from \
181
160
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):
163
class cmd_patch(BzrToolsCommand):
187
164
"""Apply a named patch to the current tree.
189
166
takes_args = ['filename?']
190
takes_options = [Option('strip', type=int, help=strip_help)]
191
def run(self, filename=None, strip=-1, bzrdiff=0):
167
takes_options = [Option('strip', type=int, help=strip_help),
168
Option('silent', help='Suppress chatter.')]
169
def run(self, filename=None, strip=None, silent=False):
192
170
from patch import patch
193
171
from bzrlib.workingtree import WorkingTree
194
172
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):
175
return patch(wt, filename, strip, silent)
178
class cmd_shelve(BzrToolsCommand):
203
179
"""Temporarily set aside some changes from the current tree.
205
181
Shelve allows you to temporarily put changes you've made "on the shelf",
423
405
If --branch is specified, the branch will be deleted too, but only if the
424
406
the branch has no new commits (relative to its parent).
426
takes_options = [Option("branch", help="Remove associtated branch from"
408
takes_options = [Option("branch", help="Remove associated branch from"
410
Option('force', help='Delete tree even if contents are'
428
412
takes_args = ["checkout"]
429
def run(self, checkout, branch=False):
413
def run(self, checkout, branch=False, force=False):
430
414
from zap import zap
431
return zap(checkout, remove_branch=branch)
434
class cmd_cbranch(bzrlib.commands.Command):
415
return zap(checkout, remove_branch=branch, allow_modified=force)
418
class cmd_cbranch(BzrToolsCommand):
436
420
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).
422
When you cbranch, bzr looks up a target location in locations.conf, and
423
creates the branch there.
425
In your locations.conf, add the following lines:
426
[/working_directory_root]
427
cbranch_target = /branch_root
428
cbranch_target:policy = appendpath
430
This will mean that if you run "bzr cbranch foo/bar foo/baz" in the
431
working directory root, the branch will be created in
432
"/branch_root/foo/baz"
434
NOTE: cbranch also supports "cbranch_root", but that behaviour is
453
takes_options = [Option("lightweight",
454
help="Create a lightweight checkout"), 'revision']
437
takes_options = [Option("lightweight",
438
help="Create a lightweight checkout."), 'revision',
439
Option('files-from', type=unicode,
440
help='Accelerate checkout using files from this'
443
help='Hard-link files from source/files-from tree'
455
445
takes_args = ["source", "target?"]
456
def run(self, source, target=None, lightweight=False, revision=None):
446
def run(self, source, target=None, lightweight=False, revision=None,
447
files_from=None, hardlink=False):
457
448
from cbranch import cbranch
458
return cbranch(source, target, lightweight=lightweight,
462
class cmd_branches(bzrlib.commands.Command):
449
return cbranch(source, target, lightweight=lightweight,
450
revision=revision, files_from=files_from,
454
class cmd_branches(BzrToolsCommand):
463
455
"""Scan a location for branches"""
464
456
takes_args = ["location?"]
465
457
def run(self, location=None):
466
458
from branches import branches
467
459
return branches(location)
461
class cmd_trees(BzrToolsCommand):
462
"""Scan a location for trees"""
463
takes_args = ['location?']
464
def run(self, location='.'):
465
from bzrlib.workingtree import WorkingTree
466
from bzrlib.transport import get_transport
467
t = get_transport(location)
468
for tree in WorkingTree.find_trees(location):
469
self.outf.write('%s\n' % t.relpath(
470
tree.bzrdir.root_transport.base))
470
class cmd_multi_pull(bzrlib.commands.Command):
472
class cmd_multi_pull(BzrToolsCommand):
471
473
"""Pull all the branches under a location, e.g. a repository.
473
475
Both branches present in the directory and the branches of checkouts are
476
478
takes_args = ["location?"]
477
479
def run(self, location=None):
478
from bzrlib.branch import Branch
479
480
from bzrlib.transport import get_transport
480
481
from bzrtools import iter_branch_tree
481
482
if location is None:
483
484
t = get_transport(location)
485
possible_transports = []
484
486
if not t.listable():
485
487
print "Can't list this type of location."
503
505
print "Pulling %s from %s" % (relpath, parent)
505
pullable.pull(Branch.open(parent))
507
branch_t = get_transport(parent, possible_transports)
508
pullable.pull(Branch.open_from_transport(branch_t))
506
509
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
514
class cmd_import(BzrToolsCommand):
515
"""Import sources from a directory, tarball or zip file
517
This command will import a directory, tarball or zip file into a bzr
518
tree, replacing any versioned files already present. If a directory is
519
specified, it is used as the target. If the directory does not exist, or
520
is not versioned, it is created.
536
522
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.
524
If the tarball or zip has a single root directory, that directory is
525
stripped when extracting the tarball. This is not done for directories.
542
528
takes_args = ['source', 'tree?']
543
529
def run(self, source, tree=None):
544
530
from upstream_import import do_import
545
531
do_import(source, tree)
548
class cmd_cdiff(bzrlib.commands.Command):
534
class cmd_cdiff(BzrToolsCommand):
549
535
"""A color version of bzr's diff"""
550
536
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):
537
takes_options = list(get_cmd_object('diff').takes_options) + [
538
Option('check-style',
539
help='Warn if trailing whitespace or spurious changes have been'
542
def run(self, check_style=False, *args, **kwargs):
553
543
from colordiff import colordiff
554
colordiff(*args, **kwargs)
557
class cmd_baz_import(bzrlib.commands.Command):
558
"""Import an Arch or Baz archive into a bzr repository.
560
This command should be used on local archives (or mirrors) only. It is
561
quite slow on remote archives.
563
reuse_history allows you to specify any previous imports you
564
have done of different archives, which this archive has branches
565
tagged from. This will dramatically reduce the time to convert
566
the archive as it will not have to convert the history already
567
converted in that other branch.
569
If you specify prefixes, only branches whose names start with that prefix
570
will be imported. Skipped branches will be listed, so you can import any
571
branches you missed by accident. Here's an example of doing a partial
572
import from thelove@canonical.com:
573
bzr baz-import thelove thelove@canonical.com --prefixes dists:talloc-except
575
WARNING: Encoding should not be specified unless necessary, because if you
576
specify an encoding, your converted branch will not interoperate with
577
independently-converted branches, unless the other branches were converted
578
with exactly the same encoding. Any encoding recognized by Python may
579
be specified. Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
582
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
583
takes_options = ['verbose', Option('prefixes', type=str,
584
help="Prefixes of branches to import, colon-separated"),
585
Option('encoding', type=str,
586
help='Force encoding to specified value. See WARNING.')]
588
def run(self, to_root_dir, from_archive, encoding=None, verbose=False,
589
reuse_history_list=[], prefixes=None):
590
from errors import NoPyBaz
593
baz_import.baz_import(to_root_dir, from_archive, encoding,
594
verbose, reuse_history_list, prefixes)
596
print "This command is disabled. Please install PyBaz."
599
class cmd_baz_import_branch(bzrlib.commands.Command):
600
"""Import an Arch or Baz branch into a bzr branch.
602
WARNING: Encoding should not be specified unless necessary, because if you
603
specify an encoding, your converted branch will not interoperate with
604
independently-converted branches, unless the other branches were converted
605
with exactly the same encoding. Any encoding recognized by Python may
606
be specified. Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
609
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
610
takes_options = ['verbose', Option('max-count', type=int),
611
Option('encoding', type=str,
612
help='Force encoding to specified value. See WARNING.')]
614
def run(self, to_location, from_branch=None, fast=False, max_count=None,
615
encoding=None, verbose=False, dry_run=False,
616
reuse_history_list=[]):
617
from errors import NoPyBaz
620
baz_import.baz_import_branch(to_location, from_branch, fast,
621
max_count, verbose, encoding, dry_run,
624
print "This command is disabled. Please install PyBaz."
627
class cmd_rspush(bzrlib.commands.Command):
544
colordiff(check_style, *args, **kwargs)
547
class cmd_rspush(BzrToolsCommand):
628
548
"""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.
550
If no location is specified, the last-used location will be used. To
551
prevent dirty trees from being uploaded, rspush will error out if there are
552
unknown files or local changes. It will also error out if the upstream
553
directory is non-empty and not an earlier version of the branch.
635
555
takes_args = ['location?']
636
556
takes_options = [Option('overwrite', help='Ignore differences between'
637
' branches and overwrite unconditionally'),
557
' branches and overwrite unconditionally.'),
638
558
Option('no-tree', help='Do not push the working tree,'
639
559
' just the .bzr.')]