~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Robert Collins
  • Date: 2005-10-08 00:39:04 UTC
  • mfrom: (1185.1.52)
  • Revision ID: robertc@robertcollins.net-20051008003904-aaffaea2778efe3e
merge in martins reweave, integrated to fetch, and a bugfix for commit and upgrade with executable files

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
39
39
from bzrlib.revisionspec import RevisionSpec
40
40
from bzrlib import BZRDIR
41
 
from bzrlib.option import Option
42
41
 
43
42
plugin_cmds = {}
44
43
 
68
67
    return cmd[4:].replace('_','-')
69
68
 
70
69
 
 
70
def _parse_revision_str(revstr):
 
71
    """This handles a revision string -> revno.
 
72
 
 
73
    This always returns a list.  The list will have one element for
 
74
    each revision.
 
75
 
 
76
    >>> _parse_revision_str('234')
 
77
    [<RevisionSpec_int 234>]
 
78
    >>> _parse_revision_str('234..567')
 
79
    [<RevisionSpec_int 234>, <RevisionSpec_int 567>]
 
80
    >>> _parse_revision_str('..')
 
81
    [<RevisionSpec None>, <RevisionSpec None>]
 
82
    >>> _parse_revision_str('..234')
 
83
    [<RevisionSpec None>, <RevisionSpec_int 234>]
 
84
    >>> _parse_revision_str('234..')
 
85
    [<RevisionSpec_int 234>, <RevisionSpec None>]
 
86
    >>> _parse_revision_str('234..456..789') # Maybe this should be an error
 
87
    [<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
 
88
    >>> _parse_revision_str('234....789') # Error?
 
89
    [<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
 
90
    >>> _parse_revision_str('revid:test@other.com-234234')
 
91
    [<RevisionSpec_revid revid:test@other.com-234234>]
 
92
    >>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
 
93
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
 
94
    >>> _parse_revision_str('revid:test@other.com-234234..23')
 
95
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
 
96
    >>> _parse_revision_str('date:2005-04-12')
 
97
    [<RevisionSpec_date date:2005-04-12>]
 
98
    >>> _parse_revision_str('date:2005-04-12 12:24:33')
 
99
    [<RevisionSpec_date date:2005-04-12 12:24:33>]
 
100
    >>> _parse_revision_str('date:2005-04-12T12:24:33')
 
101
    [<RevisionSpec_date date:2005-04-12T12:24:33>]
 
102
    >>> _parse_revision_str('date:2005-04-12,12:24:33')
 
103
    [<RevisionSpec_date date:2005-04-12,12:24:33>]
 
104
    >>> _parse_revision_str('-5..23')
 
105
    [<RevisionSpec_int -5>, <RevisionSpec_int 23>]
 
106
    >>> _parse_revision_str('-5')
 
107
    [<RevisionSpec_int -5>]
 
108
    >>> _parse_revision_str('123a')
 
109
    Traceback (most recent call last):
 
110
      ...
 
111
    BzrError: No namespace registered for string: '123a'
 
112
    >>> _parse_revision_str('abc')
 
113
    Traceback (most recent call last):
 
114
      ...
 
115
    BzrError: No namespace registered for string: 'abc'
 
116
    """
 
117
    import re
 
118
    old_format_re = re.compile('\d*:\d*')
 
119
    m = old_format_re.match(revstr)
 
120
    revs = []
 
121
    if m:
 
122
        warning('Colon separator for revision numbers is deprecated.'
 
123
                ' Use .. instead')
 
124
        for rev in revstr.split(':'):
 
125
            if rev:
 
126
                revs.append(RevisionSpec(int(rev)))
 
127
            else:
 
128
                revs.append(RevisionSpec(None))
 
129
    else:
 
130
        for x in revstr.split('..'):
 
131
            if not x:
 
132
                revs.append(RevisionSpec(None))
 
133
            else:
 
134
                revs.append(RevisionSpec(x))
 
135
    return revs
 
136
 
 
137
 
71
138
def _builtin_commands():
72
139
    import bzrlib.builtins
73
140
    r = {}
158
225
        repeated, etc.
159
226
 
160
227
    takes_options
161
 
        List of options that may be given for this command.  These can
162
 
        be either strings, referring to globally-defined options,
163
 
        or option objects.  Retrieve through options().
 
228
        List of options that may be given for this command.
164
229
 
165
230
    hidden
166
231
        If true, this command isn't advertised.  This is typically
167
232
        for commands intended for expert users.
168
233
    """
169
234
    aliases = []
 
235
    
170
236
    takes_args = []
171
237
    takes_options = []
172
238
 
177
243
        if self.__doc__ == Command.__doc__:
178
244
            warn("No help message set for %r" % self)
179
245
 
180
 
    def options(self):
181
 
        """Return dict of valid options for this command.
182
 
 
183
 
        Maps from long option name to option object."""
184
 
        r = dict()
185
 
        r['help'] = Option.OPTIONS['help']
186
 
        for o in self.takes_options:
187
 
            if not isinstance(o, Option):
188
 
                o = Option.OPTIONS[o]
189
 
            r[o.name] = o
190
 
        return r
191
246
 
192
247
    def run_argv(self, argv):
193
248
        """Parse command line and run."""
194
 
        args, opts = parse_args(self, argv)
 
249
        args, opts = parse_args(argv)
 
250
 
195
251
        if 'help' in opts:  # e.g. bzr add --help
196
252
            from bzrlib.help import help_on_command
197
253
            help_on_command(self.name())
198
254
            return 0
199
 
        # XXX: This should be handled by the parser
200
 
        allowed_names = self.options().keys()
 
255
 
 
256
        # check options are reasonable
 
257
        allowed = self.takes_options
201
258
        for oname in opts:
202
 
            if oname not in allowed_names:
 
259
            if oname not in allowed:
203
260
                raise BzrCommandError("option '--%s' is not allowed for command %r"
204
261
                                      % (oname, self.name()))
 
262
 
205
263
        # mix arguments and options into one dictionary
206
264
        cmdargs = _match_argform(self.name(), self.takes_args, args)
207
265
        cmdopts = {}
268
326
        parsed = [spec, None]
269
327
    return parsed
270
328
 
271
 
def parse_args(command, argv):
 
329
 
 
330
# list of all available options; the rhs can be either None for an
 
331
# option that takes no argument, or a constructor function that checks
 
332
# the type.
 
333
OPTIONS = {
 
334
    'all':                    None,
 
335
    'basis':                  str,
 
336
    'diff-options':           str,
 
337
    'help':                   None,
 
338
    'file':                   unicode,
 
339
    'force':                  None,
 
340
    'format':                 unicode,
 
341
    'forward':                None,
 
342
    'message':                unicode,
 
343
    'no-recurse':             None,
 
344
    'profile':                None,
 
345
    'revision':               _parse_revision_str,
 
346
    'short':                  None,
 
347
    'show-ids':               None,
 
348
    'timezone':               str,
 
349
    'verbose':                None,
 
350
    'version':                None,
 
351
    'email':                  None,
 
352
    'unchanged':              None,
 
353
    'update':                 None,
 
354
    'long':                   None,
 
355
    'root':                   str,
 
356
    'no-backup':              None,
 
357
    'pattern':                str,
 
358
    'remember':               None,
 
359
    }
 
360
 
 
361
SHORT_OPTIONS = {
 
362
    'F':                      'file', 
 
363
    'h':                      'help',
 
364
    'm':                      'message',
 
365
    'r':                      'revision',
 
366
    'v':                      'verbose',
 
367
    'l':                      'long',
 
368
}
 
369
 
 
370
 
 
371
def parse_args(argv):
272
372
    """Parse command line.
273
373
    
274
374
    Arguments and options are parsed at this level before being passed
275
375
    down to specific command handlers.  This routine knows, from a
276
376
    lookup table, something about the available options, what optargs
277
377
    they take, and which commands will accept them.
 
378
 
 
379
    >>> parse_args('--help'.split())
 
380
    ([], {'help': True})
 
381
    >>> parse_args('help -- --invalidcmd'.split())
 
382
    (['help', '--invalidcmd'], {})
 
383
    >>> parse_args('--version'.split())
 
384
    ([], {'version': True})
 
385
    >>> parse_args('status --all'.split())
 
386
    (['status'], {'all': True})
 
387
    >>> parse_args('commit --message=biter'.split())
 
388
    (['commit'], {'message': u'biter'})
 
389
    >>> parse_args('log -r 500'.split())
 
390
    (['log'], {'revision': [<RevisionSpec_int 500>]})
 
391
    >>> parse_args('log -r500..600'.split())
 
392
    (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
 
393
    >>> parse_args('log -vr500..600'.split())
 
394
    (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
 
395
    >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
 
396
    (['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
278
397
    """
279
 
    # TODO: chop up this beast; make it a method of the Command
280
398
    args = []
281
399
    opts = {}
282
400
 
283
 
    cmd_options = command.options()
284
401
    argsover = False
285
402
    while argv:
286
403
        a = argv.pop(0)
287
 
        if argsover:
288
 
            args.append(a)
289
 
            continue
290
 
        elif a == '--':
291
 
            # We've received a standalone -- No more flags
292
 
            argsover = True
293
 
            continue
294
 
        if a[0] == '-':
 
404
        if not argsover and a[0] == '-':
295
405
            # option names must not be unicode
296
406
            a = str(a)
297
407
            optarg = None
298
408
            if a[1] == '-':
 
409
                if a == '--':
 
410
                    # We've received a standalone -- No more flags
 
411
                    argsover = True
 
412
                    continue
299
413
                mutter("  got option %r" % a)
300
414
                if '=' in a:
301
415
                    optname, optarg = a[2:].split('=', 1)
302
416
                else:
303
417
                    optname = a[2:]
304
 
                if optname not in cmd_options:
305
 
                    raise BzrCommandError('unknown long option %r for command %s' 
306
 
                            % (a, command.name))
 
418
                if optname not in OPTIONS:
 
419
                    raise BzrError('unknown long option %r' % a)
307
420
            else:
308
421
                shortopt = a[1:]
309
 
                if shortopt in Option.SHORT_OPTIONS:
 
422
                if shortopt in SHORT_OPTIONS:
310
423
                    # Multi-character options must have a space to delimit
311
424
                    # their value
312
 
                    # ^^^ what does this mean? mbp 20051014
313
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
 
425
                    optname = SHORT_OPTIONS[shortopt]
314
426
                else:
315
427
                    # Single character short options, can be chained,
316
428
                    # and have their value appended to their name
317
429
                    shortopt = a[1:2]
318
 
                    if shortopt not in Option.SHORT_OPTIONS:
 
430
                    if shortopt not in SHORT_OPTIONS:
319
431
                        # We didn't find the multi-character name, and we
320
432
                        # didn't find the single char name
321
433
                        raise BzrError('unknown short option %r' % a)
322
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
 
434
                    optname = SHORT_OPTIONS[shortopt]
323
435
 
324
436
                    if a[2:]:
325
437
                        # There are extra things on this option
326
438
                        # see if it is the value, or if it is another
327
439
                        # short option
328
 
                        optargfn = Option.OPTIONS[optname].type
 
440
                        optargfn = OPTIONS[optname]
329
441
                        if optargfn is None:
330
442
                            # This option does not take an argument, so the
331
443
                            # next entry is another short option, pack it back
340
452
                # XXX: Do we ever want to support this, e.g. for -r?
341
453
                raise BzrError('repeated option %r' % a)
342
454
                
343
 
            option_obj = cmd_options[optname]
344
 
            optargfn = option_obj.type
 
455
            optargfn = OPTIONS[optname]
345
456
            if optargfn:
346
457
                if optarg == None:
347
458
                    if not argv:
355
466
                opts[optname] = True
356
467
        else:
357
468
            args.append(a)
 
469
 
358
470
    return args, opts
359
471
 
360
472
 
 
473
 
 
474
 
361
475
def _match_argform(cmd, takes_args, args):
362
476
    argdict = {}
363
477
 
450
564
    --profile
451
565
        Run under the Python profiler.
452
566
    """
 
567
    # Load all of the transport methods
 
568
    import bzrlib.transport.local, bzrlib.transport.http
 
569
    
453
570
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
454
571
 
455
572
    opt_profile = opt_no_plugins = opt_builtin = False