~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

[patch] define cli options as objects, not strings
  patch from Magnus Thering

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
41
42
 
42
43
plugin_cmds = {}
43
44
 
67
68
    return cmd[4:].replace('_','-')
68
69
 
69
70
 
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 specifier supplied.
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
 
    >>> _parse_revision_str('branch:../branch2')
117
 
    [<RevisionSpec_branch branch:../branch2>]
118
 
    """
119
 
    import re
120
 
    old_format_re = re.compile('\d*:\d*')
121
 
    m = old_format_re.match(revstr)
122
 
    revs = []
123
 
    if m:
124
 
        warning('Colon separator for revision numbers is deprecated.'
125
 
                ' Use .. instead')
126
 
        for rev in revstr.split(':'):
127
 
            if rev:
128
 
                revs.append(RevisionSpec(int(rev)))
129
 
            else:
130
 
                revs.append(RevisionSpec(None))
131
 
    else:
132
 
        next_prefix = None
133
 
        for x in revstr.split('..'):
134
 
            if not x:
135
 
                revs.append(RevisionSpec(None))
136
 
            elif x[-1] == ':':
137
 
                # looks like a namespace:.. has happened
138
 
                next_prefix = x + '..'
139
 
            else:
140
 
                if next_prefix is not None:
141
 
                    x = next_prefix + x
142
 
                revs.append(RevisionSpec(x))
143
 
                next_prefix = None
144
 
        if next_prefix is not None:
145
 
            revs.append(RevisionSpec(next_prefix))
146
 
    return revs
147
 
 
148
 
 
149
71
def _builtin_commands():
150
72
    import bzrlib.builtins
151
73
    r = {}
337
259
        parsed = [spec, None]
338
260
    return parsed
339
261
 
340
 
 
341
 
# list of all available options; the rhs can be either None for an
342
 
# option that takes no argument, or a constructor function that checks
343
 
# the type.
344
 
OPTIONS = {
345
 
    'all':                    None,
346
 
    'basis':                  str,
347
 
    'diff-options':           str,
348
 
    'help':                   None,
349
 
    'file':                   unicode,
350
 
    'force':                  None,
351
 
    'format':                 unicode,
352
 
    'forward':                None,
353
 
    'quiet':                  None,
354
 
    'message':                unicode,
355
 
    'no-recurse':             None,
356
 
    'profile':                None,
357
 
    'revision':               _parse_revision_str,
358
 
    'short':                  None,
359
 
    'show-ids':               None,
360
 
    'timezone':               str,
361
 
    'verbose':                None,
362
 
    'version':                None,
363
 
    'email':                  None,
364
 
    'unchanged':              None,
365
 
    'update':                 None,
366
 
    'long':                   None,
367
 
    'root':                   str,
368
 
    'no-backup':              None,
369
 
    'pattern':                str,
370
 
    'remember':               None,
371
 
    }
372
 
 
373
 
SHORT_OPTIONS = {
374
 
    'F':                      'file', 
375
 
    'h':                      'help',
376
 
    'm':                      'message',
377
 
    'r':                      'revision',
378
 
    'v':                      'verbose',
379
 
    'l':                      'long',
380
 
    'q':                      'quiet',
381
 
}
382
 
 
383
 
 
384
262
def parse_args(argv):
385
263
    """Parse command line.
386
264
    
428
306
                    optname, optarg = a[2:].split('=', 1)
429
307
                else:
430
308
                    optname = a[2:]
431
 
                if optname not in OPTIONS:
 
309
                if optname not in Option.OPTIONS:
432
310
                    raise BzrError('unknown long option %r' % a)
433
311
            else:
434
312
                shortopt = a[1:]
435
 
                if shortopt in SHORT_OPTIONS:
 
313
                if shortopt in Option.SHORT_OPTIONS:
436
314
                    # Multi-character options must have a space to delimit
437
315
                    # their value
438
 
                    optname = SHORT_OPTIONS[shortopt]
 
316
                    optname = Option.SHORT_OPTIONS[shortopt].name
439
317
                else:
440
318
                    # Single character short options, can be chained,
441
319
                    # and have their value appended to their name
442
320
                    shortopt = a[1:2]
443
 
                    if shortopt not in SHORT_OPTIONS:
 
321
                    if shortopt not in Option.SHORT_OPTIONS:
444
322
                        # We didn't find the multi-character name, and we
445
323
                        # didn't find the single char name
446
324
                        raise BzrError('unknown short option %r' % a)
447
 
                    optname = SHORT_OPTIONS[shortopt]
 
325
                    optname = Option.SHORT_OPTIONS[shortopt].name
448
326
 
449
327
                    if a[2:]:
450
328
                        # There are extra things on this option
451
329
                        # see if it is the value, or if it is another
452
330
                        # short option
453
 
                        optargfn = OPTIONS[optname]
 
331
                        optargfn = Option.OPTIONS[optname].type
454
332
                        if optargfn is None:
455
333
                            # This option does not take an argument, so the
456
334
                            # next entry is another short option, pack it back
465
343
                # XXX: Do we ever want to support this, e.g. for -r?
466
344
                raise BzrError('repeated option %r' % a)
467
345
                
468
 
            optargfn = OPTIONS[optname]
 
346
            optargfn = Option.OPTIONS[optname].type
469
347
            if optargfn:
470
348
                if optarg == None:
471
349
                    if not argv: