~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Robert Collins
  • Date: 2006-02-28 04:52:34 UTC
  • mfrom: (1583 +trunk)
  • mto: (1594.2.4 integration)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: robertc@robertcollins.net-20060228045234-d1856c4499648fb7
merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
import errno
35
35
 
36
36
import bzrlib
37
 
import bzrlib.trace
38
 
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
39
37
from bzrlib.errors import (BzrError, 
40
38
                           BzrCheckError,
41
39
                           BzrCommandError,
42
40
                           BzrOptionError,
43
41
                           NotBranchError)
 
42
from bzrlib.option import Option
44
43
from bzrlib.revisionspec import RevisionSpec
45
 
from bzrlib.option import Option
 
44
from bzrlib.symbol_versioning import *
 
45
import bzrlib.trace
 
46
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
46
47
 
47
48
plugin_cmds = {}
48
49
 
207
208
            r[o.name] = o
208
209
        return r
209
210
 
 
211
    @deprecated_method(zero_eight)
210
212
    def run_argv(self, argv):
211
 
        """Parse command line and run."""
212
 
        args, opts = parse_args(self, argv)
 
213
        """Parse command line and run.
 
214
        
 
215
        See run_argv_aliases for the 0.8 and beyond api.
 
216
        """
 
217
        return self.run_argv_aliases(argv)
 
218
 
 
219
    def run_argv_aliases(self, argv, alias_argv=None):
 
220
        """Parse the command line and run with extra aliases in alias_argv."""
 
221
        args, opts = parse_args(self, argv, alias_argv)
213
222
        if 'help' in opts:  # e.g. bzr add --help
214
223
            from bzrlib.help import help_on_command
215
224
            help_on_command(self.name())
218
227
        allowed_names = self.options().keys()
219
228
        for oname in opts:
220
229
            if oname not in allowed_names:
221
 
                raise BzrCommandError("option '--%s' is not allowed for command %r"
222
 
                                      % (oname, self.name()))
 
230
                raise BzrCommandError("option '--%s' is not allowed for"
 
231
                                      " command %r" % (oname, self.name()))
223
232
        # mix arguments and options into one dictionary
224
233
        cmdargs = _match_argform(self.name(), self.takes_args, args)
225
234
        cmdopts = {}
285
294
        parsed = [spec, None]
286
295
    return parsed
287
296
 
288
 
def parse_args(command, argv):
 
297
def parse_args(command, argv, alias_argv=None):
289
298
    """Parse command line.
290
299
    
291
300
    Arguments and options are parsed at this level before being passed
296
305
    # TODO: chop up this beast; make it a method of the Command
297
306
    args = []
298
307
    opts = {}
 
308
    alias_opts = {}
299
309
 
300
310
    cmd_options = command.options()
301
311
    argsover = False
302
 
    while argv:
303
 
        a = argv.pop(0)
304
 
        if argsover:
305
 
            args.append(a)
306
 
            continue
307
 
        elif a == '--':
308
 
            # We've received a standalone -- No more flags
309
 
            argsover = True
310
 
            continue
311
 
        if a[0] == '-':
312
 
            # option names must not be unicode
313
 
            a = str(a)
314
 
            optarg = None
315
 
            if a[1] == '-':
316
 
                mutter("  got option %r", a)
317
 
                if '=' in a:
318
 
                    optname, optarg = a[2:].split('=', 1)
319
 
                else:
320
 
                    optname = a[2:]
321
 
                if optname not in cmd_options:
322
 
                    raise BzrOptionError('unknown long option %r for command %s'
323
 
                        % (a, command.name()))
324
 
            else:
325
 
                shortopt = a[1:]
326
 
                if shortopt in Option.SHORT_OPTIONS:
327
 
                    # Multi-character options must have a space to delimit
328
 
                    # their value
329
 
                    # ^^^ what does this mean? mbp 20051014
330
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
331
 
                else:
332
 
                    # Single character short options, can be chained,
333
 
                    # and have their value appended to their name
334
 
                    shortopt = a[1:2]
335
 
                    if shortopt not in Option.SHORT_OPTIONS:
336
 
                        # We didn't find the multi-character name, and we
337
 
                        # didn't find the single char name
338
 
                        raise BzrError('unknown short option %r' % a)
339
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
 
312
    proc_aliasarg = True # Are we processing alias_argv now?
 
313
    for proc_argv in alias_argv, argv:
 
314
        while proc_argv:
 
315
            a = proc_argv.pop(0)
 
316
            if argsover:
 
317
                args.append(a)
 
318
                continue
 
319
            elif a == '--':
 
320
                # We've received a standalone -- No more flags
 
321
                argsover = True
 
322
                continue
 
323
            if a[0] == '-':
 
324
                # option names must not be unicode
 
325
                a = str(a)
 
326
                optarg = None
 
327
                if a[1] == '-':
 
328
                    mutter("  got option %r", a)
 
329
                    if '=' in a:
 
330
                        optname, optarg = a[2:].split('=', 1)
 
331
                    else:
 
332
                        optname = a[2:]
 
333
                    if optname not in cmd_options:
 
334
                        raise BzrOptionError('unknown long option %r for'
 
335
                                             ' command %s' % 
 
336
                                             (a, command.name()))
 
337
                else:
 
338
                    shortopt = a[1:]
 
339
                    if shortopt in Option.SHORT_OPTIONS:
 
340
                        # Multi-character options must have a space to delimit
 
341
                        # their value
 
342
                        # ^^^ what does this mean? mbp 20051014
 
343
                        optname = Option.SHORT_OPTIONS[shortopt].name
 
344
                    else:
 
345
                        # Single character short options, can be chained,
 
346
                        # and have their value appended to their name
 
347
                        shortopt = a[1:2]
 
348
                        if shortopt not in Option.SHORT_OPTIONS:
 
349
                            # We didn't find the multi-character name, and we
 
350
                            # didn't find the single char name
 
351
                            raise BzrError('unknown short option %r' % a)
 
352
                        optname = Option.SHORT_OPTIONS[shortopt].name
340
353
 
341
 
                    if a[2:]:
342
 
                        # There are extra things on this option
343
 
                        # see if it is the value, or if it is another
344
 
                        # short option
345
 
                        optargfn = Option.OPTIONS[optname].type
346
 
                        if optargfn is None:
347
 
                            # This option does not take an argument, so the
348
 
                            # next entry is another short option, pack it back
349
 
                            # into the list
350
 
                            argv.insert(0, '-' + a[2:])
 
354
                        if a[2:]:
 
355
                            # There are extra things on this option
 
356
                            # see if it is the value, or if it is another
 
357
                            # short option
 
358
                            optargfn = Option.OPTIONS[optname].type
 
359
                            if optargfn is None:
 
360
                                # This option does not take an argument, so the
 
361
                                # next entry is another short option, pack it
 
362
                                # back into the list
 
363
                                proc_argv.insert(0, '-' + a[2:])
 
364
                            else:
 
365
                                # This option takes an argument, so pack it
 
366
                                # into the array
 
367
                                optarg = a[2:]
 
368
                
 
369
                    if optname not in cmd_options:
 
370
                        raise BzrOptionError('unknown short option %r for'
 
371
                                             ' command %s' % 
 
372
                                             (shortopt, command.name()))
 
373
                if optname in opts:
 
374
                    # XXX: Do we ever want to support this, e.g. for -r?
 
375
                    if proc_aliasarg:
 
376
                        raise BzrError('repeated option %r' % a)
 
377
                    elif optname in alias_opts:
 
378
                        # Replace what's in the alias with what's in the real
 
379
                        # argument
 
380
                        del alias_opts[optname]
 
381
                        del opts[optname]
 
382
                        proc_argv.insert(0, a)
 
383
                        continue
 
384
                    else:
 
385
                        raise BzrError('repeated option %r' % a)
 
386
                    
 
387
                option_obj = cmd_options[optname]
 
388
                optargfn = option_obj.type
 
389
                if optargfn:
 
390
                    if optarg == None:
 
391
                        if not proc_argv:
 
392
                            raise BzrError('option %r needs an argument' % a)
351
393
                        else:
352
 
                            # This option takes an argument, so pack it
353
 
                            # into the array
354
 
                            optarg = a[2:]
355
 
            
356
 
                if optname not in cmd_options:
357
 
                    raise BzrOptionError('unknown short option %r for command'
358
 
                        ' %s' % (shortopt, command.name()))
359
 
            if optname in opts:
360
 
                # XXX: Do we ever want to support this, e.g. for -r?
361
 
                raise BzrError('repeated option %r' % a)
362
 
                
363
 
            option_obj = cmd_options[optname]
364
 
            optargfn = option_obj.type
365
 
            if optargfn:
366
 
                if optarg == None:
367
 
                    if not argv:
368
 
                        raise BzrError('option %r needs an argument' % a)
369
 
                    else:
370
 
                        optarg = argv.pop(0)
371
 
                opts[optname] = optargfn(optarg)
 
394
                            optarg = proc_argv.pop(0)
 
395
                    opts[optname] = optargfn(optarg)
 
396
                    if proc_aliasarg:
 
397
                        alias_opts[optname] = optargfn(optarg)
 
398
                else:
 
399
                    if optarg != None:
 
400
                        raise BzrError('option %r takes no argument' % optname)
 
401
                    opts[optname] = True
 
402
                    if proc_aliasarg:
 
403
                        alias_opts[optname] = True
372
404
            else:
373
 
                if optarg != None:
374
 
                    raise BzrError('option %r takes no argument' % optname)
375
 
                opts[optname] = True
376
 
        else:
377
 
            args.append(a)
 
405
                args.append(a)
 
406
        proc_aliasarg = False # Done with alias argv
378
407
    return args, opts
379
408
 
380
409
 
459
488
        print 'Profile data written to %r.' % filename
460
489
    return ret
461
490
 
 
491
 
 
492
def get_alias(cmd):
 
493
    """Return an expanded alias, or None if no alias exists"""
 
494
    import bzrlib.config
 
495
    alias = bzrlib.config.GlobalConfig().get_alias(cmd)
 
496
    if (alias):
 
497
        return alias.split(' ')
 
498
    return None
 
499
 
 
500
 
462
501
def run_bzr(argv):
463
502
    """Execute a command.
464
503
 
476
515
    --no-plugins
477
516
        Do not load plugin modules at all
478
517
 
 
518
    --no-aliases
 
519
        Do not allow aliases
 
520
 
479
521
    --builtin
480
522
        Only use builtin commands.  (Plugins are still allowed to change
481
523
        other behaviour.)
488
530
    """
489
531
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
490
532
 
491
 
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = False
 
533
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin =  \
 
534
                opt_no_aliases = False
492
535
    opt_lsprof_file = None
493
536
 
494
537
    # --no-plugins is handled specially at a very early stage. We need
508
551
            i += 1
509
552
        elif a == '--no-plugins':
510
553
            opt_no_plugins = True
 
554
        elif a == '--no-aliases':
 
555
            opt_no_aliases = True
511
556
        elif a == '--builtin':
512
557
            opt_builtin = True
513
558
        elif a in ('--quiet', '-q'):
537
582
        from bzrlib.plugin import disable_plugins
538
583
        disable_plugins()
539
584
 
 
585
    alias_argv = None
 
586
 
 
587
    if not opt_no_aliases:
 
588
        alias_argv = get_alias(argv[0])
 
589
        if alias_argv:
 
590
            alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
 
591
            argv[0] = alias_argv.pop(0)
 
592
 
540
593
    cmd = str(argv.pop(0))
541
594
 
542
595
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
 
596
    if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
 
597
        run = cmd_obj.run_argv
 
598
        run_argv = [argv]
 
599
    else:
 
600
        run = cmd_obj.run_argv_aliases
 
601
        run_argv = [argv, alias_argv]
543
602
 
544
603
    try:
545
604
        if opt_lsprof:
546
 
            ret = apply_lsprofiled(opt_lsprof_file, cmd_obj.run_argv, argv)
 
605
            ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
547
606
        elif opt_profile:
548
 
            ret = apply_profiled(cmd_obj.run_argv, argv)
 
607
            ret = apply_profiled(run, *run_argv)
549
608
        else:
550
 
            ret = cmd_obj.run_argv(argv)
 
609
            ret = run(*run_argv)
551
610
        return ret or 0
552
611
    finally:
553
612
        # reset, in case we may do other commands later within the same process