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"),
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."),
157
127
Option('cluster', help="Use clustered output."),
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):
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:
164
143
ranking = "cluster"
166
145
ranking = "forced"
167
graph.write_ancestry_file(branch, file, not no_collapse,
168
not no_antialias, merge_branch, ranking,
146
graph.write_ancestry_file(directory, file, not no_collapse,
147
not no_antialias, merge_branch, ranking,
169
148
max_distance=max_distance)
172
class cmd_fetch_ghosts(bzrlib.commands.Command):
151
class cmd_fetch_ghosts(BzrToolsCommand):
173
152
"""Attempt to retrieve ghosts from another branch.
174
153
If the other branch is not supplied, the last-pulled branch is used.
176
155
aliases = ['fetch-missing']
177
156
takes_args = ['branch?']
178
takes_options = [Option('no-fix')]
157
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
179
158
def run(self, branch=None, no_fix=False):
180
159
from fetch_ghosts import fetch_ghosts
181
160
fetch_ghosts(branch, no_fix)
184
163
each file name found in the patch file."""
187
class cmd_patch(bzrlib.commands.Command):
166
class cmd_patch(BzrToolsCommand):
188
167
"""Apply a named patch to the current tree.
190
169
takes_args = ['filename?']
191
takes_options = [Option('strip', type=int, help=strip_help)]
192
def run(self, filename=None, strip=None):
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):
193
173
from patch import patch
194
174
from bzrlib.workingtree import WorkingTree
195
175
wt = WorkingTree.open_containing('.')[0]
196
176
if strip is None:
198
return patch(wt, filename, strip)
201
class cmd_shelve(bzrlib.commands.Command):
178
return patch(wt, filename, strip, silent)
181
class cmd_shelve(BzrToolsCommand):
202
182
"""Temporarily set aside some changes from the current tree.
204
184
Shelve allows you to temporarily put changes you've made "on the shelf",
231
211
takes_args = ['file*']
232
takes_options = ['message', 'revision',
233
Option('all', help='Shelve all changes without prompting'),
234
Option('no-color', help='Never display changes in color')]
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.')]
236
219
def run(self, all=False, file_list=None, message=None, revision=None,
362
348
See 'shelve' for more information.
364
350
takes_options = [
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')
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.')
369
355
takes_args = ['patch?']
370
356
def run(self, patch=None, all=False, force=False, no_color=False):
371
357
source = BzrPatchSource()
372
s = Shelf(source.base)
358
s = shelf.Shelf(source.base)
373
359
s.unshelve(source, patch, all, force, no_color)
377
class cmd_shell(bzrlib.commands.Command):
363
class cmd_shell(BzrToolsCommand):
378
364
"""Begin an interactive shell tailored for bzr.
379
365
Bzr commands can be used without typing bzr first, and will be run natively
380
366
when possible. Tab completion is tailored for bzr. The shell prompt shows
422
408
If --branch is specified, the branch will be deleted too, but only if the
423
409
the branch has no new commits (relative to its parent).
425
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'
427
415
takes_args = ["checkout"]
428
def run(self, checkout, branch=False):
416
def run(self, checkout, branch=False, force=False):
429
417
from zap import zap
430
return zap(checkout, remove_branch=branch)
433
class cmd_cbranch(bzrlib.commands.Command):
418
return zap(checkout, remove_branch=branch, allow_modified=force)
421
class cmd_cbranch(BzrToolsCommand):
435
423
Create a new checkout, associated with a new repository branch.
437
425
When you cbranch, bzr looks up a target location in locations.conf, and
438
426
creates the branch there.
443
431
cbranch_target:policy = appendpath
445
433
This will mean that if you run "bzr cbranch foo/bar foo/baz" in the
446
working directory root, the branch will be created in
434
working directory root, the branch will be created in
447
435
"/branch_root/foo/baz"
449
437
NOTE: cbranch also supports "cbranch_root", but that behaviour is
452
takes_options = [Option("lightweight",
453
help="Create a lightweight checkout"), 'revision']
440
takes_options = [Option("lightweight",
441
help="Create a lightweight checkout."), 'revision']
454
442
takes_args = ["source", "target?"]
455
443
def run(self, source, target=None, lightweight=False, revision=None):
456
444
from cbranch import cbranch
457
return cbranch(source, target, lightweight=lightweight,
445
return cbranch(source, target, lightweight=lightweight,
458
446
revision=revision)
461
class cmd_branches(bzrlib.commands.Command):
449
class cmd_branches(BzrToolsCommand):
462
450
"""Scan a location for branches"""
463
451
takes_args = ["location?"]
464
452
def run(self, location=None):
466
454
return branches(location)
469
class cmd_multi_pull(bzrlib.commands.Command):
457
class cmd_multi_pull(BzrToolsCommand):
470
458
"""Pull all the branches under a location, e.g. a repository.
472
460
Both branches present in the directory and the branches of checkouts are
475
463
takes_args = ["location?"]
476
464
def run(self, location=None):
477
from bzrlib.branch import Branch
478
465
from bzrlib.transport import get_transport
479
466
from bzrtools import iter_branch_tree
480
467
if location is None:
482
469
t = get_transport(location)
470
possible_transports = []
483
471
if not t.listable():
484
472
print "Can't list this type of location."
502
490
print "Pulling %s from %s" % (relpath, parent)
504
pullable.pull(Branch.open(parent))
492
branch_t = get_transport(parent, possible_transports)
493
pullable.pull(Branch.open_from_transport(branch_t))
505
494
except Exception, e:
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):
498
class cmd_import(BzrToolsCommand):
528
499
"""Import sources from a directory, tarball or zip file
530
501
This command will import a directory, tarball or zip file into a bzr
531
502
tree, replacing any versioned files already present. If a directory is
532
503
specified, it is used as the target. If the directory does not exist, or
537
508
If the tarball or zip has a single root directory, that directory is
538
509
stripped when extracting the tarball. This is not done for directories.
541
512
takes_args = ['source', 'tree?']
542
513
def run(self, source, tree=None):
543
514
from upstream_import import do_import
544
515
do_import(source, tree)
547
class cmd_cdiff(bzrlib.commands.Command):
518
class cmd_cdiff(BzrToolsCommand):
548
519
"""A color version of bzr's diff"""
549
520
takes_args = property(lambda x: get_cmd_object('diff').takes_args)
550
takes_options = property(lambda x: get_cmd_object('diff').takes_options)
551
def run(*args, **kwargs):
521
takes_options = list(get_cmd_object('diff').takes_options) + [
522
Option('check-style',
523
help='Warn if trailing whitespace or spurious changes have been'
526
def run(self, check_style=False, *args, **kwargs):
552
527
from colordiff import colordiff
553
colordiff(*args, **kwargs)
556
class cmd_baz_import(bzrlib.commands.Command):
528
colordiff(check_style, *args, **kwargs)
531
class cmd_baz_import(BzrToolsCommand):
557
532
"""Import an Arch or Baz archive into a bzr repository.
559
534
This command should be used on local archives (or mirrors) only. It is
560
535
quite slow on remote archives.
562
reuse_history allows you to specify any previous imports you
537
reuse_history allows you to specify any previous imports you
563
538
have done of different archives, which this archive has branches
564
tagged from. This will dramatically reduce the time to convert
539
tagged from. This will dramatically reduce the time to convert
565
540
the archive as it will not have to convert the history already
566
541
converted in that other branch.
581
556
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
582
557
takes_options = ['verbose', Option('prefixes', type=str,
583
help="Prefixes of branches to import, colon-separated"),
584
Option('encoding', type=str,
558
help="Prefixes of branches to import, colon-separated."),
559
Option('encoding', type=str,
585
560
help='Force encoding to specified value. See WARNING.')]
587
562
def run(self, to_root_dir, from_archive, encoding=None, verbose=False,
606
581
are incompatible.
608
583
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
609
takes_options = ['verbose', Option('max-count', type=int),
610
Option('encoding', type=str,
584
takes_options = ['verbose',
585
Option('max-count', type=int,
586
help='Maximim revisions to import at once.'),
587
Option('encoding', type=str,
611
588
help='Force encoding to specified value. See WARNING.')]
613
590
def run(self, to_location, from_branch=None, fast=False, max_count=None,
616
593
from errors import NoPyBaz
618
595
import baz_import
619
baz_import.baz_import_branch(to_location, from_branch, fast,
596
baz_import.baz_import_branch(to_location, from_branch, fast,
620
597
max_count, verbose, encoding, dry_run,
621
598
reuse_history_list)
623
600
print "This command is disabled. Please install PyBaz."
626
class cmd_rspush(bzrlib.commands.Command):
603
class cmd_rspush(BzrToolsCommand):
627
604
"""Upload this branch to another location using rsync.
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.
606
If no location is specified, the last-used location will be used. To
607
prevent dirty trees from being uploaded, rspush will error out if there are
608
unknown files or local changes. It will also error out if the upstream
609
directory is non-empty and not an earlier version of the branch.
634
611
takes_args = ['location?']
635
612
takes_options = [Option('overwrite', help='Ignore differences between'
636
' branches and overwrite unconditionally'),
613
' branches and overwrite unconditionally.'),
637
614
Option('no-tree', help='Do not push the working tree,'
638
615
' just the .bzr.')]
641
618
from bzrlib import workingtree
643
620
cur_branch = workingtree.WorkingTree.open_containing(".")[0]
644
bzrtools.rspush(cur_branch, location, overwrite=overwrite,
621
bzrtools.rspush(cur_branch, location, overwrite=overwrite,
645
622
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)
660
627
cmd_baz_import_branch,
662
629
cmd_branch_history,
667
633
cmd_fetch_ghosts,