~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Robert Collins
  • Date: 2006-03-28 14:29:13 UTC
  • mto: (1626.2.1 integration)
  • mto: This revision was merged to the branch mainline in revision 1628.
  • Revision ID: robertc@robertcollins.net-20060328142913-ac5afb37075719c6
Convert log to use the new tsort.merge_sort routine.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
import os
33
33
from warnings import warn
34
34
import errno
35
 
import codecs
36
35
 
37
36
import bzrlib
38
 
import bzrlib.errors as errors
39
 
from bzrlib.errors import (BzrError,
 
37
from bzrlib.errors import (BzrError, 
 
38
                           BzrCheckError,
40
39
                           BzrCommandError,
41
 
                           BzrCheckError,
 
40
                           BzrOptionError,
42
41
                           NotBranchError)
43
42
from bzrlib.option import Option
44
 
import bzrlib.osutils
45
43
from bzrlib.revisionspec import RevisionSpec
46
 
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
47
 
from bzrlib import trace
 
44
from bzrlib.symbol_versioning import *
 
45
import bzrlib.trace
48
46
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
49
47
 
50
48
plugin_cmds = {}
147
145
    if cmd_obj:
148
146
        return cmd_obj
149
147
 
150
 
    raise BzrCommandError('unknown command "%s"' % cmd_name)
 
148
    raise BzrCommandError("unknown command %r" % cmd_name)
151
149
 
152
150
 
153
151
class Command(object):
191
189
    hidden
192
190
        If true, this command isn't advertised.  This is typically
193
191
        for commands intended for expert users.
194
 
 
195
 
    encoding_type
196
 
        Command objects will get a 'outf' attribute, which has been
197
 
        setup to properly handle encoding of unicode strings.
198
 
        encoding_type determines what will happen when characters cannot
199
 
        be encoded
200
 
            strict - abort if we cannot decode
201
 
            replace - put in a bogus character (typically '?')
202
 
            exact - do not encode sys.stdout
203
 
 
204
192
    """
205
193
    aliases = []
206
194
    takes_args = []
207
195
    takes_options = []
208
 
    encoding_type = 'strict'
209
196
 
210
197
    hidden = False
211
198
    
226
213
            r[o.name] = o
227
214
        return r
228
215
 
229
 
    def _setup_outf(self):
230
 
        """Return a file linked to stdout, which has proper encoding."""
231
 
        assert self.encoding_type in ['strict', 'exact', 'replace']
232
 
 
233
 
        # Originally I was using self.stdout, but that looks
234
 
        # *way* too much like sys.stdout
235
 
        if self.encoding_type == 'exact':
236
 
            self.outf = sys.stdout
237
 
            return
238
 
 
239
 
        output_encoding = bzrlib.osutils.get_terminal_encoding()
240
 
 
241
 
        # use 'replace' so that we don't abort if trying to write out
242
 
        # in e.g. the default C locale.
243
 
        self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
244
 
        # For whatever reason codecs.getwriter() does not advertise its encoding
245
 
        # it just returns the encoding of the wrapped file, which is completely
246
 
        # bogus. So set the attribute, so we can find the correct encoding later.
247
 
        self.outf.encoding = output_encoding
248
 
 
249
216
    @deprecated_method(zero_eight)
250
217
    def run_argv(self, argv):
251
218
        """Parse command line and run.
265
232
        allowed_names = self.options().keys()
266
233
        for oname in opts:
267
234
            if oname not in allowed_names:
268
 
                raise BzrOptionError("option '--%s' is not allowed for"
269
 
                                " command %r" % (oname, self.name()))
 
235
                raise BzrCommandError("option '--%s' is not allowed for"
 
236
                                      " command %r" % (oname, self.name()))
270
237
        # mix arguments and options into one dictionary
271
238
        cmdargs = _match_argform(self.name(), self.takes_args, args)
272
239
        cmdopts = {}
276
243
        all_cmd_args = cmdargs.copy()
277
244
        all_cmd_args.update(cmdopts)
278
245
 
279
 
        self._setup_outf()
280
 
 
281
246
        return self.run(**all_cmd_args)
282
247
    
283
248
    def run(self):
303
268
    def name(self):
304
269
        return _unsquish_command_name(self.__class__.__name__)
305
270
 
306
 
    def plugin_name(self):
307
 
        """Get the name of the plugin that provides this command.
308
 
 
309
 
        :return: The name of the plugin or None if the command is builtin.
310
 
        """
311
 
        mod_parts = self.__module__.split('.')
312
 
        if len(mod_parts) >= 3 and mod_parts[1] == 'plugins':
313
 
            return mod_parts[2]
314
 
        else:
315
 
            return None
316
 
 
317
271
 
318
272
def parse_spec(spec):
319
273
    """
368
322
            if argsover:
369
323
                args.append(a)
370
324
                continue
371
 
            elif a == '-':
372
 
                args.append(a)
373
 
                continue
374
325
            elif a == '--':
375
326
                # We've received a standalone -- No more flags
376
327
                argsover = True
386
337
                    else:
387
338
                        optname = a[2:]
388
339
                    if optname not in cmd_options:
389
 
                        raise BzrCommandError('unknown option "%s"' % a)
 
340
                        raise BzrOptionError('unknown long option %r for'
 
341
                                             ' command %s' % 
 
342
                                             (a, command.name()))
390
343
                else:
391
344
                    shortopt = a[1:]
392
345
                    if shortopt in Option.SHORT_OPTIONS:
401
354
                        if shortopt not in Option.SHORT_OPTIONS:
402
355
                            # We didn't find the multi-character name, and we
403
356
                            # didn't find the single char name
404
 
                            raise BzrCommandError('unknown option "%s"' % a)
 
357
                            raise BzrError('unknown short option %r' % a)
405
358
                        optname = Option.SHORT_OPTIONS[shortopt].name
406
359
 
407
360
                        if a[2:]:
418
371
                                # This option takes an argument, so pack it
419
372
                                # into the array
420
373
                                optarg = a[2:]
 
374
                
421
375
                    if optname not in cmd_options:
422
 
                        raise BzrCommandError('unknown option "%s"' % shortopt)
 
376
                        raise BzrOptionError('unknown short option %r for'
 
377
                                             ' command %s' % 
 
378
                                             (shortopt, command.name()))
423
379
                if optname in opts:
424
380
                    # XXX: Do we ever want to support this, e.g. for -r?
425
381
                    if proc_aliasarg:
426
 
                        raise BzrCommandError('repeated option %r' % a)
 
382
                        raise BzrError('repeated option %r' % a)
427
383
                    elif optname in alias_opts:
428
384
                        # Replace what's in the alias with what's in the real
429
385
                        # argument
432
388
                        proc_argv.insert(0, a)
433
389
                        continue
434
390
                    else:
435
 
                        raise BzrCommandError('repeated option %r' % a)
 
391
                        raise BzrError('repeated option %r' % a)
436
392
                    
437
393
                option_obj = cmd_options[optname]
438
394
                optargfn = option_obj.type
439
395
                if optargfn:
440
396
                    if optarg == None:
441
397
                        if not proc_argv:
442
 
                            raise BzrCommandError('option %r needs an argument' % a)
 
398
                            raise BzrError('option %r needs an argument' % a)
443
399
                        else:
444
400
                            optarg = proc_argv.pop(0)
445
401
                    opts[optname] = optargfn(optarg)
447
403
                        alias_opts[optname] = optargfn(optarg)
448
404
                else:
449
405
                    if optarg != None:
450
 
                        raise BzrCommandError('option %r takes no argument' % optname)
 
406
                        raise BzrError('option %r takes no argument' % optname)
451
407
                    opts[optname] = True
452
408
                    if proc_aliasarg:
453
409
                        alias_opts[optname] = True
484
440
                raise BzrCommandError("command %r needs one or more %s"
485
441
                        % (cmd, argname.upper()))
486
442
            argdict[argname + '_list'] = args[:-1]
487
 
            args[:-1] = []
 
443
            args[:-1] = []                
488
444
        else:
489
445
            # just a plain arg
490
446
            argname = ap
556
512
    
557
513
    argv
558
514
       The command-line arguments, without the program name from argv[0]
559
 
       These should already be decoded. All library/test code calling
560
 
       run_bzr should be passing valid strings (don't need decoding).
561
515
    
562
516
    Returns a command status or raises an exception.
563
517
 
580
534
    --lsprof
581
535
        Run under the Python lsprof profiler.
582
536
    """
583
 
    argv = list(argv)
 
537
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
584
538
 
585
539
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin =  \
586
540
                opt_no_aliases = False
599
553
        elif a == '--lsprof':
600
554
            opt_lsprof = True
601
555
        elif a == '--lsprof-file':
602
 
            opt_lsprof = True
603
556
            opt_lsprof_file = argv[i + 1]
604
557
            i += 1
605
558
        elif a == '--no-plugins':
615
568
        i += 1
616
569
 
617
570
    argv = argv_copy
618
 
    if (not argv):
619
 
        from bzrlib.builtins import cmd_help
620
 
        cmd_help().run_argv_aliases([])
 
571
    if (not argv) or (argv[0] == '--help'):
 
572
        from bzrlib.help import help
 
573
        if len(argv) > 1:
 
574
            help(argv[1])
 
575
        else:
 
576
            help()
621
577
        return 0
622
578
 
623
579
    if argv[0] == '--version':
673
629
            if not hasattr(e, 'errno'):
674
630
                raise
675
631
            if e.errno != errno.EPIPE:
676
 
                # Win32 raises IOError with errno=0 on a broken pipe
677
 
                if sys.platform != 'win32' or e.errno != 0:
678
 
                    raise
 
632
                raise
679
633
            pass
680
634
        except KeyboardInterrupt:
681
635
            pass
685
639
def main(argv):
686
640
    import bzrlib.ui
687
641
    from bzrlib.ui.text import TextUIFactory
 
642
    ## bzrlib.trace.enable_default_logging()
 
643
    bzrlib.trace.log_startup(argv)
688
644
    bzrlib.ui.ui_factory = TextUIFactory()
689
 
    argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
690
 
    ret = run_bzr_catch_errors(argv)
 
645
    ret = run_bzr_catch_errors(argv[1:])
691
646
    mutter("return code %d", ret)
692
647
    return ret
693
648
 
694
649
 
695
650
def run_bzr_catch_errors(argv):
696
651
    try:
697
 
        return run_bzr(argv)
698
 
        # do this here inside the exception wrappers to catch EPIPE
699
 
        sys.stdout.flush()
 
652
        try:
 
653
            return run_bzr(argv)
 
654
        finally:
 
655
            # do this here inside the exception wrappers to catch EPIPE
 
656
            sys.stdout.flush()
700
657
    except Exception, e:
701
658
        # used to handle AssertionError and KeyboardInterrupt
702
659
        # specially here, but hopefully they're handled ok by the logger now
703
 
        bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
704
 
        if os.environ.get('BZR_PDB'):
705
 
            print '**** entering debugger'
706
 
            import pdb
707
 
            pdb.post_mortem(sys.exc_traceback)
708
 
        return 3
 
660
        import errno
 
661
        if (isinstance(e, IOError) 
 
662
            and hasattr(e, 'errno')
 
663
            and e.errno == errno.EPIPE):
 
664
            bzrlib.trace.note('broken pipe')
 
665
            return 3
 
666
        else:
 
667
            bzrlib.trace.log_exception()
 
668
            if os.environ.get('BZR_PDB'):
 
669
                print '**** entering debugger'
 
670
                import pdb
 
671
                pdb.post_mortem(sys.exc_traceback)
 
672
            return 3
709
673
 
710
674
if __name__ == '__main__':
711
675
    sys.exit(main(sys.argv))