~abentley/bzrtools/bzrtools.dev

504 by Aaron Bentley
Clarify version mismatch warnings
1
# Copyright (C) 2005, 2006, 2007 Aaron Bentley <aaron.bentley@utoronto.ca>
460 by Aaron Bentley
Add encoding parameter everywhere
2
# Copyright (C) 2005, 2006 Canonical Limited.
3
# Copyright (C) 2006 Michael Ellerman.
4
#
5
#    This program is free software; you can redistribute it and/or modify
6
#    it under the terms of the GNU General Public License as published by
7
#    the Free Software Foundation; either version 2 of the License, or
8
#    (at your option) any later version.
9
#
10
#    This program is distributed in the hope that it will be useful,
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
#    GNU General Public License for more details.
14
#
15
#    You should have received a copy of the GNU General Public License
16
#    along with this program; if not, write to the Free Software
17
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
246 by Aaron Bentley
Merged shelf_v2
19
"""\
20
Various useful plugins for working with bzr.
21
"""
428 by Aaron Bentley
Add version number, check against bzrlib version
22
23
import bzrlib
24
25
502 by Aaron Bentley
Update versions to 0.15
26
__version__ = '0.15.0'
428 by Aaron Bentley
Add version number, check against bzrlib version
27
28
29
version_info = tuple(int(n) for n in __version__.split('.'))
30
31
32
def check_bzrlib_version(desired):
33
    """Check that bzrlib is compatible.
34
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.
39
    """
40
    desired_plus = (desired[0], desired[1]+1)
41
    bzrlib_version = bzrlib.version_info[:2]
42
    if bzrlib_version == desired:
43
        return
44
    try:
45
        from bzrlib.trace import warning
46
    except ImportError:
47
        # get the message out any way we can
48
        from warnings import warn as warning
49
    if bzrlib_version < desired:
504 by Aaron Bentley
Clarify version mismatch warnings
50
        warning('Installed Bazzar version %s is too old to be used with'
51
                ' plugin \n'
52
                '"Bzrtools" %s.' % (bzrlib.__version__, __version__))
428 by Aaron Bentley
Add version number, check against bzrlib version
53
        # Not using BzrNewError, because it may not exist.
447 by Aaron Bentley
Fix up test and selftest, make robust against missing PyBaz
54
        raise Exception, ('Version mismatch', version_info)
428 by Aaron Bentley
Add version number, check against bzrlib version
55
    else:
504 by Aaron Bentley
Clarify version mismatch warnings
56
        warning('Plugin "Bzrtools" is not up to date with installed Bazaar'
57
                ' version %s.\n'
58
                ' There should be a newer version of Bzrtools available, e.g.'
59
                ' %i.%i.'
428 by Aaron Bentley
Add version number, check against bzrlib version
60
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
61
        if bzrlib_version != desired_plus:
62
            raise Exception, 'Version mismatch'
63
64
65
check_bzrlib_version(version_info[:2])
66
67
447 by Aaron Bentley
Fix up test and selftest, make robust against missing PyBaz
68
from errors import CommandError, NoPyBaz
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
69
from patchsource import BzrPatchSource
246 by Aaron Bentley
Merged shelf_v2
70
from shelf import Shelf
71
import sys
72
import os.path
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
73
74
import bzrlib.builtins
75
import bzrlib.commands
410 by Aaron Bentley
Ensure the option settings come from the right 'diff' in colordiff
76
from bzrlib.commands import get_cmd_object
0.1.39 by Michael Ellerman
Fix shelve and unshelve to pass location to Shelf().
77
from bzrlib.errors import BzrCommandError
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
78
from bzrlib.help import command_usage
423 by Aaron Bentley
Add runtime ignores for shelf
79
import bzrlib.ignores
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
80
from bzrlib.option import Option
147.1.41 by Aaron Bentley
Merge from mainline
81
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), 
147.4.37 by Robert Collins
Convert push to rpush.
82
                                                 "external")))
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
83
465 by Aaron Bentley
Add show-paths command from Alexander Belchenko
84
import show_paths
85
0.7.2 by Michael Ellerman
Convert from DEFAULT_IGNORES to bzrlib.ignores.add_runtime_ignores().
86
bzrlib.ignores.add_runtime_ignores(['./.shelf'])
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
87
246 by Aaron Bentley
Merged shelf_v2
88
89
class cmd_clean_tree(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
90
    """Remove unwanted files from working tree.
417 by Aaron Bentley
Update clean-tree docs
91
92
    By default, only unknown files, not ignored files, are deleted.  Versioned
93
    files are never deleted.
94
95
    Another class is 'detritus', which includes files emitted by bzr during
96
    normal operations and selftests.  (The value of these files decreases with
97
    time.)
98
99
    If no options are specified, unknown files are deleted.  Otherwise, option
100
    flags are respected, and may be combined.
101
102
    To check what clean-tree will do, use --dry-run.
246 by Aaron Bentley
Merged shelf_v2
103
    """
386 by Aaron Bentley
Stop adding global options
104
    takes_options = [Option('ignored', help='delete all ignored files.'), 
417 by Aaron Bentley
Update clean-tree docs
105
                     Option('detritus', help='delete conflict files, merge'
106
                            ' backups, and failed selftest dirs.'), 
416 by Aaron Bentley
clean-tree --detritus no longer implies --unknown
107
                     Option('unknown', 
108
                            help='delete files unknown to bzr.  (default)'),
386 by Aaron Bentley
Stop adding global options
109
                     Option('dry-run', help='show files to delete instead of'
110
                            ' deleting them.')]
415.1.1 by Adeodato Simó
Make clean-tree --detritus or --ignored not delete also unknown files,
111
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False):
246 by Aaron Bentley
Merged shelf_v2
112
        from clean_tree import clean_tree
415.1.1 by Adeodato Simó
Make clean-tree --detritus or --ignored not delete also unknown files,
113
        if not (unknown or ignored or detritus):
114
            unknown = True
416 by Aaron Bentley
clean-tree --detritus no longer implies --unknown
115
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus, 
116
                   dry_run=dry_run)
246 by Aaron Bentley
Merged shelf_v2
117
445 by Aaron Bentley
Remove shove, tweak imports, docs
118
246 by Aaron Bentley
Merged shelf_v2
119
class cmd_graph_ancestry(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
120
    """Produce ancestry graphs using dot.
246 by Aaron Bentley
Merged shelf_v2
121
    
122
    Output format is detected according to file extension.  Some of the more
296 by Aaron Bentley
Updated graph-ancestry help
123
    common output formats are html, png, gif, svg, ps.  An extension of '.dot'
124
    will cause a dot graph file to be produced.  HTML output has mouseovers
125
    that show the commit message.
246 by Aaron Bentley
Merged shelf_v2
126
127
    Branches are labeled r?, where ? is the revno.  If they have no revno,
128
    with the last 5 characters of their revision identifier are used instead.
296 by Aaron Bentley
Updated graph-ancestry help
129
130
    The value starting with d is "(maximum) distance from the null revision".
246 by Aaron Bentley
Merged shelf_v2
131
    
132
    If --merge-branch is specified, the two branches are compared and a merge
133
    base is selected.
134
    
135
    Legend:
136
    white    normal revision
137
    yellow   THIS  history
138
    red      OTHER history
139
    orange   COMMON history
140
    blue     COMMON non-history ancestor
296 by Aaron Bentley
Updated graph-ancestry help
141
    green    Merge base (COMMON ancestor farthest from the null revision)
142
    dotted   Ghost revision (missing from branch storage)
246 by Aaron Bentley
Merged shelf_v2
143
296 by Aaron Bentley
Updated graph-ancestry help
144
    Ancestry is usually collapsed by skipping revisions with a single parent
246 by Aaron Bentley
Merged shelf_v2
145
    and descendant.  The number of skipped revisions is shown on the arrow.
146
    This feature can be disabled with --no-collapse.
147
148
    By default, revisions are ordered by distance from root, but they can be
149
    clustered instead using --cluster.
150
151
    If available, rsvg is used to antialias PNG and JPEG output, but this can
152
    be disabled with --no-antialias.
153
    """
154
    takes_args = ['branch', 'file']
296 by Aaron Bentley
Updated graph-ancestry help
155
    takes_options = [Option('no-collapse', help="Do not skip simple nodes"), 
156
                     Option('no-antialias',
157
                     help="Do not use rsvg to produce antialiased output"), 
158
                     Option('merge-branch', type=str, 
159
                     help="Use this branch to calcuate a merge base"), 
476.1.2 by Aaron Bentley
graph-ancestry can restrict the number of nodes shown by distance
160
                     Option('cluster', help="Use clustered output."),
161
                     Option('max-distance', help="Show no nodes farther than this",
162
                            type=int)]
246 by Aaron Bentley
Merged shelf_v2
163
    def run(self, branch, file, no_collapse=False, no_antialias=False,
476.1.2 by Aaron Bentley
graph-ancestry can restrict the number of nodes shown by distance
164
        merge_branch=None, cluster=False, max_distance=None):
246 by Aaron Bentley
Merged shelf_v2
165
        import graph
166
        if cluster:
167
            ranking = "cluster"
168
        else:
169
            ranking = "forced"
170
        graph.write_ancestry_file(branch, file, not no_collapse, 
476.1.2 by Aaron Bentley
graph-ancestry can restrict the number of nodes shown by distance
171
                                  not no_antialias, merge_branch, ranking, 
172
                                  max_distance=max_distance)
246 by Aaron Bentley
Merged shelf_v2
173
445 by Aaron Bentley
Remove shove, tweak imports, docs
174
246 by Aaron Bentley
Merged shelf_v2
175
class cmd_fetch_ghosts(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
176
    """Attempt to retrieve ghosts from another branch.
246 by Aaron Bentley
Merged shelf_v2
177
    If the other branch is not supplied, the last-pulled branch is used.
178
    """
179
    aliases = ['fetch-missing']
180
    takes_args = ['branch?']
275.1.3 by Daniel Silverstone
Fix up fetch_ghosts to lock the branches, and to invoke bzr fix if it fetches any ghosts into the tree
181
    takes_options = [Option('no-fix')]
182
    def run(self, branch=None, no_fix=False):
246 by Aaron Bentley
Merged shelf_v2
183
        from fetch_ghosts import fetch_ghosts
275.1.3 by Daniel Silverstone
Fix up fetch_ghosts to lock the branches, and to invoke bzr fix if it fetches any ghosts into the tree
184
        fetch_ghosts(branch, no_fix)
246 by Aaron Bentley
Merged shelf_v2
185
186
strip_help="""Strip the smallest prefix containing num leading slashes  from \
187
each file name found in the patch file."""
445 by Aaron Bentley
Remove shove, tweak imports, docs
188
189
246 by Aaron Bentley
Merged shelf_v2
190
class cmd_patch(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
191
    """Apply a named patch to the current tree.
246 by Aaron Bentley
Merged shelf_v2
192
    """
193
    takes_args = ['filename?']
496 by Aaron Bentley
Add --silent option to patch
194
    takes_options = [Option('strip', type=int, help=strip_help),
195
                     Option('silent', help='Suppress chatter')]
196
    def run(self, filename=None, strip=None, silent=False):
246 by Aaron Bentley
Merged shelf_v2
197
        from patch import patch
340 by Aaron Bentley
Fixed patch on checkouts
198
        from bzrlib.workingtree import WorkingTree
199
        wt = WorkingTree.open_containing('.')[0]
473 by Aaron Bentley
Clean up patch command (support http urls again)
200
        if strip is None:
201
            strip = 0
496 by Aaron Bentley
Add --silent option to patch
202
        return patch(wt, filename, strip, silent)
246 by Aaron Bentley
Merged shelf_v2
203
427 by Aaron Bentley
Merge latest changes from Shelf
204
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
205
class cmd_shelve(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
206
    """Temporarily set aside some changes from the current tree.
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
207
208
    Shelve allows you to temporarily put changes you've made "on the shelf",
209
    ie. out of the way, until a later time when you can bring them back from
210
    the shelf with the 'unshelve' command.
211
289 by Aaron Bentley
Updated shelf help
212
    Shelve is intended to help separate several sets of text changes that have
213
    been inappropriately mingled.  If you just want to get rid of all changes
214
    (text and otherwise) and you don't need to restore them later, use revert.
215
    If you want to shelve all text changes at once, use shelve --all.
216
0.1.90 by Michael Ellerman
Update help text to try and be clearer, some stolen from bzrtools.
217
    By default shelve asks you what you want to shelve, press '?' at the
218
    prompt to get help. To shelve everything run shelve --all.
219
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
220
    If filenames are specified, only the changes to those files will be
221
    shelved, other files will be left untouched.
222
223
    If a revision is specified, changes since that revision will be shelved.
0.1.113 by Michael Ellerman
Support for unshelving in arbitrary order.
224
225
    You can put multiple items on the shelf. Normally each time you run
226
    unshelve the most recently shelved changes will be reinstated. However,
227
    you can also unshelve changes in a different order by explicitly
228
    specifiying which changes to unshelve. This works best when the changes
229
    don't depend on each other.
0.7.3 by Michael Ellerman
Add a reference from 'shelve' help to 'shelf'.
230
231
    While you have patches on the shelf you can view and manipulate them with
232
    the 'shelf' command. Run 'bzr shelf -h' for more info.
0.1.90 by Michael Ellerman
Update help text to try and be clearer, some stolen from bzrtools.
233
    """
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
234
235
    takes_args = ['file*']
0.1.90 by Michael Ellerman
Update help text to try and be clearer, some stolen from bzrtools.
236
    takes_options = ['message', 'revision',
423.1.4 by Aaron Bentley
Add --no-color option to shelf
237
            Option('all', help='Shelve all changes without prompting'), 
238
            Option('no-color', help='Never display changes in color')]
0.1.90 by Michael Ellerman
Update help text to try and be clearer, some stolen from bzrtools.
239
423.1.4 by Aaron Bentley
Add --no-color option to shelf
240
    def run(self, all=False, file_list=None, message=None, revision=None,
241
            no_color=False):
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
242
        if revision is not None and revision:
243
            if len(revision) == 1:
244
                revision = revision[0]
245
            else:
246
                raise CommandError("shelve only accepts a single revision "
247
                                  "parameter.")
248
249
        source = BzrPatchSource(revision, file_list)
0.1.74 by Michael Ellerman
Adapt to BzrDir changes and deprecation of show_diff().
250
        s = Shelf(source.base)
423.1.4 by Aaron Bentley
Add --no-color option to shelf
251
        s.shelve(source, all, message, no_color)
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
252
        return 0
253
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
254
255
# The following classes are only used as subcommands for 'shelf', they're
256
# not to be registered directly with bzr.
257
258
class cmd_shelf_list(bzrlib.commands.Command):
259
    """List the patches on the current shelf."""
260
    aliases = ['list', 'ls']
261
    def run(self):
262
        self.shelf.list()
263
264
265
class cmd_shelf_delete(bzrlib.commands.Command):
266
    """Delete the patch from the current shelf."""
267
    aliases = ['delete', 'del']
268
    takes_args = ['patch']
269
    def run(self, patch):
270
        self.shelf.delete(patch)
271
272
273
class cmd_shelf_switch(bzrlib.commands.Command):
274
    """Switch to the other shelf, create it if necessary."""
275
    aliases = ['switch']
0.1.117 by Michael Ellerman
Arg names with hyphens don't seem to work (broke shelf switch).
276
    takes_args = ['othershelf']
277
    def run(self, othershelf):
278
        s = Shelf(self.shelf.base, othershelf)
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
279
        s.make_default()
280
281
282
class cmd_shelf_show(bzrlib.commands.Command):
0.1.110 by Michael Ellerman
Make the patch argument to 'shelf show' optional.
283
    """Show the contents of the specified or topmost patch."""
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
284
    aliases = ['show', 'cat', 'display']
0.1.110 by Michael Ellerman
Make the patch argument to 'shelf show' optional.
285
    takes_args = ['patch?']
286
    def run(self, patch=None):
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
287
        self.shelf.display(patch)
288
289
290
class cmd_shelf_upgrade(bzrlib.commands.Command):
291
    """Upgrade old format shelves."""
292
    aliases = ['upgrade']
293
    def run(self):
294
        self.shelf.upgrade()
295
296
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
297
class cmd_shelf(bzrlib.commands.Command):
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
298
    """Perform various operations on your shelved patches. See also shelve."""
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
299
    takes_args = ['subcommand', 'args*']
300
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
301
    subcommands = [cmd_shelf_list, cmd_shelf_delete, cmd_shelf_switch,
302
        cmd_shelf_show, cmd_shelf_upgrade]
303
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
304
    def run(self, subcommand, args_list):
305
        import sys
306
456.1.1 by Aaron Bentley
Fix shelf ls with no args (Alexander Belchenko)
307
        if args_list is None:
308
            args_list = []
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
309
        cmd = self._get_cmd_object(subcommand)
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
310
        source = BzrPatchSource()
0.1.74 by Michael Ellerman
Adapt to BzrDir changes and deprecation of show_diff().
311
        s = Shelf(source.base)
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
312
        cmd.shelf = s
313
        return cmd.run_argv_aliases(args_list)
314
315
    def _get_cmd_object(self, cmd_name):
316
        for cmd_class in self.subcommands:
317
            for alias in cmd_class.aliases:
318
                if alias == cmd_name:
319
                    return cmd_class()
320
        raise CommandError("Unknown shelf subcommand '%s'" % cmd_name)
321
322
    def help(self):
0.1.111 by Michael Ellerman
Make help for subcommands more readable, print options in help also.
323
        text = ["%s\n\nSubcommands:\n" % self.__doc__]
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
324
325
        for cmd_class in self.subcommands:
0.1.111 by Michael Ellerman
Make help for subcommands more readable, print options in help also.
326
            text.extend(self.sub_help(cmd_class) + ['\n'])
327
328
        return ''.join(text)
329
330
    def sub_help(self, cmd_class):
331
        text = []
332
        cmd_obj = cmd_class()
333
        indent = 2 * ' '
334
335
        usage = command_usage(cmd_obj)
336
        usage = usage.replace('bzr shelf-', '')
337
        text.append('%s%s\n' % (indent, usage))
338
339
        text.append('%s%s\n' % (2 * indent, cmd_class.__doc__))
340
341
        # Somewhat copied from bzrlib.help.help_on_command_options
342
        option_help = []
343
        for option_name, option in sorted(cmd_obj.options().items()):
344
            if option_name == 'help':
345
                continue
346
            option_help.append('%s--%s' % (3 * indent, option_name))
347
            if option.type is not None:
348
                option_help.append(' %s' % option.argname.upper())
349
            if option.short_name():
350
                option_help.append(', -%s' % option.short_name())
351
            option_help.append('%s%s\n' % (2 * indent, option.help))
352
353
        if len(option_help) > 0:
354
            text.append('%soptions:\n' % (2 * indent))
355
            text.extend(option_help)
356
357
        return text
0.1.109 by Michael Ellerman
Hijack the bzr command infrastructure to do subcommands for 'shelf'.
358
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
359
360
class cmd_unshelve(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
361
    """Restore shelved changes.
0.1.113 by Michael Ellerman
Support for unshelving in arbitrary order.
362
363
    By default the most recently shelved changes are restored. However if you
364
    specify a patch by name those changes will be restored instead.
365
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
366
    See 'shelve' for more information.
367
    """
0.1.91 by Michael Ellerman
Add --force option to unshelve, which runs the shelved changes through
368
    takes_options = [
369
            Option('all', help='Unshelve all changes without prompting'),
370
            Option('force', help='Force unshelving even if errors occur'),
423.1.4 by Aaron Bentley
Add --no-color option to shelf
371
            Option('no-color', help='Never display changes in color')
372
        ]
0.1.113 by Michael Ellerman
Support for unshelving in arbitrary order.
373
    takes_args = ['patch?']
423.1.4 by Aaron Bentley
Add --no-color option to shelf
374
    def run(self, patch=None, all=False, force=False, no_color=False):
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
375
        source = BzrPatchSource()
0.1.74 by Michael Ellerman
Adapt to BzrDir changes and deprecation of show_diff().
376
        s = Shelf(source.base)
423.1.4 by Aaron Bentley
Add --no-color option to shelf
377
        s.unshelve(source, patch, all, force, no_color)
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
378
        return 0
379
0.1.22 by Michael Ellerman
Add __init__.py, put cmd_shelve/unshelve in there.
380
249 by Aaron Bentley
Got the shell basics working properly
381
class cmd_shell(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
382
    """Begin an interactive shell tailored for bzr.
287 by Aaron Bentley
Added shell docstring
383
    Bzr commands can be used without typing bzr first, and will be run natively
384
    when possible.  Tab completion is tailored for bzr.  The shell prompt shows
385
    the branch nick, revno, and path.
386
387
    If it encounters any moderately complicated shell command, it will punt to
388
    the system shell.
389
390
    Example:
391
    $ bzr shell
392
    bzr bzrtools:287/> status
393
    modified:
394
      __init__.py
395
    bzr bzrtools:287/> status --[TAB][TAB]
396
    --all        --help       --revision   --show-ids
397
    bzr bzrtools:287/> status --
398
    """
249 by Aaron Bentley
Got the shell basics working properly
399
    def run(self):
400
        import shell
281 by Aaron Bentley
Handled whitespace branch names better
401
        return shell.run_shell()
246 by Aaron Bentley
Merged shelf_v2
402
445 by Aaron Bentley
Remove shove, tweak imports, docs
403
292 by Aaron Bentley
Introduced branch-history command
404
class cmd_branch_history(bzrlib.commands.Command):
405
    """\
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
406
    Display the development history of a branch.
292 by Aaron Bentley
Introduced branch-history command
407
293 by Aaron Bentley
Updated help
408
    Each different committer or branch nick is considered a different line of
409
    development.  Committers are treated as the same if they have the same
410
    name, or if they have the same email address.
292 by Aaron Bentley
Introduced branch-history command
411
    """
412
    takes_args = ["branch?"]
413
    def run(self, branch=None):
414
        from branchhistory import branch_history 
415
        return branch_history(branch)
416
345 by Aaron Bentley
Added zap command
417
418
class cmd_zap(bzrlib.commands.Command):
419
    """\
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
420
    Remove a lightweight checkout, if it can be done safely.
411 by Aaron Bentley
Update zap documentation
421
422
    This command will remove a lightweight checkout without losing data.  That
423
    means it only removes lightweight checkouts, and only if they have no
424
    uncommitted changes.
425
426
    If --branch is specified, the branch will be deleted too, but only if the
427
    the branch has no new commits (relative to its parent).
345 by Aaron Bentley
Added zap command
428
    """
355.1.1 by Aaron Bentley
Provided --branch option to for zapping branches
429
    takes_options = [Option("branch", help="Remove associtated branch from"
430
                                           " repository")]
345 by Aaron Bentley
Added zap command
431
    takes_args = ["checkout"]
355.1.1 by Aaron Bentley
Provided --branch option to for zapping branches
432
    def run(self, checkout, branch=False):
345 by Aaron Bentley
Added zap command
433
        from zap import zap
355.1.1 by Aaron Bentley
Provided --branch option to for zapping branches
434
        return zap(checkout, remove_branch=branch)
345 by Aaron Bentley
Added zap command
435
436
349 by Aaron Bentley
Added cbranch command
437
class cmd_cbranch(bzrlib.commands.Command):
438
    """
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
439
    Create a new checkout, associated with a new repository branch.
349 by Aaron Bentley
Added cbranch command
440
    
486 by Aaron Bentley
Support deep cbranch hierarcy via appendpath
441
    When you cbranch, bzr looks up a target location in locations.conf, and
442
    creates the branch there.
443
444
    In your locations.conf, add the following lines:
445
    [/working_directory_root]
446
    cbranch_target = /branch_root
447
    cbranch_target:policy = appendpath
448
449
    This will mean that if you run "bzr cbranch foo/bar foo/baz" in the
450
    working directory root, the branch will be created in 
451
    "/branch_root/foo/baz"
452
453
    NOTE: cbranch also supports "cbranch_root", but that behaviour is
454
    deprecated.
349 by Aaron Bentley
Added cbranch command
455
    """
355.1.2 by Aaron Bentley
cbranch mimics checkout wrt --lightweight
456
    takes_options = [Option("lightweight", 
418 by Aaron Bentley
Cbranch takes a revision option
457
                            help="Create a lightweight checkout"), 'revision']
355.1.2 by Aaron Bentley
cbranch mimics checkout wrt --lightweight
458
    takes_args = ["source", "target?"]
418 by Aaron Bentley
Cbranch takes a revision option
459
    def run(self, source, target=None, lightweight=False, revision=None):
349 by Aaron Bentley
Added cbranch command
460
        from cbranch import cbranch
418 by Aaron Bentley
Cbranch takes a revision option
461
        return cbranch(source, target, lightweight=lightweight, 
462
                       revision=revision)
355.1.2 by Aaron Bentley
cbranch mimics checkout wrt --lightweight
463
349 by Aaron Bentley
Added cbranch command
464
352 by Aaron Bentley
Added branches subcommand
465
class cmd_branches(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
466
    """Scan a location for branches"""
352 by Aaron Bentley
Added branches subcommand
467
    takes_args = ["location?"]
468
    def run(self, location=None):
469
        from branches import branches
470
        return branches(location)
471
353 by Aaron Bentley
Added multi-pull, working on branches and checkouts
472
473
class cmd_multi_pull(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
474
    """Pull all the branches under a location, e.g. a repository.
353 by Aaron Bentley
Added multi-pull, working on branches and checkouts
475
    
476
    Both branches present in the directory and the branches of checkouts are
477
    pulled.
478
    """
479
    takes_args = ["location?"]
480
    def run(self, location=None):
481
        from bzrlib.branch import Branch
482
        from bzrlib.transport import get_transport
483
        from bzrtools import iter_branch_tree
484
        if location is None:
485
            location = '.'
486
        t = get_transport(location)
487
        if not t.listable():
488
            print "Can't list this type of location."
489
            return 3
490
        for branch, wt in iter_branch_tree(t):
491
            if wt is None:
492
                pullable = branch
493
            else:
494
                pullable = wt
495
            parent = branch.get_parent()
496
            if parent is None:
497
                continue
498
            if wt is not None:
499
                base = wt.basedir
500
            else:
501
                base = branch.base
502
            if base.startswith(t.base):
503
                relpath = base[len(t.base):].rstrip('/')
504
            else:
505
                relpath = base
506
            print "Pulling %s from %s" % (relpath, parent)
507
            try:
508
                pullable.pull(Branch.open(parent))
509
            except Exception, e:
510
                print e
511
512
360.1.3 by Aaron Bentley
Add experimental branch-mark command
513
class cmd_branch_mark(bzrlib.commands.Command):
514
    """
515
    Add, view or list branch markers <EXPERIMENTAL>
516
517
    To add a mark, do 'bzr branch-mark MARK'.
518
    To list marks, do 'bzr branch-mark' (this lists all marks for the branch's
519
    repository).
520
    To delete a mark, do 'bzr branch-mark --delete MARK'
521
522
    These marks can be used to track a branch's status.
523
    """
524
    takes_args = ['mark?', 'branch?']
525
    takes_options = [Option('delete', help='Delete this mark')]
526
    def run(self, mark=None, branch=None, delete=False):
527
        from branch_mark import branch_mark
528
        branch_mark(mark, branch, delete)
529
445 by Aaron Bentley
Remove shove, tweak imports, docs
530
377 by Aaron Bentley
Got import command working
531
class cmd_import(bzrlib.commands.Command):
490 by Aaron Bentley
Improve bzr import docs
532
    """Import sources from a directory, tarball or zip file
380 by Aaron Bentley
Got import working decently
533
    
490 by Aaron Bentley
Improve bzr import docs
534
    This command will import a directory, tarball or zip file into a bzr
535
    tree, replacing any versioned files already present.  If a directory is
536
    specified, it is used as the target.  If the directory does not exist, or
537
    is not versioned, it is created.
380 by Aaron Bentley
Got import working decently
538
539
    Tarballs may be gzip or bzip2 compressed.  This is autodetected.
540
490 by Aaron Bentley
Improve bzr import docs
541
    If the tarball or zip has a single root directory, that directory is
542
    stripped when extracting the tarball.  This is not done for directories.
380 by Aaron Bentley
Got import working decently
543
    """
544
    
545
    takes_args = ['source', 'tree?']
546
    def run(self, source, tree=None):
377 by Aaron Bentley
Got import command working
547
        from upstream_import import do_import
380 by Aaron Bentley
Got import working decently
548
        do_import(source, tree)
377 by Aaron Bentley
Got import command working
549
392.1.1 by Aaron Bentley
Implement 'shove' for moving changes to other trees
550
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
551
class cmd_cdiff(bzrlib.commands.Command):
415 by Aaron Bentley
Remove <BZRTOOLS> tag from command descriptions
552
    """A color version of bzr's diff"""
410 by Aaron Bentley
Ensure the option settings come from the right 'diff' in colordiff
553
    takes_args = property(lambda x: get_cmd_object('diff').takes_args)
497 by Aaron Bentley
Add optional style checks to colordiff
554
555
    def _takes_options(self):
556
        options = list(get_cmd_object('diff').takes_options)
500 by Aaron Bentley
Add help
557
        options.append(Option('check-style',
558
            help='Warn if trailing whitespace or spurious changes have been'
559
                 ' added.'))
497 by Aaron Bentley
Add optional style checks to colordiff
560
        return options
561
562
    takes_options = property(_takes_options)
563
564
    def run(self, check_style=False, *args, **kwargs):
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
565
        from colordiff import colordiff
497 by Aaron Bentley
Add optional style checks to colordiff
566
        colordiff(check_style, *args, **kwargs)
360.1.3 by Aaron Bentley
Add experimental branch-mark command
567
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
568
569
class cmd_baz_import(bzrlib.commands.Command):
570
    """Import an Arch or Baz archive into a bzr repository.
571
572
    This command should be used on local archives (or mirrors) only.  It is
573
    quite slow on remote archives.
574
    
575
    reuse_history allows you to specify any previous imports you 
576
    have done of different archives, which this archive has branches
577
    tagged from. This will dramatically reduce the time to convert 
578
    the archive as it will not have to convert the history already
579
    converted in that other branch.
580
581
    If you specify prefixes, only branches whose names start with that prefix
582
    will be imported.  Skipped branches will be listed, so you can import any
583
    branches you missed by accident.  Here's an example of doing a partial
584
    import from thelove@canonical.com:
585
    bzr baz-import thelove thelove@canonical.com --prefixes dists:talloc-except
463 by Aaron Bentley
Get encoding flag under test
586
587
    WARNING: Encoding should not be specified unless necessary, because if you
588
    specify an encoding, your converted branch will not interoperate with
589
    independently-converted branches, unless the other branches were converted
590
    with exactly the same encoding.  Any encoding recognized by Python may
591
    be specified.  Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
592
    are incompatible.
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
593
    """
594
    takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
595
    takes_options = ['verbose', Option('prefixes', type=str,
463 by Aaron Bentley
Get encoding flag under test
596
                     help="Prefixes of branches to import, colon-separated"),
597
                     Option('encoding', type=str, 
598
                     help='Force encoding to specified value.  See WARNING.')]
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
599
460 by Aaron Bentley
Add encoding parameter everywhere
600
    def run(self, to_root_dir, from_archive, encoding=None, verbose=False,
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
601
            reuse_history_list=[], prefixes=None):
602
        from errors import NoPyBaz
603
        try:
604
            import baz_import
460 by Aaron Bentley
Add encoding parameter everywhere
605
            baz_import.baz_import(to_root_dir, from_archive, encoding,
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
606
                                  verbose, reuse_history_list, prefixes)
607
        except NoPyBaz:
608
            print "This command is disabled.  Please install PyBaz."
609
610
611
class cmd_baz_import_branch(bzrlib.commands.Command):
463 by Aaron Bentley
Get encoding flag under test
612
    """Import an Arch or Baz branch into a bzr branch.
613
614
    WARNING: Encoding should not be specified unless necessary, because if you
615
    specify an encoding, your converted branch will not interoperate with
616
    independently-converted branches, unless the other branches were converted
617
    with exactly the same encoding.  Any encoding recognized by Python may
618
    be specified.  Aliases are not detected, so 'utf_8', 'U8', 'UTF' and 'utf8'
619
    are incompatible.
620
    """
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
621
    takes_args = ['to_location', 'from_branch?', 'reuse_history*']
463 by Aaron Bentley
Get encoding flag under test
622
    takes_options = ['verbose', Option('max-count', type=int),
623
                     Option('encoding', type=str, 
624
                     help='Force encoding to specified value.  See WARNING.')]
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
625
626
    def run(self, to_location, from_branch=None, fast=False, max_count=None,
460 by Aaron Bentley
Add encoding parameter everywhere
627
            encoding=None, verbose=False, dry_run=False,
628
            reuse_history_list=[]):
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
629
        from errors import NoPyBaz
630
        try:
631
            import baz_import
632
            baz_import.baz_import_branch(to_location, from_branch, fast, 
460 by Aaron Bentley
Add encoding parameter everywhere
633
                                         max_count, verbose, encoding, dry_run,
430 by Aaron Bentley
Avoid loading PyBaz unless running baz-import
634
                                         reuse_history_list)
635
        except NoPyBaz:
636
            print "This command is disabled.  Please install PyBaz."
637
638
460 by Aaron Bentley
Add encoding parameter everywhere
639
class cmd_rspush(bzrlib.commands.Command):
640
    """Upload this branch to another location using rsync.
641
642
    If no location is specified, the last-used location will be used.  To 
643
    prevent dirty trees from being uploaded, rspush will error out if there are 
644
    unknown files or local changes.  It will also error out if the upstream 
645
    directory is non-empty and not an earlier version of the branch. 
646
    """
647
    takes_args = ['location?']
648
    takes_options = [Option('overwrite', help='Ignore differences between'
649
                            ' branches and overwrite unconditionally'),
650
                     Option('no-tree', help='Do not push the working tree,'
651
                            ' just the .bzr.')]
652
653
    def run(self, location=None, overwrite=False, no_tree=False):
654
        from bzrlib import workingtree
655
        import bzrtools
656
        cur_branch = workingtree.WorkingTree.open_containing(".")[0]
657
        bzrtools.rspush(cur_branch, location, overwrite=overwrite, 
658
                      working_tree=not no_tree)
659
660
661
class cmd_switch(bzrlib.commands.Command):
662
    """Set the branch of a lightweight checkout and update."""
663
664
    takes_args = ['to_location']
665
666
    def run(self, to_location):
667
        from switch import cmd_switch
668
        cmd_switch().run(to_location)
669
670
445 by Aaron Bentley
Remove shove, tweak imports, docs
671
commands = [
672
            cmd_baz_import,
673
            cmd_baz_import_branch,
674
            cmd_branches,
675
            cmd_branch_history,
676
            cmd_branch_mark,
677
            cmd_cbranch,  
678
            cmd_cdiff,
679
            cmd_clean_tree,
680
            cmd_fetch_ghosts,
681
            cmd_graph_ancestry,
682
            cmd_import,
683
            cmd_multi_pull,
684
            cmd_patch,
460 by Aaron Bentley
Add encoding parameter everywhere
685
            cmd_rspush,
445 by Aaron Bentley
Remove shove, tweak imports, docs
686
            cmd_shelf, 
687
            cmd_shell,
688
            cmd_shelve, 
689
            cmd_switch,
690
            cmd_unshelve, 
691
            cmd_zap,            
692
            ]
399 by Aaron Bentley
Implement cdiff (based on old Fai code)
693
246 by Aaron Bentley
Merged shelf_v2
694
695
if hasattr(bzrlib.commands, 'register_command'):
696
    for command in commands:
697
        bzrlib.commands.register_command(command)
271 by Aaron Bentley
Cherry-picked Robert's diff and push fixes
698
0.1.73 by Michael Ellerman
Merge most of the standalone shelf branch. This brings in a few changes which
699
700
def test_suite():
701
    from bzrlib.tests.TestUtil import TestLoader
147.1.41 by Aaron Bentley
Merge from mainline
702
    import tests
321.1.3 by Aaron Bentley
Fixed up Robert's test changes
703
    from doctest import DocTestSuite, ELLIPSIS
325.1.2 by Aaron Bentley
Merge shelf v2
704
    from unittest import TestSuite
460 by Aaron Bentley
Add encoding parameter everywhere
705
    import bzrtools
391 by Aaron Bentley
Updates from the bzr clean-tree branch
706
    import tests.clean_tree
477 by Aaron Bentley
split out upstream_import test cases
707
    import tests.upstream_import
345 by Aaron Bentley
Added zap command
708
    import zap
339 by Aaron Bentley
Moved tests into a subdir
709
    import tests.blackbox
710
    import tests.shelf_tests
246 by Aaron Bentley
Merged shelf_v2
711
    result = TestSuite()
321.1.3 by Aaron Bentley
Fixed up Robert's test changes
712
    result.addTest(DocTestSuite(bzrtools, optionflags=ELLIPSIS))
391 by Aaron Bentley
Updates from the bzr clean-tree branch
713
    result.addTest(tests.clean_tree.test_suite())
387 by Aaron Bentley
Got test suite running with PyBaz unavailable
714
    try:
715
        import baz_import
716
        result.addTest(DocTestSuite(baz_import))
717
    except NoPyBaz:
718
        pass
147.1.41 by Aaron Bentley
Merge from mainline
719
    result.addTest(tests.test_suite())
339 by Aaron Bentley
Moved tests into a subdir
720
    result.addTest(TestLoader().loadTestsFromModule(tests.shelf_tests))
721
    result.addTest(tests.blackbox.test_suite())
477 by Aaron Bentley
split out upstream_import test cases
722
    result.addTest(tests.upstream_import.test_suite())
345 by Aaron Bentley
Added zap command
723
    result.addTest(zap.test_suite())
246 by Aaron Bentley
Merged shelf_v2
724
    return result