test fix
[catalyst.git] / catalyst
index 7fd83bf3ca4ee538b3dd84f8130bdfd564def837..8337824ece92454a3e340f0b0aa58dacef6008ad 100755 (executable)
--- a/catalyst
+++ b/catalyst
 
 import os,sys,imp,string
 
-def die(msg=None):
-       if msg:
-               print "catalyst: "+msg
-       sys.exit(1)
+def usage():
+       print "Usage: catalyst [-f file] [variable=value ...]"
+       print " -h --help               print this usage and exit"
+       print " -v --version            display version information"
+       print " -f --file               read specified file for build instructions"
+       print " variable=value          specify a variable/value pair"
 
-def warn(msg):
-       print "catalyst: "+msg
+def vers():
+       print "Gentoo catalyst, version "+version
+       print "Copyright 2003-2004 Gentoo Technologies, Inc."
+       print "Distributed under the GNU General Public License version 2"
 
-def usage():
-       print "usage: meep!"
+version="1.0"
 
 if len(sys.argv)==1 or sys.argv[1] in ["-h","--help"]:
        usage()
        sys.exit(1)
-
-def arg_parse(mydict, myvalids):
-       "very wimpy argument parsing, just for the prototype"
-       for x in sys.argv[1:]:
-               foo=string.split(x,"=")
-               if len(foo)!=2:
-                       die("Invalid arg syntax: "+x)
-               else:
-                       if foo[0] not in myvalids:
-                               die("Invalid arg name: "+foo[0])
-                       mydict[foo[0]]=foo[1]
-                       
-def spec_dump(myspec):
-       for x in myspec.keys():
-               print x+": "+repr(myspec[x])
-
-"""
-Overview of catalyst operation
-==============================
-
-* The program starts, and the local machine type is detected. 
-
-* Based on this information, catalyst determines what kind of machine types
-  it can build for (amd64 and ia64 can build for x86 as well, for example.)
-  The appropriate arch plugins are loaded, which contain builder classes
-  for each supported sub-arch.
-
-* Command-line arguments are parsed. If specified, a spec file is read.
-
-* These build variables are stored in an internal "spec" object, which will
-  be a standard python dictionary. This spec dictionary contains all relevant
-  build-related information.
-
-* The spec object is passed to the appropriate subarch builder constructor.
-  The subarch builder constructor updates the spec object with variables
-  relevant to the sub-arch (pentium4, g3, etc.)
-
-* The spec object is passed to the appropriate target constructor.
-  The target constructor updates the spec object to contain data relevant
-  to the particular target (stage1, stage3, grp, etc.)
-
-*** PROTOTYPE CODE UP TO HERE IS COMPLETE (drobbins, 26 Oct '03)
-
-* The full data of the spec object is written to disc, so there is a complete
-  record of all variables that will be used to build what we're building.  This
-  will allow for another person to re-use this information to replicate our
-  work (it should be possible to distribute a spec file along with a portage
-  snapshot and a starter tarball, and our build can be replicated exactly on
-  any machine.) The spec object contains data like CFLAGS, CHOST, subarch,
-  mainarch, the profile used to build, and for GRP and LiveCDs the complete
-  package build list. This is important to allow work to be replicated. It's
-  possible that the stage1/2/3.sh and other scripts should be distributed as
-  well, to allow proper replication of work.
-
-* The build process begins by calling the appropriate method of the builder
-  instance. This includes cleanup, setup of chroot, entering the chroot,
-  running the appropriate bash build script, checking for error conditions,
-  and finishing up.
-  
-* The catalyst process is now complete :)
-"""
-
-#This allows plugins to import modules in the /modules dir
-sys.path.append(os.getcwd()+"/modules")
-
-#map current machine information from uname() to the mainarch we are running
-#under
-
-machinemap={   "i386" : "x86",
-               "i486" : "x86",
-               "i586" : "x86",
-               "i686" : "x86",
-               "x86_64" : "amd64"
-       }
-
-# map the mainarch we are running under to the mainarches we support for
-# building stages and LiveCDs. (for example, on amd64, we can build stages for
-# x86 or amd64.
-
-targetmap={    "x86" : ["x86"],
-               "amd64" : ["x86","amd64"]
-       }
-               
-mymachine=os.uname()[4]
-if not machinemap.has_key(mymachine):
-       print "Unknown machine type:",mymachine
+elif sys.argv[1] in ["-v","--version"]:
+       vers()
        sys.exit(1)
-hostarch=machinemap[mymachine]
-print "Host architecture:",hostarch
-print "Supported architectures for targets:",string.join(targetmap[hostarch])
-print "Loading plugins:",
-archmap={}
-subarchmap={}
-for x in targetmap[hostarch]:
-       fh=open("arch/"+x+".py")
-       #this next line loads the plugin as a module and assigns it to archmap[x]
-       archmap[x]=imp.load_module(x,fh,"arch/"+x+".py",(".py","r",imp.PY_SOURCE))
-       #this next line registers all the subarches supported in the plugin
-       archmap[x].register(subarchmap)
-       fh.close()      
-       print x,
-print
-print "Available subarches:",string.join(subarchmap.keys())
-
-import targets
-targetmap={}
-targets.register(targetmap)
-
-print "Available targets:",string.join(targetmap.keys())
-
 if os.getuid()!=0:
        #non-root callers can't go any further than here. 
-       die("This script requires root privileges to operate.") 
+       print "catalyst: This script requires root privileges to operate."
+       sys.exit(1)
 
-#the spec begins!
-validspec=["version_stamp","target","subarch","rel_type","rel_version","snapshot","source_subpath"]
 myspec={}
+myconf={}
+if os.path.exists("/etc/catalyst.conf"):
+       try:
+               execfile("/etc/catalyst.conf",myconf,myconf)
+       except:
+               print "catalyst: Unable to /etc/catalyst.conf config file (syntax error)"
+               sys.exit(1)
+
+confdefaults={ "storedir":"/var/tmp/catalyst","sharedir":"/usr/share/catalyst","distdir":"/usr/portage/distfiles",
+"portdir":"/usr/portage","options":"ccache"}
+
+for x in confdefaults.keys():
+       if myconf.has_key(x):
+               print "Setting",x,"to config file value \""+myconf[x]+"\""
+               myspec[x]=myconf[x]
+       else:
+               print "Setting",x,"to default value \""+confdefaults[x]+"\""
+               myspec[x]=confdefaults[x]
+
+#This allows plugins (and this code) to import modules in the /modules dir
+sys.path.append(myspec["sharedir"]+"/modules")
+try:
+       from catalyst_support import *
+       import targets
+except ImportError:
+       print "catalyst: python modules not found in "+myspec["sharedir"]+"/modules; exiting."
+       sys.exit(1)
 
-"""
-local variables from spec:
-
-version_stamp                  20031016                                        user (from spec)
-target                         stage3                                          user (from spec)
-subarch                                pentium4                                        user (from spec)
-rel_type                       default                                         user (from spec) (was BUILDTYPE)
-rel_version                    1.4                                             user (from spec) (was MAINVERSION)
-snapshot                       20031016                                        user (from spec)
-source_subpath                 default-x86-1.4/stage2-pentium4-20031016        user (from spec)
-"""
-
-arg_parse(myspec,validspec)
-#need to verify that we have all required args here. Leaving this out for the prototype.
-if myspec["subarch"] not in subarchmap.keys():
-       die("Sub-arch "+myspec["subarch"]+" not available.")
-
-#call builder constructor:
-mybuilder=subarchmap[myspec["subarch"]](myspec)
-if myspec["target"] not in targetmap.keys():
-       die("Target "+myspec["target"]+" not available.")
-
-#these would come from /etc/catalyst.conf:
-myspec["storedir"]="/var/tmp/catalyst"
-myspec["sharedir"]="/usr/share/catalyst"
-#these would come from there too?:
-myspec["distdir"]="/usr/portage/distfiles"
-myspec["portdir"]="/usr/portage"
-
-#call target constructor:
-mytarget=targetmap[myspec["target"]](myspec)
-print
-spec_dump(myspec)
-
-#to test this program, type:
-
-# ./catalyst subarch=pentium4 version_stamp=20031016 target=stage3 rel_type=default rel_version=1.4 snapshot=20031016 source_subpath=default-x86-1.4/stage2-pentium4-20031016
+targetmap={}
+targets.register(targetmap)
 
+if "ccache" in string.split(myspec["options"]):
+       if not os.path.exists("/root/.ccache"):
+               os.makedirs("/root/.ccache")
+       print "Compiler cache support enabled."
+       myspec["CCACHE"]="1"
+if "pkgcache" in string.split(myspec["options"]):
+       print "Package cache support enabled."
+       myspec["PKGCACHE"]="1"
+
+if sys.argv[1] in ["-f", "--file" ]:
+       try:
+               addlargs=read_spec(sys.argv[2])
+       except:
+               raise CatalystError,"Unable to read spec file: "+sys.argv[2]
+       unparsedargs=sys.argv[3:]
+else:
+       addlargs={}
+       unparsedargs=sys.argv[1:]
+try:
+       arg_parse(myspec,addlargs,unparsedargs)
+       if not targetmap.has_key(myspec["target"]):
+               raise CatalystError,"Target \""+myspec["target"]+"\" not available."
+       mytarget=targetmap[myspec["target"]](myspec,addlargs)
+       
+       mytarget.run()
+except CatalystError:
+       sys.exit(1)