add first (preview) version of the bitbake interactive mode
[bitbake.git] / lib / bb / shell.py
1 #!/usr/bin/env python
2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 #
5 # Copyright (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de>, Vanille Media
6 #
7 # This program is free software; you can redistribute it and/or modify it under
8 # the terms of the GNU General Public License as published by the Free Software
9 # Foundation; version 2 of the License.
10 #
11 # This program is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 # Place, Suite 330, Boston, MA 02111-1307 USA.
18 #
19
20 """
21 BitBake Shell
22
23 General Question to be decided: Make it a full-fledged Python Shell or
24 retain the simple command line interface like it is at the moment?
25
26 TODO:
27     * readline completion (file and provider?)
28     * specify tasks
29     * specify force
30     * command to clean stamps
31     * command to reparse one bbfile
32     * automatic check if reparsing is necessary (inotify?)
33     * bb file wizard
34     * call editor on bb file
35     * clean-and-rebuild bbfile
36 """
37
38 import sys, os, imp, readline
39 imp.load_source( "bitbake", os.path.dirname( sys.argv[0] )+"/bitbake" )
40 from bb import make, data
41
42 __version__ = 0.1
43 __credits__ = """BitBake Shell Version %2.1f (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
44 Type 'help' for more information, press CTRL-D to exit.""" % __version__
45
46 cmds = {}
47 cooker = None
48 parsed = False
49 debug = False
50
51 def rebuildCommand( params ):
52     """Clean and rebuild a .bb file or a provider"""
53     print "BBSHELL: sorry, not yet implemented :/"
54
55 def buildCommand( params ):
56     """Build a .bb file or a provider"""
57     try:
58         name = params[0]
59     except IndexError:
60         print "Usage: build <bbfile|provider>"
61     else:
62         if name.endswith( ".bb" ):
63             cooker.executeOneBB( os.path.abspath( name ) )
64         else:
65             if not parsed:
66                 print "BBSHELL: D'oh! The .bb files haven't been parsed yet. Next time call 'parse' before building stuff. This time I'll do it for 'ya."
67                 parseCommand( None )
68             cooker.buildPackage( name )
69
70 def parseCommand( params ):
71     """(Re-)parse .bb files and calculate the dependency graph"""
72     cooker.status = cooker.ParsingStatus()
73     ignore = data.getVar("ASSUME_PROVIDED", make.cfg, 1) or ""
74     cooker.status.ignored_dependencies = set( ignore.split() )
75     cooker.handleCollections( data.getVar("BBFILE_COLLECTIONS", make.cfg, 1) )
76
77     make.collect_bbfiles( cooker.myProgressCallback )
78     cooker.buildDepgraph()
79     global parsed
80     parsed = True
81     print
82
83 def environmentCommand( params ):
84     """Dump out the outer BitBake environment (see bbread)"""
85     data.emit_env(sys.__stdout__, make.cfg, True)
86
87 def printCommand( params ):
88     """Print the contents of an outer BitBake environment variable"""
89     try:
90         var = params[0]
91     except IndexError:
92         print "Usage: print <variable>"
93     else:
94         value = data.getVar( var, make.cfg, 1 )
95         print value
96
97 def setVarCommand( params ):
98     """Set an outer BitBake environment variable"""
99     try:
100         var, value = params
101     except ValueError, IndexError:
102         print "Usage: set <variable> <value>"
103     else:
104         data.setVar( var, value, make.cfg )
105         print "OK"
106
107 def init():
108     """Register commands and set up readline"""
109     registerCommand( "help", showHelp )
110     registerCommand( "exit", exitShell )
111     
112     registerCommand( "build", buildCommand )
113     registerCommand( "environment", environmentCommand )
114     registerCommand( "rebuild", rebuildCommand )
115     registerCommand( "parse", parseCommand )
116     registerCommand( "print", printCommand )
117     registerCommand( "set", setVarCommand )
118     
119     readline.set_completer( completer )
120     readline.parse_and_bind("tab: complete")
121
122 def exitShell( params ):
123     """Leave the BitBake Shell"""
124     sys.exit(0)
125
126 def completer( *args, **kwargs ):
127     print "completer called", args, kwargs
128     return None
129
130 def showCredits():
131     print __credits__
132
133 def showHelp( *args ):
134     """Show a comprehensive list of commands and their purpose"""
135     print "="*35, "Available Commands", "="*35
136     for cmd, func in cmds.items():
137         print "| %s | %s" % (cmd.ljust(max([len(x) for x in cmds.keys()])), func.__doc__)
138     print "="*88
139
140 def registerCommand( command, function ):
141     cmds[command] = function
142
143 def processCommand( command, params ):
144     if debug: print "(processing command '%s'...)" % command
145     if command in cmds:
146         result = cmds[command]( params )
147     else:
148         print "Error: '%s' command is not a valid command." % command
149         return
150     if debug: print "(result was '%s')" % result
151
152 def main():
153     while True:
154         try:
155             cmdline = raw_input( "BB>> " )
156             if cmdline:
157                 if ' ' in cmdline:
158                     processCommand( cmdline.split()[0], cmdline.split()[1:] )
159                 else:
160                     processCommand( cmdline, "" )
161         except EOFError:
162             print
163             return
164         except KeyboardInterrupt:
165             print
166
167 def start( aCooker ):
168     global cooker
169     cooker = aCooker
170     showCredits()
171     init()
172     main()
173
174 if __name__ == "__main__":
175     print "BBSHELL: Sorry, this program should only be called by BitBake."