diff options
| author | Richard Purdie <rpurdie@linux.intel.com> | 2010-01-20 18:46:02 +0000 | 
|---|---|---|
| committer | Richard Purdie <rpurdie@linux.intel.com> | 2010-01-20 18:46:02 +0000 | 
| commit | 22c29d8651668195f72e2f6a8e059d625eb511c3 (patch) | |
| tree | dd1dd43f0ec47a9964c8a766eb8b3ad75cf51a64 /bitbake-dev/lib/bb/shell.py | |
| parent | 1bfd6edef9db9c9175058ae801d1b601e4f15263 (diff) | |
| download | openembedded-core-22c29d8651668195f72e2f6a8e059d625eb511c3.tar.gz openembedded-core-22c29d8651668195f72e2f6a8e059d625eb511c3.tar.bz2 openembedded-core-22c29d8651668195f72e2f6a8e059d625eb511c3.zip | |
bitbake: Switch to bitbake-dev version (bitbake master upstream)
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'bitbake-dev/lib/bb/shell.py')
| -rw-r--r-- | bitbake-dev/lib/bb/shell.py | 824 | 
1 files changed, 0 insertions, 824 deletions
| diff --git a/bitbake-dev/lib/bb/shell.py b/bitbake-dev/lib/bb/shell.py deleted file mode 100644 index 66e51719a4..0000000000 --- a/bitbake-dev/lib/bb/shell.py +++ /dev/null @@ -1,824 +0,0 @@ -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- -########################################################################## -# -# Copyright (C) 2005-2006 Michael 'Mickey' Lauer <mickey@Vanille.de> -# Copyright (C) 2005-2006 Vanille Media -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -########################################################################## -# -# Thanks to: -# * Holger Freyther <zecke@handhelds.org> -# * Justin Patrin <papercrane@reversefold.com> -# -########################################################################## - -""" -BitBake Shell - -IDEAS: -    * list defined tasks per package -    * list classes -    * toggle force -    * command to reparse just one (or more) bbfile(s) -    * automatic check if reparsing is necessary (inotify?) -    * frontend for bb file manipulation -    * more shell-like features: -        - output control, i.e. pipe output into grep, sort, etc. -        - job control, i.e. bring running commands into background and foreground -    * start parsing in background right after startup -    * ncurses interface - -PROBLEMS: -    * force doesn't always work -    * readline completion for commands with more than one parameters - -""" - -########################################################################## -# Import and setup global variables -########################################################################## - -try: -    set -except NameError: -    from sets import Set as set -import sys, os, readline, socket, httplib, urllib, commands, popen2, copy, shlex, Queue, fnmatch -from bb import data, parse, build, fatal, cache, taskdata, runqueue, providers as Providers - -__version__ = "0.5.3.1" -__credits__ = """BitBake Shell Version %s (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de> -Type 'help' for more information, press CTRL-D to exit.""" % __version__ - -cmds = {} -leave_mainloop = False -last_exception = None -cooker = None -parsed = False -debug = os.environ.get( "BBSHELL_DEBUG", "" ) - -########################################################################## -# Class BitBakeShellCommands -########################################################################## - -class BitBakeShellCommands: -    """This class contains the valid commands for the shell""" - -    def __init__( self, shell ): -        """Register all the commands""" -        self._shell = shell -        for attr in BitBakeShellCommands.__dict__: -            if not attr.startswith( "_" ): -                if attr.endswith( "_" ): -                    command = attr[:-1].lower() -                else: -                    command = attr[:].lower() -                method = getattr( BitBakeShellCommands, attr ) -                debugOut( "registering command '%s'" % command ) -                # scan number of arguments -                usage = getattr( method, "usage", "" ) -                if usage != "<...>": -                    numArgs = len( usage.split() ) -                else: -                    numArgs = -1 -                shell.registerCommand( command, method, numArgs, "%s %s" % ( command, usage ), method.__doc__ ) - -    def _checkParsed( self ): -        if not parsed: -            print "SHELL: This command needs to parse bbfiles..." -            self.parse( None ) - -    def _findProvider( self, item ): -        self._checkParsed() -        # Need to use taskData for this information -        preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, cooker.configuration.data, 1 ) -        if not preferred: preferred = item -        try: -            lv, lf, pv, pf = Providers.findBestProvider(preferred, cooker.configuration.data, cooker.status) -        except KeyError: -            if item in cooker.status.providers: -                pf = cooker.status.providers[item][0] -            else: -                pf = None -        return pf - -    def alias( self, params ): -        """Register a new name for a command""" -        new, old = params -        if not old in cmds: -            print "ERROR: Command '%s' not known" % old -        else: -            cmds[new] = cmds[old] -            print "OK" -    alias.usage = "<alias> <command>" - -    def buffer( self, params ): -        """Dump specified output buffer""" -        index = params[0] -        print self._shell.myout.buffer( int( index ) ) -    buffer.usage = "<index>" - -    def buffers( self, params ): -        """Show the available output buffers""" -        commands = self._shell.myout.bufferedCommands() -        if not commands: -            print "SHELL: No buffered commands available yet. Start doing something." -        else: -            print "="*35, "Available Output Buffers", "="*27 -            for index, cmd in enumerate( commands ): -                print "| %s %s" % ( str( index ).ljust( 3 ), cmd ) -            print "="*88 - -    def build( self, params, cmd = "build" ): -        """Build a providee""" -        global last_exception -        globexpr = params[0] -        self._checkParsed() -        names = globfilter( cooker.status.pkg_pn.keys(), globexpr ) -        if len( names ) == 0: names = [ globexpr ] -        print "SHELL: Building %s" % ' '.join( names ) - -        td = taskdata.TaskData(cooker.configuration.abort) -        localdata = data.createCopy(cooker.configuration.data) -        data.update_data(localdata) -        data.expandKeys(localdata) - -        try: -            tasks = [] -            for name in names: -                td.add_provider(localdata, cooker.status, name) -                providers = td.get_provider(name) - -                if len(providers) == 0: -                    raise Providers.NoProvider - -                tasks.append([name, "do_%s" % cmd]) - -            td.add_unresolved(localdata, cooker.status) -             -            rq = runqueue.RunQueue(cooker, localdata, cooker.status, td, tasks) -            rq.prepare_runqueue() -            rq.execute_runqueue() - -        except Providers.NoProvider: -            print "ERROR: No Provider" -            last_exception = Providers.NoProvider - -        except runqueue.TaskFailure, fnids: -            for fnid in fnids: -                print "ERROR: '%s' failed" % td.fn_index[fnid] -            last_exception = runqueue.TaskFailure - -        except build.EventException, e: -            print "ERROR: Couldn't build '%s'" % names -            last_exception = e - - -    build.usage = "<providee>" - -    def clean( self, params ): -        """Clean a providee""" -        self.build( params, "clean" ) -    clean.usage = "<providee>" - -    def compile( self, params ): -        """Execute 'compile' on a providee""" -        self.build( params, "compile" ) -    compile.usage = "<providee>" - -    def configure( self, params ): -        """Execute 'configure' on a providee""" -        self.build( params, "configure" ) -    configure.usage = "<providee>" - -    def install( self, params ): -        """Execute 'install' on a providee""" -        self.build( params, "install" ) -    install.usage = "<providee>" - -    def edit( self, params ): -        """Call $EDITOR on a providee""" -        name = params[0] -        bbfile = self._findProvider( name ) -        if bbfile is not None: -            os.system( "%s %s" % ( os.environ.get( "EDITOR", "vi" ), bbfile ) ) -        else: -            print "ERROR: Nothing provides '%s'" % name -    edit.usage = "<providee>" - -    def environment( self, params ): -        """Dump out the outer BitBake environment""" -        cooker.showEnvironment() - -    def exit_( self, params ): -        """Leave the BitBake Shell""" -        debugOut( "setting leave_mainloop to true" ) -        global leave_mainloop -        leave_mainloop = True - -    def fetch( self, params ): -        """Fetch a providee""" -        self.build( params, "fetch" ) -    fetch.usage = "<providee>" - -    def fileBuild( self, params, cmd = "build" ): -        """Parse and build a .bb file""" -        global last_exception -        name = params[0] -        bf = completeFilePath( name ) -        print "SHELL: Calling '%s' on '%s'" % ( cmd, bf ) - -        try: -            cooker.buildFile(bf, cmd) -        except parse.ParseError: -            print "ERROR: Unable to open or parse '%s'" % bf -        except build.EventException, e: -            print "ERROR: Couldn't build '%s'" % name -            last_exception = e - -    fileBuild.usage = "<bbfile>" - -    def fileClean( self, params ): -        """Clean a .bb file""" -        self.fileBuild( params, "clean" ) -    fileClean.usage = "<bbfile>" - -    def fileEdit( self, params ): -        """Call $EDITOR on a .bb file""" -        name = params[0] -        os.system( "%s %s" % ( os.environ.get( "EDITOR", "vi" ), completeFilePath( name ) ) ) -    fileEdit.usage = "<bbfile>" - -    def fileRebuild( self, params ): -        """Rebuild (clean & build) a .bb file""" -        self.fileBuild( params, "rebuild" ) -    fileRebuild.usage = "<bbfile>" - -    def fileReparse( self, params ): -        """(re)Parse a bb file""" -        bbfile = params[0] -        print "SHELL: Parsing '%s'" % bbfile -        parse.update_mtime( bbfile ) -        cooker.bb_cache.cacheValidUpdate(bbfile) -        fromCache = cooker.bb_cache.loadData(bbfile, cooker.configuration.data, cooker.status) -        cooker.bb_cache.sync() -        if False: #fromCache: -            print "SHELL: File has not been updated, not reparsing" -        else: -            print "SHELL: Parsed" -    fileReparse.usage = "<bbfile>" - -    def abort( self, params ): -        """Toggle abort task execution flag (see bitbake -k)""" -        cooker.configuration.abort = not cooker.configuration.abort -        print "SHELL: Abort Flag is now '%s'" % repr( cooker.configuration.abort ) - -    def force( self, params ): -        """Toggle force task execution flag (see bitbake -f)""" -        cooker.configuration.force = not cooker.configuration.force -        print "SHELL: Force Flag is now '%s'" % repr( cooker.configuration.force ) - -    def help( self, params ): -        """Show a comprehensive list of commands and their purpose""" -        print "="*30, "Available Commands", "="*30 -        allcmds = cmds.keys() -        allcmds.sort() -        for cmd in allcmds: -            function,numparams,usage,helptext = cmds[cmd] -            print "| %s | %s" % (usage.ljust(30), helptext) -        print "="*78 - -    def lastError( self, params ): -        """Show the reason or log that was produced by the last BitBake event exception""" -        if last_exception is None: -            print "SHELL: No Errors yet (Phew)..." -        else: -            reason, event = last_exception.args -            print "SHELL: Reason for the last error: '%s'" % reason -            if ':' in reason: -                msg, filename = reason.split( ':' ) -                filename = filename.strip() -                print "SHELL: Dumping log file for last error:" -                try: -                    print open( filename ).read() -                except IOError: -                    print "ERROR: Couldn't open '%s'" % filename - -    def match( self, params ): -        """Dump all files or providers matching a glob expression""" -        what, globexpr = params -        if what == "files": -            self._checkParsed() -            for key in globfilter( cooker.status.pkg_fn.keys(), globexpr ): print key -        elif what == "providers": -            self._checkParsed() -            for key in globfilter( cooker.status.pkg_pn.keys(), globexpr ): print key -        else: -            print "Usage: match %s" % self.print_.usage -    match.usage = "<files|providers> <glob>" - -    def new( self, params ): -        """Create a new .bb file and open the editor""" -        dirname, filename = params -        packages = '/'.join( data.getVar( "BBFILES", cooker.configuration.data, 1 ).split('/')[:-2] ) -        fulldirname = "%s/%s" % ( packages, dirname ) - -        if not os.path.exists( fulldirname ): -            print "SHELL: Creating '%s'" % fulldirname -            os.mkdir( fulldirname ) -        if os.path.exists( fulldirname ) and os.path.isdir( fulldirname ): -            if os.path.exists( "%s/%s" % ( fulldirname, filename ) ): -                print "SHELL: ERROR: %s/%s already exists" % ( fulldirname, filename ) -                return False -            print "SHELL: Creating '%s/%s'" % ( fulldirname, filename ) -            newpackage = open( "%s/%s" % ( fulldirname, filename ), "w" ) -            print >>newpackage,"""DESCRIPTION = "" -SECTION = "" -AUTHOR = "" -HOMEPAGE = "" -MAINTAINER = "" -LICENSE = "GPL" -PR = "r0" - -SRC_URI = "" - -#inherit base - -#do_configure() { -# -#} - -#do_compile() { -# -#} - -#do_stage() { -# -#} - -#do_install() { -# -#} -""" -            newpackage.close() -            os.system( "%s %s/%s" % ( os.environ.get( "EDITOR" ), fulldirname, filename ) ) -    new.usage = "<directory> <filename>" - -    def package( self, params ): -        """Execute 'package' on a providee""" -        self.build( params, "package" ) -    package.usage = "<providee>" - -    def pasteBin( self, params ): -        """Send a command + output buffer to the pastebin at http://rafb.net/paste""" -        index = params[0] -        contents = self._shell.myout.buffer( int( index ) ) -        sendToPastebin( "output of " + params[0], contents ) -    pasteBin.usage = "<index>" - -    def pasteLog( self, params ): -        """Send the last event exception error log (if there is one) to http://rafb.net/paste""" -        if last_exception is None: -            print "SHELL: No Errors yet (Phew)..." -        else: -            reason, event = last_exception.args -            print "SHELL: Reason for the last error: '%s'" % reason -            if ':' in reason: -                msg, filename = reason.split( ':' ) -                filename = filename.strip() -                print "SHELL: Pasting log file to pastebin..." - -                file = open( filename ).read() -                sendToPastebin( "contents of " + filename, file ) - -    def patch( self, params ): -        """Execute 'patch' command on a providee""" -        self.build( params, "patch" ) -    patch.usage = "<providee>" - -    def parse( self, params ): -        """(Re-)parse .bb files and calculate the dependency graph""" -        cooker.status = cache.CacheData() -        ignore = data.getVar("ASSUME_PROVIDED", cooker.configuration.data, 1) or "" -        cooker.status.ignored_dependencies = set( ignore.split() ) -        cooker.handleCollections( data.getVar("BBFILE_COLLECTIONS", cooker.configuration.data, 1) ) - -        (filelist, masked) = cooker.collect_bbfiles() -        cooker.parse_bbfiles(filelist, masked, cooker.myProgressCallback) -        cooker.buildDepgraph() -        global parsed -        parsed = True -        print - -    def reparse( self, params ): -        """(re)Parse a providee's bb file""" -        bbfile = self._findProvider( params[0] ) -        if bbfile is not None: -            print "SHELL: Found bbfile '%s' for '%s'" % ( bbfile, params[0] ) -            self.fileReparse( [ bbfile ] ) -        else: -            print "ERROR: Nothing provides '%s'" % params[0] -    reparse.usage = "<providee>" - -    def getvar( self, params ): -        """Dump the contents of an outer BitBake environment variable""" -        var = params[0] -        value = data.getVar( var, cooker.configuration.data, 1 ) -        print value -    getvar.usage = "<variable>" - -    def peek( self, params ): -        """Dump contents of variable defined in providee's metadata""" -        name, var = params -        bbfile = self._findProvider( name ) -        if bbfile is not None: -            the_data = cooker.bb_cache.loadDataFull(bbfile, cooker.configuration.data) -            value = the_data.getVar( var, 1 ) -            print value -        else: -            print "ERROR: Nothing provides '%s'" % name -    peek.usage = "<providee> <variable>" - -    def poke( self, params ): -        """Set contents of variable defined in providee's metadata""" -        name, var, value = params -        bbfile = self._findProvider( name ) -        if bbfile is not None: -            print "ERROR: Sorry, this functionality is currently broken" -            #d = cooker.pkgdata[bbfile] -            #data.setVar( var, value, d ) - -            # mark the change semi persistant -            #cooker.pkgdata.setDirty(bbfile, d) -            #print "OK" -        else: -            print "ERROR: Nothing provides '%s'" % name -    poke.usage = "<providee> <variable> <value>" - -    def print_( self, params ): -        """Dump all files or providers""" -        what = params[0] -        if what == "files": -            self._checkParsed() -            for key in cooker.status.pkg_fn.keys(): print key -        elif what == "providers": -            self._checkParsed() -            for key in cooker.status.providers.keys(): print key -        else: -            print "Usage: print %s" % self.print_.usage -    print_.usage = "<files|providers>" - -    def python( self, params ): -        """Enter the expert mode - an interactive BitBake Python Interpreter""" -        sys.ps1 = "EXPERT BB>>> " -        sys.ps2 = "EXPERT BB... " -        import code -        interpreter = code.InteractiveConsole( dict( globals() ) ) -        interpreter.interact( "SHELL: Expert Mode - BitBake Python %s\nType 'help' for more information, press CTRL-D to switch back to BBSHELL." % sys.version ) - -    def showdata( self, params ): -        """Execute 'showdata' on a providee""" -        cooker.showEnvironment(None, params) -    showdata.usage = "<providee>" - -    def setVar( self, params ): -        """Set an outer BitBake environment variable""" -        var, value = params -        data.setVar( var, value, cooker.configuration.data ) -        print "OK" -    setVar.usage = "<variable> <value>" - -    def rebuild( self, params ): -        """Clean and rebuild a .bb file or a providee""" -        self.build( params, "clean" ) -        self.build( params, "build" ) -    rebuild.usage = "<providee>" - -    def shell( self, params ): -        """Execute a shell command and dump the output""" -        if params != "": -            print commands.getoutput( " ".join( params ) ) -    shell.usage = "<...>" - -    def stage( self, params ): -        """Execute 'stage' on a providee""" -        self.build( params, "populate_staging" ) -    stage.usage = "<providee>" - -    def status( self, params ): -        """<just for testing>""" -        print "-" * 78 -        print "building list = '%s'" % cooker.building_list -        print "build path = '%s'" % cooker.build_path -        print "consider_msgs_cache = '%s'" % cooker.consider_msgs_cache -        print "build stats = '%s'" % cooker.stats -        if last_exception is not None: print "last_exception = '%s'" % repr( last_exception.args ) -        print "memory output contents = '%s'" % self._shell.myout._buffer - -    def test( self, params ): -        """<just for testing>""" -        print "testCommand called with '%s'" % params - -    def unpack( self, params ): -        """Execute 'unpack' on a providee""" -        self.build( params, "unpack" ) -    unpack.usage = "<providee>" - -    def which( self, params ): -        """Computes the providers for a given providee""" -        # Need to use taskData for this information -        item = params[0] - -        self._checkParsed() - -        preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, cooker.configuration.data, 1 ) -        if not preferred: preferred = item - -        try: -            lv, lf, pv, pf = Providers.findBestProvider(preferred, cooker.configuration.data, cooker.status) -        except KeyError: -            lv, lf, pv, pf = (None,)*4 - -        try: -            providers = cooker.status.providers[item] -        except KeyError: -            print "SHELL: ERROR: Nothing provides", preferred -        else: -            for provider in providers: -                if provider == pf: provider = " (***) %s" % provider -                else:              provider = "       %s" % provider -                print provider -    which.usage = "<providee>" - -########################################################################## -# Common helper functions -########################################################################## - -def completeFilePath( bbfile ): -    """Get the complete bbfile path""" -    if not cooker.status: return bbfile -    if not cooker.status.pkg_fn: return bbfile -    for key in cooker.status.pkg_fn.keys(): -        if key.endswith( bbfile ): -            return key -    return bbfile - -def sendToPastebin( desc, content ): -    """Send content to http://oe.pastebin.com""" -    mydata = {} -    mydata["lang"] = "Plain Text" -    mydata["desc"] = desc -    mydata["cvt_tabs"] = "No" -    mydata["nick"] = "%s@%s" % ( os.environ.get( "USER", "unknown" ), socket.gethostname() or "unknown" ) -    mydata["text"] = content -    params = urllib.urlencode( mydata ) -    headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"} - -    host = "rafb.net" -    conn = httplib.HTTPConnection( "%s:80" % host ) -    conn.request("POST", "/paste/paste.php", params, headers ) - -    response = conn.getresponse() -    conn.close() - -    if response.status == 302: -        location = response.getheader( "location" ) or "unknown" -        print "SHELL: Pasted to http://%s%s" % ( host, location ) -    else: -        print "ERROR: %s %s" % ( response.status, response.reason ) - -def completer( text, state ): -    """Return a possible readline completion""" -    debugOut( "completer called with text='%s', state='%d'" % ( text, state ) ) - -    if state == 0: -        line = readline.get_line_buffer() -        if " " in line: -            line = line.split() -            # we are in second (or more) argument -            if line[0] in cmds and hasattr( cmds[line[0]][0], "usage" ): # known command and usage -                u = getattr( cmds[line[0]][0], "usage" ).split()[0] -                if u == "<variable>": -                    allmatches = cooker.configuration.data.keys() -                elif u == "<bbfile>": -                    if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ] -                    else: allmatches = [ x.split("/")[-1] for x in cooker.status.pkg_fn.keys() ] -                elif u == "<providee>": -                    if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ] -                    else: allmatches = cooker.status.providers.iterkeys() -                else: allmatches = [ "(No tab completion available for this command)" ] -            else: allmatches = [ "(No tab completion available for this command)" ] -        else: -            # we are in first argument -            allmatches = cmds.iterkeys() - -        completer.matches = [ x for x in allmatches if x[:len(text)] == text ] -        #print "completer.matches = '%s'" % completer.matches -    if len( completer.matches ) > state: -        return completer.matches[state] -    else: -        return None - -def debugOut( text ): -    if debug: -        sys.stderr.write( "( %s )\n" % text ) - -def columnize( alist, width = 80 ): -    """ -    A word-wrap function that preserves existing line breaks -    and most spaces in the text. Expects that existing line -    breaks are posix newlines (\n). -    """ -    return reduce(lambda line, word, width=width: '%s%s%s' % -                  (line, -                   ' \n'[(len(line[line.rfind('\n')+1:]) -                         + len(word.split('\n',1)[0] -                              ) >= width)], -                   word), -                  alist -                 ) - -def globfilter( names, pattern ): -    return fnmatch.filter( names, pattern ) - -########################################################################## -# Class MemoryOutput -########################################################################## - -class MemoryOutput: -    """File-like output class buffering the output of the last 10 commands""" -    def __init__( self, delegate ): -        self.delegate = delegate -        self._buffer = [] -        self.text = [] -        self._command = None - -    def startCommand( self, command ): -        self._command = command -        self.text = [] -    def endCommand( self ): -        if self._command is not None: -            if len( self._buffer ) == 10: del self._buffer[0] -            self._buffer.append( ( self._command, self.text ) ) -    def removeLast( self ): -        if self._buffer: -            del self._buffer[ len( self._buffer ) - 1 ] -        self.text = [] -        self._command = None -    def lastBuffer( self ): -        if self._buffer: -            return self._buffer[ len( self._buffer ) -1 ][1] -    def bufferedCommands( self ): -        return [ cmd for cmd, output in self._buffer ] -    def buffer( self, i ): -        if i < len( self._buffer ): -            return "BB>> %s\n%s" % ( self._buffer[i][0], "".join( self._buffer[i][1] ) ) -        else: return "ERROR: Invalid buffer number. Buffer needs to be in (0, %d)" % ( len( self._buffer ) - 1 ) -    def write( self, text ): -        if self._command is not None and text != "BB>> ": self.text.append( text ) -        if self.delegate is not None: self.delegate.write( text ) -    def flush( self ): -        return self.delegate.flush() -    def fileno( self ): -        return self.delegate.fileno() -    def isatty( self ): -        return self.delegate.isatty() - -########################################################################## -# Class BitBakeShell -########################################################################## - -class BitBakeShell: - -    def __init__( self ): -        """Register commands and set up readline""" -        self.commandQ = Queue.Queue() -        self.commands = BitBakeShellCommands( self ) -        self.myout = MemoryOutput( sys.stdout ) -        self.historyfilename = os.path.expanduser( "~/.bbsh_history" ) -        self.startupfilename = os.path.expanduser( "~/.bbsh_startup" ) - -        readline.set_completer( completer ) -        readline.set_completer_delims( " " ) -        readline.parse_and_bind("tab: complete") - -        try: -            readline.read_history_file( self.historyfilename ) -        except IOError: -            pass  # It doesn't exist yet. - -        print __credits__ - -    def cleanup( self ): -        """Write readline history and clean up resources""" -        debugOut( "writing command history" ) -        try: -            readline.write_history_file( self.historyfilename ) -        except: -            print "SHELL: Unable to save command history" - -    def registerCommand( self, command, function, numparams = 0, usage = "", helptext = "" ): -        """Register a command""" -        if usage == "": usage = command -        if helptext == "": helptext = function.__doc__ or "<not yet documented>" -        cmds[command] = ( function, numparams, usage, helptext ) - -    def processCommand( self, command, params ): -        """Process a command. Check number of params and print a usage string, if appropriate""" -        debugOut( "processing command '%s'..." % command ) -        try: -            function, numparams, usage, helptext = cmds[command] -        except KeyError: -            print "SHELL: ERROR: '%s' command is not a valid command." % command -            self.myout.removeLast() -        else: -            if (numparams != -1) and (not len( params ) == numparams): -                print "Usage: '%s'" % usage -                return - -            result = function( self.commands, params ) -            debugOut( "result was '%s'" % result ) - -    def processStartupFile( self ): -        """Read and execute all commands found in $HOME/.bbsh_startup""" -        if os.path.exists( self.startupfilename ): -            startupfile = open( self.startupfilename, "r" ) -            for cmdline in startupfile: -                debugOut( "processing startup line '%s'" % cmdline ) -                if not cmdline: -                    continue -                if "|" in cmdline: -                    print "ERROR: '|' in startup file is not allowed. Ignoring line" -                    continue -                self.commandQ.put( cmdline.strip() ) - -    def main( self ): -        """The main command loop""" -        while not leave_mainloop: -            try: -                if self.commandQ.empty(): -                    sys.stdout = self.myout.delegate -                    cmdline = raw_input( "BB>> " ) -                    sys.stdout = self.myout -                else: -                    cmdline = self.commandQ.get() -                if cmdline: -                    allCommands = cmdline.split( ';' ) -                    for command in allCommands: -                        pipecmd = None -                        # -                        # special case for expert mode -                        if command == 'python': -                            sys.stdout = self.myout.delegate -                            self.processCommand( command, "" ) -                            sys.stdout = self.myout -                        else: -                            self.myout.startCommand( command ) -                            if '|' in command: # disable output -                                command, pipecmd = command.split( '|' ) -                                delegate = self.myout.delegate -                                self.myout.delegate = None -                            tokens = shlex.split( command, True ) -                            self.processCommand( tokens[0], tokens[1:] or "" ) -                            self.myout.endCommand() -                            if pipecmd is not None: # restore output -                                self.myout.delegate = delegate - -                                pipe = popen2.Popen4( pipecmd ) -                                pipe.tochild.write( "\n".join( self.myout.lastBuffer() ) ) -                                pipe.tochild.close() -                                sys.stdout.write( pipe.fromchild.read() ) -                        # -            except EOFError: -                print -                return -            except KeyboardInterrupt: -                print - -########################################################################## -# Start function - called from the BitBake command line utility -########################################################################## - -def start( aCooker ): -    global cooker -    cooker = aCooker -    bbshell = BitBakeShell() -    bbshell.processStartupFile() -    bbshell.main() -    bbshell.cleanup() - -if __name__ == "__main__": -    print "SHELL: Sorry, this program should only be called by BitBake." | 
