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
26
__version__ = '0.13.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
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
81
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
56
class cmd_clean_tree(BzrToolsCommand):
84
class cmd_clean_tree(bzrlib.commands.Command):
57
85
"""Remove unwanted files from working tree.
59
87
By default, only unknown files, not ignored files, are deleted. Versioned
118
146
If available, rsvg is used to antialias PNG and JPEG output, but this can
119
147
be disabled with --no-antialias.
121
takes_args = ['file', 'merge_branch?']
122
takes_options = [Option('no-collapse', help="Do not skip simple nodes."),
149
takes_args = ['branch', 'file']
150
takes_options = [Option('no-collapse', help="Do not skip simple nodes"),
123
151
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."),
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:
152
help="Do not use rsvg to produce antialiased output"),
153
Option('merge-branch', type=str,
154
help="Use this branch to calcuate a merge base"),
155
Option('cluster', help="Use clustered output.")]
156
def run(self, branch, file, no_collapse=False, no_antialias=False,
157
merge_branch=None, cluster=False):
143
160
ranking = "cluster"
145
162
ranking = "forced"
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):
163
graph.write_ancestry_file(branch, file, not no_collapse,
164
not no_antialias, merge_branch, ranking)
167
class cmd_fetch_ghosts(bzrlib.commands.Command):
152
168
"""Attempt to retrieve ghosts from another branch.
153
169
If the other branch is not supplied, the last-pulled branch is used.
155
171
aliases = ['fetch-missing']
156
172
takes_args = ['branch?']
157
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
173
takes_options = [Option('no-fix')]
158
174
def run(self, branch=None, no_fix=False):
159
175
from fetch_ghosts import fetch_ghosts
160
176
fetch_ghosts(branch, no_fix)
162
178
strip_help="""Strip the smallest prefix containing num leading slashes from \
163
179
each file name found in the patch file."""
166
class cmd_patch(BzrToolsCommand):
180
Option.OPTIONS['bzrdiff'] = Option('bzrdiff',type=None,
181
help="""Handle extra bzr tags""")
184
class cmd_patch(bzrlib.commands.Command):
167
185
"""Apply a named patch to the current tree.
169
187
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):
188
takes_options = [Option('strip', type=int, help=strip_help)]
189
def run(self, filename=None, strip=-1, bzrdiff=0):
173
190
from patch import patch
174
191
from bzrlib.workingtree import WorkingTree
175
192
wt = WorkingTree.open_containing('.')[0]
178
return patch(wt, filename, strip, silent)
181
class cmd_shelve(BzrToolsCommand):
194
if bzrdiff: strip = 0
197
return patch(wt, filename, strip, legacy= not bzrdiff)
200
class cmd_shelve(bzrlib.commands.Command):
182
201
"""Temporarily set aside some changes from the current tree.
184
203
Shelve allows you to temporarily put changes you've made "on the shelf",
408
421
If --branch is specified, the branch will be deleted too, but only if the
409
422
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'
424
takes_options = [Option("branch", help="Remove associtated branch from"
415
426
takes_args = ["checkout"]
416
def run(self, checkout, branch=False, force=False):
427
def run(self, checkout, branch=False):
417
428
from zap import zap
418
return zap(checkout, remove_branch=branch, allow_modified=force)
421
class cmd_cbranch(BzrToolsCommand):
429
return zap(checkout, remove_branch=branch)
432
class cmd_cbranch(bzrlib.commands.Command):
423
434
Create a new checkout, associated with a new repository branch.
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
436
When you cbranch, bzr looks up the repository associated with your current
437
directory in locations.conf. It creates a new branch in that repository
438
with the same name and relative path as the checkout you request.
440
The locations.conf parameter is "cbranch_root". So if you want
441
cbranch operations in /home/jrandom/bigproject to produce branches in
442
/home/jrandom/bigproject/repository, you'd add this:
444
[/home/jrandom/bigproject]
445
cbranch_root = /home/jrandom/bigproject/repository
447
Note that if "/home/jrandom/bigproject/repository" isn't a repository,
448
standalone branches will be produced. Standalone branches will also
449
be produced if the source branch is in 0.7 format (or earlier).
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'
451
takes_options = [Option("lightweight",
452
help="Create a lightweight checkout"), 'revision']
448
453
takes_args = ["source", "target?"]
449
def run(self, source, target=None, lightweight=False, revision=None,
450
files_from=None, hardlink=False):
454
def run(self, source, target=None, lightweight=False, revision=None):
451
455
from cbranch import cbranch
452
return cbranch(source, target, lightweight=lightweight,
453
revision=revision, files_from=files_from,
457
class cmd_branches(BzrToolsCommand):
456
return cbranch(source, target, lightweight=lightweight,
460
class cmd_branches(bzrlib.commands.Command):
458
461
"""Scan a location for branches"""
459
462
takes_args = ["location?"]
460
463
def run(self, location=None):
461
464
from branches import branches
462
465
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))
475
class cmd_multi_pull(BzrToolsCommand):
468
class cmd_multi_pull(bzrlib.commands.Command):
476
469
"""Pull all the branches under a location, e.g. a repository.
478
471
Both branches present in the directory and the branches of checkouts are
481
474
takes_args = ["location?"]
482
475
def run(self, location=None):
476
from bzrlib.branch import Branch
483
477
from bzrlib.transport import get_transport
484
478
from bzrtools import iter_branch_tree
485
479
if location is None:
487
481
t = get_transport(location)
488
possible_transports = []
489
482
if not t.listable():
490
483
print "Can't list this type of location."
508
501
print "Pulling %s from %s" % (relpath, parent)
510
branch_t = get_transport(parent, possible_transports)
511
pullable.pull(Branch.open_from_transport(branch_t))
503
pullable.pull(Branch.open(parent))
512
504
except Exception, e:
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.
508
class cmd_branch_mark(bzrlib.commands.Command):
510
Add, view or list branch markers <EXPERIMENTAL>
512
To add a mark, do 'bzr branch-mark MARK'.
513
To list marks, do 'bzr branch-mark' (this lists all marks for the branch's
515
To delete a mark, do 'bzr branch-mark --delete MARK'
517
These marks can be used to track a branch's status.
519
takes_args = ['mark?', 'branch?']
520
takes_options = [Option('delete', help='Delete this mark')]
521
def run(self, mark=None, branch=None, delete=False):
522
from branch_mark import branch_mark
523
branch_mark(mark, branch, delete)
526
class cmd_import(bzrlib.commands.Command):
527
"""Import sources from a tarball
529
This command will import a tarball into a bzr tree, replacing any versioned
530
files already present. If a directory is specified, it is used as the
531
target. If the directory does not exist, or is not versioned, it is
525
534
Tarballs may be gzip or bzip2 compressed. This is autodetected.
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.
536
If the tarball has a single root directory, that directory is stripped
537
when extracting the tarball.
531
540
takes_args = ['source', 'tree?']
532
541
def run(self, source, tree=None):
533
542
from upstream_import import do_import
534
543
do_import(source, tree)
537
class cmd_cdiff(BzrToolsCommand):
546
class cmd_cdiff(bzrlib.commands.Command):
538
547
"""A color version of bzr's diff"""
539
548
takes_args = property(lambda x: get_cmd_object('diff').takes_args)
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):
549
takes_options = property(lambda x: get_cmd_object('diff').takes_options)
550
def run(*args, **kwargs):
546
551
from colordiff import colordiff
547
colordiff(check_style, *args, **kwargs)
550
class cmd_rspush(BzrToolsCommand):
552
colordiff(*args, **kwargs)
555
class cmd_baz_import(bzrlib.commands.Command):
556
"""Import an Arch or Baz archive into a bzr repository.
558
This command should be used on local archives (or mirrors) only. It is
559
quite slow on remote archives.
561
reuse_history allows you to specify any previous imports you
562
have done of different archives, which this archive has branches
563
tagged from. This will dramatically reduce the time to convert
564
the archive as it will not have to convert the history already
565
converted in that other branch.
567
If you specify prefixes, only branches whose names start with that prefix
568
will be imported. Skipped branches will be listed, so you can import any
569
branches you missed by accident. Here's an example of doing a partial
570
import from thelove@canonical.com:
571
bzr baz-import thelove thelove@canonical.com --prefixes dists:talloc-except
573
WARNING: Encoding should not be specified unless necessary, because if you
574
specify an encoding, your converted branch will not interoperate with
575
independently-converted branches, unless the other branches were converted
576
with exactly the same encoding. Any encoding recognized by Python may
577
be specified. Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
580
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
581
takes_options = ['verbose', Option('prefixes', type=str,
582
help="Prefixes of branches to import, colon-separated"),
583
Option('encoding', type=str,
584
help='Force encoding to specified value. See WARNING.')]
586
def run(self, to_root_dir, from_archive, encoding=None, verbose=False,
587
reuse_history_list=[], prefixes=None):
588
from errors import NoPyBaz
591
baz_import.baz_import(to_root_dir, from_archive, encoding,
592
verbose, reuse_history_list, prefixes)
594
print "This command is disabled. Please install PyBaz."
597
class cmd_baz_import_branch(bzrlib.commands.Command):
598
"""Import an Arch or Baz branch into a bzr branch.
600
WARNING: Encoding should not be specified unless necessary, because if you
601
specify an encoding, your converted branch will not interoperate with
602
independently-converted branches, unless the other branches were converted
603
with exactly the same encoding. Any encoding recognized by Python may
604
be specified. Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
607
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
608
takes_options = ['verbose', Option('max-count', type=int),
609
Option('encoding', type=str,
610
help='Force encoding to specified value. See WARNING.')]
612
def run(self, to_location, from_branch=None, fast=False, max_count=None,
613
encoding=None, verbose=False, dry_run=False,
614
reuse_history_list=[]):
615
from errors import NoPyBaz
618
baz_import.baz_import_branch(to_location, from_branch, fast,
619
max_count, verbose, encoding, dry_run,
622
print "This command is disabled. Please install PyBaz."
625
class cmd_rspush(bzrlib.commands.Command):
551
626
"""Upload this branch to another location using rsync.
553
If no location is specified, the last-used location will be used. To
554
prevent dirty trees from being uploaded, rspush will error out if there are
555
unknown files or local changes. It will also error out if the upstream
556
directory is non-empty and not an earlier version of the branch.
628
If no location is specified, the last-used location will be used. To
629
prevent dirty trees from being uploaded, rspush will error out if there are
630
unknown files or local changes. It will also error out if the upstream
631
directory is non-empty and not an earlier version of the branch.
558
633
takes_args = ['location?']
559
634
takes_options = [Option('overwrite', help='Ignore differences between'
560
' branches and overwrite unconditionally.'),
635
' branches and overwrite unconditionally'),
561
636
Option('no-tree', help='Do not push the working tree,'
562
637
' just the .bzr.')]