~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Aaron Bentley
  • Date: 2005-06-08 22:51:36 UTC
  • Revision ID: abentley@bruiser-20050608225136-c900df20f33fb550
Updated copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
"""\
3
 
Various useful plugins for working with bzr.
4
 
"""
5
 
import bzrlib.commands
6
 
import push
7
 
from errors import CommandError
8
 
from patchsource import BzrPatchSource
9
 
from shelf import Shelf
10
 
import sys
11
 
import os.path
12
 
from bzrlib.option import Option
13
 
import bzrlib.branch
14
 
from bzrlib.errors import BzrCommandError
15
 
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), 
16
 
                                                 "external")))
17
 
from bzrlib import DEFAULT_IGNORE
18
 
 
19
 
 
20
 
DEFAULT_IGNORE.append('./.shelf')
21
 
DEFAULT_IGNORE.append('./.bzr-shelf*')
22
 
 
23
 
 
24
 
Option.OPTIONS['ignored'] = Option('ignored',
25
 
        help='delete all ignored files.')
26
 
Option.OPTIONS['detritus'] = Option('detritus',
27
 
        help='delete conflict files merge backups, and failed selftest dirs.' +
28
 
              '(*.THIS, *.BASE, *.OTHER, *~, *.tmp')
29
 
Option.OPTIONS['dry-run'] = Option('dry-run',
30
 
        help='show files to delete instead of deleting them.')
31
 
 
32
 
class cmd_clean_tree(bzrlib.commands.Command):
33
 
    """Remove unwanted files from working tree.  <BZRTOOLS>
34
 
    Normally, ignored files are left alone.
35
 
    """
36
 
    takes_options = ['ignored', 'detritus', 'dry-run']
37
 
    def run(self, ignored=False, detritus=False, dry_run=False):
38
 
        from clean_tree import clean_tree
39
 
        clean_tree('.', ignored=ignored, detritus=detritus, dry_run=dry_run)
40
 
 
41
 
Option.OPTIONS['merge-branch'] = Option('merge-branch',type=str)
42
 
 
43
 
class cmd_graph_ancestry(bzrlib.commands.Command):
44
 
    """Produce ancestry graphs using dot.  <BZRTOOLS>
45
 
    
46
 
    Output format is detected according to file extension.  Some of the more
47
 
    common output formats are html, png, gif, svg, ps.  An extension of '.dot'
48
 
    will cause a dot graph file to be produced.  HTML output has mouseovers
49
 
    that show the commit message.
50
 
 
51
 
    Branches are labeled r?, where ? is the revno.  If they have no revno,
52
 
    with the last 5 characters of their revision identifier are used instead.
53
 
 
54
 
    The value starting with d is "(maximum) distance from the null revision".
55
 
    
56
 
    If --merge-branch is specified, the two branches are compared and a merge
57
 
    base is selected.
58
 
    
59
 
    Legend:
60
 
    white    normal revision
61
 
    yellow   THIS  history
62
 
    red      OTHER history
63
 
    orange   COMMON history
64
 
    blue     COMMON non-history ancestor
65
 
    green    Merge base (COMMON ancestor farthest from the null revision)
66
 
    dotted   Ghost revision (missing from branch storage)
67
 
 
68
 
    Ancestry is usually collapsed by skipping revisions with a single parent
69
 
    and descendant.  The number of skipped revisions is shown on the arrow.
70
 
    This feature can be disabled with --no-collapse.
71
 
 
72
 
    By default, revisions are ordered by distance from root, but they can be
73
 
    clustered instead using --cluster.
74
 
 
75
 
    If available, rsvg is used to antialias PNG and JPEG output, but this can
76
 
    be disabled with --no-antialias.
77
 
    """
78
 
    takes_args = ['branch', 'file']
79
 
    takes_options = [Option('no-collapse', help="Do not skip simple nodes"), 
80
 
                     Option('no-antialias',
81
 
                     help="Do not use rsvg to produce antialiased output"), 
82
 
                     Option('merge-branch', type=str, 
83
 
                     help="Use this branch to calcuate a merge base"), 
84
 
                     Option('cluster', help="Use clustered output.")]
85
 
    def run(self, branch, file, no_collapse=False, no_antialias=False,
86
 
        merge_branch=None, cluster=False):
87
 
        import graph
88
 
        if cluster:
89
 
            ranking = "cluster"
90
 
        else:
91
 
            ranking = "forced"
92
 
        graph.write_ancestry_file(branch, file, not no_collapse, 
93
 
                                  not no_antialias, merge_branch, ranking)
94
 
 
95
 
class cmd_fetch_ghosts(bzrlib.commands.Command):
96
 
    """Attempt to retrieve ghosts from another branch.  <BZRTOOLS>
97
 
    If the other branch is not supplied, the last-pulled branch is used.
98
 
    """
99
 
    aliases = ['fetch-missing']
100
 
    takes_args = ['branch?']
101
 
    takes_options = [Option('no-fix')]
102
 
    def run(self, branch=None, no_fix=False):
103
 
        from fetch_ghosts import fetch_ghosts
104
 
        fetch_ghosts(branch, no_fix)
105
 
 
106
 
strip_help="""Strip the smallest prefix containing num leading slashes  from \
107
 
each file name found in the patch file."""
108
 
Option.OPTIONS['strip'] = Option('strip', type=int, help=strip_help)
109
 
Option.OPTIONS['bzrdiff'] = Option('bzrdiff',type=None,
110
 
                                help="""Handle extra bzr tags""")
111
 
class cmd_patch(bzrlib.commands.Command):
112
 
    """Apply a named patch to the current tree.  <BZRTOOLS>
113
 
    """
114
 
    takes_args = ['filename?']
115
 
    takes_options = ['strip','bzrdiff']
116
 
    def run(self, filename=None, strip=-1, bzrdiff=0):
117
 
        from patch import patch
118
 
        from bzrlib.workingtree import WorkingTree
119
 
        wt = WorkingTree.open_containing('.')[0]
120
 
        if strip == -1:
121
 
            if bzrdiff: strip = 0
122
 
            else:       strip = 1
123
 
 
124
 
        return patch(wt, filename, strip, legacy= not bzrdiff)
125
 
 
126
 
class cmd_shelve(bzrlib.commands.Command):
127
 
    """Temporarily set aside some changes from the current tree.  <BZRTOOLS>
128
 
 
129
 
    Shelve allows you to temporarily put changes you've made "on the shelf",
130
 
    ie. out of the way, until a later time when you can bring them back from
131
 
    the shelf with the 'unshelve' command.
132
 
 
133
 
    Shelve is intended to help separate several sets of text changes that have
134
 
    been inappropriately mingled.  If you just want to get rid of all changes
135
 
    (text and otherwise) and you don't need to restore them later, use revert.
136
 
    If you want to shelve all text changes at once, use shelve --all.
137
 
 
138
 
    By default shelve asks you what you want to shelve, press '?' at the
139
 
    prompt to get help. To shelve everything run shelve --all.
140
 
 
141
 
    You can put multiple items on the shelf, each time you run unshelve the
142
 
    most recently shelved changes will be reinstated.
143
 
 
144
 
    If filenames are specified, only the changes to those files will be
145
 
    shelved, other files will be left untouched.
146
 
 
147
 
    If a revision is specified, changes since that revision will be shelved.
148
 
    """
149
 
 
150
 
    takes_args = ['file*']
151
 
    takes_options = ['message', 'revision',
152
 
            Option('all', help='Shelve all changes without prompting')]
153
 
 
154
 
    def run(self, all=False, file_list=None, message=None, revision=None):
155
 
        if revision is not None and revision:
156
 
            if len(revision) == 1:
157
 
                revision = revision[0]
158
 
            else:
159
 
                raise CommandError("shelve only accepts a single revision "
160
 
                                  "parameter.")
161
 
 
162
 
        source = BzrPatchSource(revision, file_list)
163
 
        s = Shelf(source.base)
164
 
        s.shelve(source, all, message)
165
 
        return 0
166
 
 
167
 
class cmd_shelf(bzrlib.commands.Command):
168
 
    """Perform various operations on your shelved patches. See also shelve.
169
 
 
170
 
    Subcommands:
171
 
        list   (ls)           List the patches on the current shelf.
172
 
        delete (del) <patch>  Delete a patch from the current shelf.
173
 
        switch       <shelf>  Switch to the named shelf, create it if necessary.
174
 
        show         <patch>  Show the contents of the specified patch.
175
 
        upgrade               Upgrade old format shelves.
176
 
    """
177
 
    takes_args = ['subcommand', 'args*']
178
 
 
179
 
    def run(self, subcommand, args_list):
180
 
        import sys
181
 
 
182
 
        source = BzrPatchSource()
183
 
        s = Shelf(source.base)
184
 
 
185
 
        if subcommand == 'ls' or subcommand == 'list':
186
 
            self.__check_no_args(args_list, "shelf list takes no arguments!")
187
 
            s.list()
188
 
        elif subcommand == 'delete' or subcommand == 'del':
189
 
            self.__check_one_arg(args_list, "shelf delete takes one argument!")
190
 
            s.delete(args_list[0])
191
 
        elif subcommand == 'switch':
192
 
            self.__check_one_arg(args_list, "shelf switch takes one argument!")
193
 
            s = Shelf(source.base, args_list[0])
194
 
            s.make_default()
195
 
        elif subcommand == 'show':
196
 
            self.__check_one_arg(args_list, "shelf show takes one argument!")
197
 
            s.display(args_list[0])
198
 
        elif subcommand == 'upgrade':
199
 
            self.__check_no_args(args_list, "shelf upgrade takes no arguments!")
200
 
            s.upgrade()
201
 
        else:
202
 
            print subcommand, args_list
203
 
            print >>sys.stderr, "Unknown shelf subcommand '%s'" % subcommand
204
 
 
205
 
    def __check_one_arg(self, args, msg):
206
 
        if args is None or len(args) != 1:
207
 
            raise CommandError(msg)
208
 
 
209
 
    def __check_no_args(self, args, msg):
210
 
        if args is not None:
211
 
            raise CommandError(msg)
212
 
 
213
 
 
214
 
class cmd_unshelve(bzrlib.commands.Command):
215
 
    """Restore the most recently shelved changes to current tree.  <BZRTOOLS>
216
 
    See 'shelve' for more information.
217
 
    """
218
 
    takes_options = [
219
 
            Option('all', help='Unshelve all changes without prompting'),
220
 
            Option('force', help='Force unshelving even if errors occur'),
221
 
    ]
222
 
    def run(self, all=False, force=False):
223
 
        source = BzrPatchSource()
224
 
        s = Shelf(source.base)
225
 
        s.unshelve(source, all, force)
226
 
        return 0
227
 
 
228
 
 
229
 
class cmd_shell(bzrlib.commands.Command):
230
 
    """Begin an interactive shell tailored for bzr.  <BZRTOOLS>
231
 
    Bzr commands can be used without typing bzr first, and will be run natively
232
 
    when possible.  Tab completion is tailored for bzr.  The shell prompt shows
233
 
    the branch nick, revno, and path.
234
 
 
235
 
    If it encounters any moderately complicated shell command, it will punt to
236
 
    the system shell.
237
 
 
238
 
    Example:
239
 
    $ bzr shell
240
 
    bzr bzrtools:287/> status
241
 
    modified:
242
 
      __init__.py
243
 
    bzr bzrtools:287/> status --[TAB][TAB]
244
 
    --all        --help       --revision   --show-ids
245
 
    bzr bzrtools:287/> status --
246
 
    """
247
 
    def run(self):
248
 
        import shell
249
 
        return shell.run_shell()
250
 
 
251
 
class cmd_branch_history(bzrlib.commands.Command):
252
 
    """\
253
 
    Display the development history of a branch  <BZRTOOLS>.
254
 
 
255
 
    Each different committer or branch nick is considered a different line of
256
 
    development.  Committers are treated as the same if they have the same
257
 
    name, or if they have the same email address.
258
 
    """
259
 
    takes_args = ["branch?"]
260
 
    def run(self, branch=None):
261
 
        from branchhistory import branch_history 
262
 
        return branch_history(branch)
263
 
 
264
 
 
265
 
class cmd_zap(bzrlib.commands.Command):
266
 
    """\
267
 
    Remove a checkout, if it can be done safely. <BZRTOOLS>
268
 
 
269
 
    This command will remove a checkout without losing data.  That means
270
 
    it only removes checkouts, and only if they have no uncommitted changes.
271
 
    """
272
 
    takes_options = [Option("branch", help="Remove associtated branch from"
273
 
                                           " repository")]
274
 
    takes_args = ["checkout"]
275
 
    def run(self, checkout, branch=False):
276
 
        from zap import zap
277
 
        return zap(checkout, remove_branch=branch)
278
 
 
279
 
 
280
 
class cmd_cbranch(bzrlib.commands.Command):
281
 
    """
282
 
    Create a new checkout, associated with a new repository branch. <BZRTOOLS>
283
 
    
284
 
    When you cbranch, bzr looks up the repository associated with your current
285
 
    directory in branches.conf.  It creates a new branch in that repository
286
 
    with the same name and relative path as the checkout you request.
287
 
 
288
 
    The branches.conf parameter is "cbranch_root".  So if you want 
289
 
    cbranch operations in /home/jrandom/bigproject to produce branches in 
290
 
    /home/jrandom/bigproject/repository, you'd add this:
291
 
 
292
 
    [/home/jrandom/bigproject]
293
 
    cbranch_root = /home/jrandom/bigproject/repository
294
 
 
295
 
    Note that if "/home/jrandom/bigproject/repository" isn't a repository,
296
 
    standalone branches will be produced.  Standalone branches will also
297
 
    be produced if the source branch is in 0.7 format (or earlier).
298
 
    """
299
 
    takes_options = [Option("lightweight", 
300
 
                            help="Create a lightweight checkout")]
301
 
    takes_args = ["source", "target?"]
302
 
    def run(self, source, target=None, lightweight=False):
303
 
        from cbranch import cbranch
304
 
        return cbranch(source, target, lightweight=lightweight)
305
 
 
306
 
 
307
 
class cmd_branches(bzrlib.commands.Command):
308
 
    """Scan a location for branches <BZRTOOLS>"""
309
 
    takes_args = ["location?"]
310
 
    def run(self, location=None):
311
 
        from branches import branches
312
 
        return branches(location)
313
 
 
314
 
 
315
 
class cmd_multi_pull(bzrlib.commands.Command):
316
 
    """Pull all the branches under a location, e.g. a repository. <BZRTOOLS>
317
 
    
318
 
    Both branches present in the directory and the branches of checkouts are
319
 
    pulled.
320
 
    """
321
 
    takes_args = ["location?"]
322
 
    def run(self, location=None):
323
 
        from bzrlib.branch import Branch
324
 
        from bzrlib.transport import get_transport
325
 
        from bzrtools import iter_branch_tree
326
 
        if location is None:
327
 
            location = '.'
328
 
        t = get_transport(location)
329
 
        if not t.listable():
330
 
            print "Can't list this type of location."
331
 
            return 3
332
 
        for branch, wt in iter_branch_tree(t):
333
 
            if wt is None:
334
 
                pullable = branch
335
 
            else:
336
 
                pullable = wt
337
 
            parent = branch.get_parent()
338
 
            if parent is None:
339
 
                continue
340
 
            if wt is not None:
341
 
                base = wt.basedir
342
 
            else:
343
 
                base = branch.base
344
 
            if base.startswith(t.base):
345
 
                relpath = base[len(t.base):].rstrip('/')
346
 
            else:
347
 
                relpath = base
348
 
            print "Pulling %s from %s" % (relpath, parent)
349
 
            try:
350
 
                pullable.pull(Branch.open(parent))
351
 
            except Exception, e:
352
 
                print e
353
 
 
354
 
 
355
 
commands = [cmd_shelve, cmd_unshelve, cmd_shelf, cmd_clean_tree,
356
 
            cmd_graph_ancestry, cmd_fetch_ghosts, cmd_patch, cmd_shell,
357
 
            cmd_branch_history, cmd_zap, cmd_cbranch, cmd_branches, 
358
 
            cmd_multi_pull]
359
 
 
360
 
 
361
 
command_decorators = []
362
 
 
363
 
 
364
 
import bzrlib.builtins
365
 
if not hasattr(bzrlib.builtins, "cmd_push"):
366
 
    commands.append(push.cmd_push)
367
 
else:
368
 
    command_decorators.append(push.cmd_push)
369
 
 
370
 
from errors import NoPyBaz
371
 
try:
372
 
    import baz_import
373
 
    commands.append(baz_import.cmd_baz_import_branch)
374
 
    commands.append(baz_import.cmd_baz_import)
375
 
 
376
 
except NoPyBaz:
377
 
    class cmd_baz_import_branch(bzrlib.commands.Command):
378
 
        """Disabled. (Requires PyBaz)   <BZRTOOLS>"""
379
 
        takes_args = ['to_location?', 'from_branch?', 'reuse_history*']
380
 
        takes_options = ['verbose', Option('max-count', type=int)]
381
 
        def run(self, to_location=None, from_branch=None, fast=False, 
382
 
                max_count=None, verbose=False, dry_run=False,
383
 
                reuse_history_list=[]):
384
 
            print "This command is disabled.  Please install PyBaz."
385
 
 
386
 
 
387
 
    class cmd_baz_import(bzrlib.commands.Command):
388
 
        """Disabled. (Requires PyBaz)   <BZRTOOLS>"""
389
 
        takes_args = ['to_root_dir?', 'from_archive?', 'reuse_history*']
390
 
        takes_options = ['verbose', Option('prefixes', type=str,
391
 
                         help="Prefixes of branches to import")]
392
 
        def run(self, to_root_dir=None, from_archive=None, verbose=False,
393
 
                reuse_history_list=[], prefixes=None):
394
 
                print "This command is disabled.  Please install PyBaz."
395
 
    commands.extend((cmd_baz_import_branch, cmd_baz_import))
396
 
 
397
 
 
398
 
if hasattr(bzrlib.commands, 'register_command'):
399
 
    for command in commands:
400
 
        bzrlib.commands.register_command(command)
401
 
    for command in command_decorators:
402
 
        command._original_command = bzrlib.commands.register_command(
403
 
            command, True)
404
 
 
405
 
 
406
 
def test_suite():
407
 
    import baz_import
408
 
    from bzrlib.tests.TestUtil import TestLoader
409
 
    import tests
410
 
    from doctest import DocTestSuite, ELLIPSIS
411
 
    from unittest import TestSuite
412
 
    import clean_tree
413
 
    import zap
414
 
    import tests.blackbox
415
 
    import tests.shelf_tests
416
 
    result = TestSuite()
417
 
    result.addTest(DocTestSuite(bzrtools, optionflags=ELLIPSIS))
418
 
    result.addTest(clean_tree.test_suite())
419
 
    result.addTest(DocTestSuite(baz_import))
420
 
    result.addTest(tests.test_suite())
421
 
    result.addTest(TestLoader().loadTestsFromModule(tests.shelf_tests))
422
 
    result.addTest(tests.blackbox.test_suite())
423
 
    result.addTest(zap.test_suite())
424
 
    return result