~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
# TODO: probably should say which arguments are candidates for glob
50
50
 
51
51
from bzrlib import registry
52
52
# Compatibility
53
 
from bzrlib.hooks import Hooks
 
53
from bzrlib.hooks import HookPoint, Hooks
54
54
from bzrlib.option import Option
55
55
 
56
56
 
139
139
            real_name = _unsquish_command_name(name)
140
140
            r[real_name] = builtins[name]
141
141
    return r
142
 
            
 
142
 
143
143
 
144
144
def builtin_command_names():
145
145
    """Return list of builtin command names."""
146
146
    return _builtin_commands().keys()
147
 
    
 
147
 
148
148
 
149
149
def plugin_command_names():
150
150
    return plugin_cmds.keys()
157
157
        d.update(plugin_cmds.iteritems())
158
158
    return d
159
159
 
160
 
    
 
160
 
161
161
def get_all_cmds(plugins_override=True):
162
162
    """Return canonical name and class for all registered commands."""
163
163
    for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
291
291
    encoding_type = 'strict'
292
292
 
293
293
    hidden = False
294
 
    
 
294
 
295
295
    def __init__(self):
296
296
        """Construct an instance of this command."""
297
297
        if self.__doc__ == Command.__doc__:
301
301
 
302
302
    def _maybe_expand_globs(self, file_list):
303
303
        """Glob expand file_list if the platform does not do that itself.
304
 
        
 
304
 
305
305
        :return: A possibly empty list of unicode paths.
306
306
 
307
307
        Introduced in bzrlib 0.18.
331
331
        return s
332
332
 
333
333
    def get_help_text(self, additional_see_also=None, plain=True,
334
 
                      see_also_as_links=False):
 
334
                      see_also_as_links=False, verbose=True):
335
335
        """Return a text string with help for this command.
336
 
        
 
336
 
337
337
        :param additional_see_also: Additional help topics to be
338
338
            cross-referenced.
339
339
        :param plain: if False, raw help (reStructuredText) is
340
340
            returned instead of plain text.
341
341
        :param see_also_as_links: if True, convert items in 'See also'
342
342
            list to internal links (used by bzr_man rstx generator)
 
343
        :param verbose: if True, display the full help, otherwise
 
344
            leave out the descriptive sections and just display
 
345
            usage help (e.g. Purpose, Usage, Options) with a
 
346
            message explaining how to obtain full help.
343
347
        """
344
348
        doc = self.help()
345
349
        if doc is None:
374
378
            result += options
375
379
        result += '\n'
376
380
 
377
 
        # Add the description, indenting it 2 spaces
378
 
        # to match the indentation of the options
379
 
        if sections.has_key(None):
380
 
            text = sections.pop(None)
381
 
            text = '\n  '.join(text.splitlines())
382
 
            result += ':%s:\n  %s\n\n' % ('Description',text)
 
381
        if verbose:
 
382
            # Add the description, indenting it 2 spaces
 
383
            # to match the indentation of the options
 
384
            if sections.has_key(None):
 
385
                text = sections.pop(None)
 
386
                text = '\n  '.join(text.splitlines())
 
387
                result += ':%s:\n  %s\n\n' % ('Description',text)
383
388
 
384
 
        # Add the custom sections (e.g. Examples). Note that there's no need
385
 
        # to indent these as they must be indented already in the source.
386
 
        if sections:
387
 
            for label in order:
388
 
                if sections.has_key(label):
389
 
                    result += ':%s:\n%s\n\n' % (label,sections[label])
 
389
            # Add the custom sections (e.g. Examples). Note that there's no need
 
390
            # to indent these as they must be indented already in the source.
 
391
            if sections:
 
392
                for label in order:
 
393
                    if sections.has_key(label):
 
394
                        result += ':%s:\n%s\n' % (label,sections[label])
 
395
                result += '\n'
 
396
        else:
 
397
            result += ("See bzr help %s for more details and examples.\n\n"
 
398
                % self.name())
390
399
 
391
400
        # Add the aliases, source (plug-in) and see also links, if any
392
401
        if self.aliases:
463
472
 
464
473
    def get_see_also(self, additional_terms=None):
465
474
        """Return a list of help topics that are related to this command.
466
 
        
 
475
 
467
476
        The list is derived from the content of the _see_also attribute. Any
468
477
        duplicates are removed and the result is in lexical order.
469
478
        :param additional_terms: Additional help topics to cross-reference.
523
532
        if 'help' in opts:  # e.g. bzr add --help
524
533
            sys.stdout.write(self.get_help_text())
525
534
            return 0
 
535
        if 'usage' in opts:  # e.g. bzr add --usage
 
536
            sys.stdout.write(self.get_help_text(verbose=False))
 
537
            return 0
526
538
        trace.set_verbosity_level(option._verbosity_level)
527
539
        if 'verbose' in self.supported_std_options:
528
540
            opts['verbose'] = trace.is_verbose()
591
603
        notified.
592
604
        """
593
605
        Hooks.__init__(self)
594
 
        # Introduced in 1.13:
595
 
        # invoked after creating a command object to allow modifications such
596
 
        # as adding or removing options, docs etc. Invoked with the command
597
 
        # object.
598
 
        self['extend_command'] = []
 
606
        self.create_hook(HookPoint('extend_command',
 
607
            "Called after creating a command object to allow modifications "
 
608
            "such as adding or removing options, docs etc. Called with the "
 
609
            "new bzrlib.commands.Command object.", (1, 13), None))
599
610
 
600
611
Command.hooks = CommandHooks()
601
612
 
602
613
 
603
614
def parse_args(command, argv, alias_argv=None):
604
615
    """Parse command line.
605
 
    
 
616
 
606
617
    Arguments and options are parsed at this level before being passed
607
618
    down to specific command handlers.  This routine knows, from a
608
619
    lookup table, something about the available options, what optargs
657
668
                               % (cmd, argname.upper()))
658
669
            else:
659
670
                argdict[argname] = args.pop(0)
660
 
            
 
671
 
661
672
    if args:
662
673
        raise errors.BzrCommandError("extra argument to command %s: %s"
663
674
                                     % (cmd, args[0]))
672
683
    tracer = trace.Trace(count=1, trace=0)
673
684
    sys.settrace(tracer.globaltrace)
674
685
 
675
 
    ret = the_callable(*args, **kwargs)
676
 
 
677
 
    sys.settrace(None)
678
 
    results = tracer.results()
679
 
    results.write_results(show_missing=1, summary=False,
680
 
                          coverdir=dirname)
 
686
    try:
 
687
        return exception_to_return_code(the_callable, *args, **kwargs)
 
688
    finally:
 
689
        sys.settrace(None)
 
690
        results = tracer.results()
 
691
        results.write_results(show_missing=1, summary=False,
 
692
                              coverdir=dirname)
681
693
 
682
694
 
683
695
def apply_profiled(the_callable, *args, **kwargs):
688
700
    try:
689
701
        prof = hotshot.Profile(pfname)
690
702
        try:
691
 
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
 
703
            ret = prof.runcall(exception_to_return_code, the_callable, *args,
 
704
                **kwargs) or 0
692
705
        finally:
693
706
            prof.close()
694
707
        stats = hotshot.stats.load(pfname)
703
716
        os.remove(pfname)
704
717
 
705
718
 
 
719
def exception_to_return_code(the_callable, *args, **kwargs):
 
720
    """UI level helper for profiling and coverage.
 
721
 
 
722
    This transforms exceptions into a return value of 3. As such its only
 
723
    relevant to the UI layer, and should never be called where catching
 
724
    exceptions may be desirable.
 
725
    """
 
726
    try:
 
727
        return the_callable(*args, **kwargs)
 
728
    except (KeyboardInterrupt, Exception), e:
 
729
        # used to handle AssertionError and KeyboardInterrupt
 
730
        # specially here, but hopefully they're handled ok by the logger now
 
731
        exc_info = sys.exc_info()
 
732
        exitcode = trace.report_exception(exc_info, sys.stderr)
 
733
        if os.environ.get('BZR_PDB'):
 
734
            print '**** entering debugger'
 
735
            tb = exc_info[2]
 
736
            import pdb
 
737
            if sys.version_info[:2] < (2, 6):
 
738
                # XXX: we want to do
 
739
                #    pdb.post_mortem(tb)
 
740
                # but because pdb.post_mortem gives bad results for tracebacks
 
741
                # from inside generators, we do it manually.
 
742
                # (http://bugs.python.org/issue4150, fixed in Python 2.6)
 
743
 
 
744
                # Setup pdb on the traceback
 
745
                p = pdb.Pdb()
 
746
                p.reset()
 
747
                p.setup(tb.tb_frame, tb)
 
748
                # Point the debugger at the deepest frame of the stack
 
749
                p.curindex = len(p.stack) - 1
 
750
                p.curframe = p.stack[p.curindex][0]
 
751
                # Start the pdb prompt.
 
752
                p.print_stack_entry(p.stack[p.curindex])
 
753
                p.execRcLines()
 
754
                p.cmdloop()
 
755
            else:
 
756
                pdb.post_mortem(tb)
 
757
        return exitcode
 
758
 
 
759
 
706
760
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
707
761
    from bzrlib.lsprof import profile
708
 
    ret, stats = profile(the_callable, *args, **kwargs)
 
762
    ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
709
763
    stats.sort()
710
764
    if filename is None:
711
765
        stats.pprint()
746
800
       The command-line arguments, without the program name from argv[0]
747
801
       These should already be decoded. All library/test code calling
748
802
       run_bzr should be passing valid strings (don't need decoding).
749
 
    
 
803
 
750
804
    Returns a command status or raises an exception.
751
805
 
752
806
    Special master options: these must come before the command because
809
863
            argv_copy.append(a)
810
864
        i += 1
811
865
 
 
866
    debug.set_debug_flags_from_config()
 
867
 
812
868
    argv = argv_copy
813
869
    if (not argv):
814
870
        from bzrlib.builtins import cmd_help
915
971
 
916
972
 
917
973
def run_bzr_catch_errors(argv):
918
 
    # Note: The except clause logic below should be kept in sync with the
919
 
    # profile() routine in lsprof.py.
920
 
    try:
921
 
        return run_bzr(argv)
922
 
    except (KeyboardInterrupt, Exception), e:
923
 
        # used to handle AssertionError and KeyboardInterrupt
924
 
        # specially here, but hopefully they're handled ok by the logger now
925
 
        exc_info = sys.exc_info()
926
 
        exitcode = trace.report_exception(exc_info, sys.stderr)
927
 
        if os.environ.get('BZR_PDB'):
928
 
            print '**** entering debugger'
929
 
            tb = exc_info[2]
930
 
            import pdb
931
 
            if sys.version_info[:2] < (2, 6):
932
 
                # XXX: we want to do
933
 
                #    pdb.post_mortem(tb)
934
 
                # but because pdb.post_mortem gives bad results for tracebacks
935
 
                # from inside generators, we do it manually.
936
 
                # (http://bugs.python.org/issue4150, fixed in Python 2.6)
937
 
                
938
 
                # Setup pdb on the traceback
939
 
                p = pdb.Pdb()
940
 
                p.reset()
941
 
                p.setup(tb.tb_frame, tb)
942
 
                # Point the debugger at the deepest frame of the stack
943
 
                p.curindex = len(p.stack) - 1
944
 
                p.curframe = p.stack[p.curindex]
945
 
                # Start the pdb prompt.
946
 
                p.print_stack_entry(p.stack[p.curindex])
947
 
                p.execRcLines()
948
 
                p.cmdloop()
949
 
            else:
950
 
                pdb.post_mortem(tb)
951
 
        return exitcode
 
974
    """Run a bzr command with parameters as described by argv.
 
975
 
 
976
    This function assumed that that UI layer is setup, that symbol deprecations
 
977
    are already applied, and that unicode decoding has already been performed on argv.
 
978
    """
 
979
    return exception_to_return_code(run_bzr, argv)
952
980
 
953
981
 
954
982
def run_bzr_catch_user_errors(argv):
996
1024
 
997
1025
    def plugin_for_command(self, cmd_name):
998
1026
        '''Takes a command and returns the information for that plugin
999
 
        
1000
 
        :return: A dictionary with all the available information 
 
1027
 
 
1028
        :return: A dictionary with all the available information
1001
1029
        for the requested plugin
1002
1030
        '''
1003
1031
        raise NotImplementedError