~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to command_classes.py

  • Committer: Aaron Bentley
  • Date: 2011-04-26 22:54:07 UTC
  • Revision ID: aaron@aaronbentley.com-20110426225407-3vhag292qui1n98f
Eschew failIfExists/failUnlessExists.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006, 2007 Aaron Bentley <aaron@aaronbentley.com>
2
 
# Copyright (C) 2005, 2006 Canonical Limited.
 
2
# Copyright (C) 2005, 2006, 2011 Canonical Limited.
3
3
# Copyright (C) 2006 Michael Ellerman.
4
4
#
5
5
#    This program is free software; you can redistribute it and/or modify
16
16
#    along with this program; if not, write to the Free Software
17
17
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
 
"""\
20
 
Various useful plugins for working with bzr.
21
 
"""
 
19
import errno
22
20
 
23
21
import bzrlib
24
22
 
28
26
import shelf
29
27
""")
30
28
 
31
 
from version import version_info, __version__
32
29
from command import BzrToolsCommand
33
30
from errors import CommandError
34
31
from patchsource import BzrPatchSource
43
40
from bzrlib.errors import BzrCommandError
44
41
import bzrlib.ignores
45
42
from bzrlib.trace import note
46
 
from bzrlib.option import Option
47
 
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__),
48
 
                                                 "external")))
 
43
from bzrlib.option import Option, RegistryOption
 
44
from bzrlib.workingtree import WorkingTree
49
45
 
50
 
import show_paths
51
46
from command import BzrToolsCommand
52
47
 
53
 
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
54
 
 
55
 
 
56
 
class cmd_clean_tree(BzrToolsCommand):
57
 
    """Remove unwanted files from working tree.
58
 
 
59
 
    By default, only unknown files, not ignored files, are deleted.  Versioned
60
 
    files are never deleted.
61
 
 
62
 
    Another class is 'detritus', which includes files emitted by bzr during
63
 
    normal operations and selftests.  (The value of these files decreases with
64
 
    time.)
65
 
 
66
 
    If no options are specified, unknown files are deleted.  Otherwise, option
67
 
    flags are respected, and may be combined.
68
 
 
69
 
    To check what clean-tree will do, use --dry-run.
70
 
    """
71
 
    takes_options = [Option('ignored', help='Delete all ignored files.'),
72
 
                     Option('detritus', help='Delete conflict files, merge'
73
 
                            ' backups, and failed selftest dirs.'),
74
 
                     Option('unknown',
75
 
                            help='Delete files unknown to bzr (default).'),
76
 
                     Option('dry-run', help='Show files to delete instead of'
77
 
                            ' deleting them.')]
78
 
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False):
79
 
        from clean_tree import clean_tree
80
 
        if not (unknown or ignored or detritus):
81
 
            unknown = True
82
 
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus, 
83
 
                   dry_run=dry_run)
84
 
 
85
48
 
86
49
class cmd_graph_ancestry(BzrToolsCommand):
87
50
    """Produce ancestry graphs using dot.
88
 
    
 
51
 
89
52
    Output format is detected according to file extension.  Some of the more
90
53
    common output formats are html, png, gif, svg, ps.  An extension of '.dot'
91
54
    will cause a dot graph file to be produced.  HTML output has mouseovers
157
120
    takes_options = [Option('no-fix', help="Skip additional synchonization.")]
158
121
    def run(self, branch=None, no_fix=False):
159
122
        from fetch_ghosts import fetch_ghosts
160
 
        fetch_ghosts(branch, no_fix)
 
123
        fetch_ghosts(branch, do_reconcile=not no_fix)
161
124
 
162
125
strip_help="""Strip the smallest prefix containing num leading slashes  from \
163
126
each file name found in the patch file."""
167
130
    """Apply a named patch to the current tree.
168
131
    """
169
132
    takes_args = ['filename?']
170
 
    takes_options = [Option('strip', type=int, help=strip_help),
 
133
    takes_options = [Option('strip', type=int, short_name='p',
 
134
                            help=strip_help),
171
135
                     Option('silent', help='Suppress chatter.')]
172
136
    def run(self, filename=None, strip=None, silent=False):
173
137
        from patch import patch
178
142
        return patch(wt, filename, strip, silent)
179
143
 
180
144
 
181
 
class cmd_shelve(BzrToolsCommand):
 
145
class cmd_shelve1(BzrToolsCommand):
182
146
    """Temporarily set aside some changes from the current tree.
183
147
 
184
148
    Shelve allows you to temporarily put changes you've made "on the shelf",
185
149
    ie. out of the way, until a later time when you can bring them back from
186
 
    the shelf with the 'unshelve' command.
 
150
    the shelf with the 'unshelve1' command.
187
151
 
188
152
    Shelve is intended to help separate several sets of text changes that have
189
153
    been inappropriately mingled.  If you just want to get rid of all changes
190
154
    (text and otherwise) and you don't need to restore them later, use revert.
191
 
    If you want to shelve all text changes at once, use shelve --all.
 
155
    If you want to shelve all text changes at once, use shelve1 --all.
192
156
 
193
 
    By default shelve asks you what you want to shelve, press '?' at the
194
 
    prompt to get help. To shelve everything run shelve --all.
 
157
    By default shelve1 asks you what you want to shelve, press '?' at the
 
158
    prompt to get help. To shelve everything run shelve1 --all.
195
159
 
196
160
    If filenames are specified, only the changes to those files will be
197
161
    shelved, other files will be left untouched.
199
163
    If a revision is specified, changes since that revision will be shelved.
200
164
 
201
165
    You can put multiple items on the shelf. Normally each time you run
202
 
    unshelve the most recently shelved changes will be reinstated. However,
 
166
    unshelve1 the most recently shelved changes will be reinstated. However,
203
167
    you can also unshelve changes in a different order by explicitly
204
 
    specifiying which changes to unshelve. This works best when the changes
 
168
    specifiying which changes to unshelve1. This works best when the changes
205
169
    don't depend on each other.
206
170
 
207
171
    While you have patches on the shelf you can view and manipulate them with
208
 
    the 'shelf' command. Run 'bzr shelf -h' for more info.
 
172
    the 'shelf1' command. Run 'bzr shelf1 -h' for more info.
209
173
    """
210
174
 
211
175
    takes_args = ['file*']
231
195
        return 0
232
196
 
233
197
 
234
 
# The following classes are only used as subcommands for 'shelf', they're
 
198
# The following classes are only used as subcommands for 'shelf1', they're
235
199
# not to be registered directly with bzr.
236
200
 
237
201
class cmd_shelf_list(bzrlib.commands.Command):
273
237
        self.shelf.upgrade()
274
238
 
275
239
 
276
 
class cmd_shelf(BzrToolsCommand):
277
 
    """Perform various operations on your shelved patches. See also shelve."""
 
240
class cmd_shelf1(BzrToolsCommand):
 
241
    """Perform various operations on your shelved patches. See also shelve1."""
278
242
    takes_args = ['subcommand', 'args*']
279
243
 
280
244
    subcommands = [cmd_shelf_list, cmd_shelf_delete, cmd_shelf_switch,
339
303
        return text
340
304
 
341
305
 
342
 
class cmd_unshelve(BzrToolsCommand):
 
306
class cmd_unshelve1(BzrToolsCommand):
343
307
    """Restore shelved changes.
344
308
 
345
309
    By default the most recently shelved changes are restored. However if you
346
310
    specify a patch by name those changes will be restored instead.
347
311
 
348
 
    See 'shelve' for more information.
 
312
    See 'shelve1' for more information.
349
313
    """
350
314
    takes_options = [
351
315
            Option('all', help='Unshelve all changes without prompting.'),
378
342
    --all        --help       --revision   --show-ids
379
343
    bzr bzrtools:287/> status --
380
344
    """
381
 
    def run(self):
 
345
    takes_options = [
 
346
        Option('directory',
 
347
            help='Branch in which to start the shell, '
 
348
                 'rather than the one containing the working directory.',
 
349
            short_name='d',
 
350
            type=unicode,
 
351
            ),
 
352
        ]
 
353
    def run(self, directory=None):
382
354
        import shell
383
 
        return shell.run_shell()
 
355
        return shell.run_shell(directory)
384
356
 
385
357
 
386
358
class cmd_branch_history(BzrToolsCommand):
407
379
 
408
380
    If --branch is specified, the branch will be deleted too, but only if the
409
381
    the branch has no new commits (relative to its parent).
 
382
 
 
383
    If bzr-pipeline is also installed, the --store option will store changes
 
384
    in the branch before deleting the tree.  To restore the changes, do::
 
385
 
 
386
      bzr checkout --lightweight $BRANCH $CHECKOUT
 
387
      bzr switch-pipe -d $CHECKOUT `bzr nick -d $CHECKOUT`
410
388
    """
411
389
    takes_options = [Option("branch", help="Remove associated branch from"
412
390
                                           " repository."),
413
 
                     Option('force', help='Delete tree even if contents are'
414
 
                     ' modified.')]
 
391
                     RegistryOption('change_policy',
 
392
                                    'How to handle changed files',
 
393
                                    lazy_registry =
 
394
                                    ('bzrlib.plugins.bzrtools.zap',
 
395
                                        'change_policy_registry'),
 
396
                                    value_switches=True,
 
397
                                    enum_switch=False)]
415
398
    takes_args = ["checkout"]
416
 
    def run(self, checkout, branch=False, force=False):
417
 
        from zap import zap
418
 
        return zap(checkout, remove_branch=branch, allow_modified=force)
 
399
    def run(self, checkout, branch=False, change_policy=None):
 
400
        from zap import (
 
401
            change_policy_registry,
 
402
            StoreChanges,
 
403
            zap,
 
404
        )
 
405
        if change_policy is None:
 
406
            change_policy = change_policy_registry.get()
 
407
        if change_policy is StoreChanges:
 
408
            try:
 
409
                import bzrlib.plugins.pipeline
 
410
            except ImportError:
 
411
                raise BzrCommandError('--store requires bzr-pipeline.')
 
412
        return zap(checkout, remove_branch=branch, policy=change_policy)
419
413
 
420
414
 
421
415
class cmd_cbranch(BzrToolsCommand):
538
532
    """A color version of bzr's diff"""
539
533
    takes_args = property(lambda x: get_cmd_object('diff').takes_args)
540
534
    takes_options = list(get_cmd_object('diff').takes_options) + [
 
535
        RegistryOption.from_kwargs('color',
 
536
            'Color mode to use.',
 
537
            title='Color Mode', value_switches=False, enum_switch=True,
 
538
            never='Never colorize output.',
 
539
            auto='Only colorize output if terminal supports it and STDOUT is a'
 
540
            ' TTY.',
 
541
            always='Always colorize output (default).'),
541
542
        Option('check-style',
542
543
            help='Warn if trailing whitespace or spurious changes have been'
543
544
                 ' added.')]
544
545
 
545
 
    def run(self, check_style=False, *args, **kwargs):
 
546
    def run(self, color='always', check_style=False, *args, **kwargs):
546
547
        from colordiff import colordiff
547
 
        colordiff(check_style, *args, **kwargs)
 
548
        colordiff(color, check_style, *args, **kwargs)
 
549
 
 
550
 
 
551
class cmd_conflict_diff(BzrToolsCommand):
 
552
 
 
553
    """Compare a conflicted file against BASE."""
 
554
 
 
555
    encoding_type = 'exact'
 
556
    takes_args = ['file*']
 
557
    takes_options = [
 
558
        RegistryOption.from_kwargs('direction', 'Direction of comparison.',
 
559
            value_switches=True, enum_switch=False,
 
560
            other='Compare OTHER against common base.',
 
561
            this='Compare THIS against common base.')]
 
562
 
 
563
    def run(self, file_list, direction='other'):
 
564
        from bzrlib.plugins.bzrtools.colordiff import DiffWriter
 
565
        from conflict_diff import ConflictDiffer
 
566
        dw = DiffWriter(self.outf, check_style=False, color='auto')
 
567
        ConflictDiffer().run(dw, file_list, direction)
548
568
 
549
569
 
550
570
class cmd_rspush(BzrToolsCommand):
591
611
        finally:
592
612
            target_tree.unlock()
593
613
 
594
 
from heads import cmd_heads
595
 
commands = [
596
 
            cmd_branches,
597
 
            cmd_branch_history,
598
 
            cmd_cbranch,
599
 
            cmd_cdiff,
600
 
            cmd_clean_tree,
601
 
            cmd_fetch_ghosts,
602
 
            cmd_graph_ancestry,
603
 
            cmd_heads,
604
 
            cmd_import,
605
 
            cmd_link_tree,
606
 
            cmd_multi_pull,
607
 
            cmd_patch,
608
 
            cmd_rspush,
609
 
            cmd_shelf,
610
 
            cmd_shell,
611
 
            cmd_shelve,
612
 
            cmd_trees,
613
 
            cmd_unshelve,
614
 
            cmd_zap,
615
 
            ]
616
 
 
617
 
 
618
 
if hasattr(bzrlib.commands, 'register_command'):
619
 
    for command in commands:
620
 
        bzrlib.commands.register_command(command)
621
 
 
622
 
 
623
 
def test_suite():
624
 
    from bzrlib.tests.TestUtil import TestLoader
625
 
    import tests
626
 
    from doctest import DocTestSuite, ELLIPSIS
627
 
    from unittest import TestSuite
628
 
    import bzrtools
629
 
    import tests.clean_tree
630
 
    import tests.test_dotgraph
631
 
    import tests.is_clean
632
 
    import tests.test_cbranch
633
 
    import tests.test_link_tree
634
 
    import tests.test_patch
635
 
    import tests.test_rspush
636
 
    import tests.upstream_import
637
 
    import zap
638
 
    import tests.blackbox
639
 
    import tests.shelf_tests
640
 
    result = TestSuite()
641
 
    result.addTest(DocTestSuite(bzrtools, optionflags=ELLIPSIS))
642
 
    result.addTest(tests.clean_tree.test_suite())
643
 
    result.addTest(tests.test_suite())
644
 
    result.addTest(TestLoader().loadTestsFromModule(tests.shelf_tests))
645
 
    result.addTest(tests.blackbox.test_suite())
646
 
    result.addTest(tests.upstream_import.test_suite())
647
 
    result.addTest(zap.test_suite())
648
 
    result.addTest(TestLoader().loadTestsFromModule(tests.test_dotgraph))
649
 
    result.addTest(TestLoader().loadTestsFromModule(tests.is_clean))
650
 
    result.addTest(TestLoader().loadTestsFromModule(tests.test_link_tree))
651
 
    result.addTest(TestLoader().loadTestsFromModule(tests.test_patch))
652
 
    result.addTest(TestLoader().loadTestsFromModule(tests.test_rspush))
653
 
    result.addTest(TestLoader().loadTestsFromModule(tests.test_cbranch))
654
 
    return result
 
614
 
 
615
class cmd_create_mirror(BzrToolsCommand):
 
616
    """Create a mirror of another branch.
 
617
 
 
618
    This is similar to `bzr branch`, but copies more settings, including the
 
619
    submit branch and nickname.
 
620
 
 
621
    It sets the public branch and parent of the target to the source location.
 
622
    """
 
623
 
 
624
    takes_args = ['source', 'target']
 
625
 
 
626
    def run(self, source, target):
 
627
        source_branch = Branch.open(source)
 
628
        from bzrlib.plugins.bzrtools.mirror import create_mirror
 
629
        create_mirror(source_branch, target, [])