#!/usr/bin/python -OO
import os,sys
__app__=os.path.basename(sys.argv[0])
import string,getopt,types
# we need this hard-coded path because we need a module here before we can parse our config file
__maintainer__="Daniel Robbins <drobbins@funtoo.org>"
__license__=""" Distributed under the terms of the GNU General Public License version 2
Metro comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to
redistribute it under certain conditions. See /usr/lib/metro/LICENSE for details.
"""
__status__="Release"
__version__="1.4.2"
def usage():
version()
print """ metro [OPTION]... [FILE]...
-h, --help Print this message
-V, --version Display version information
-d, --debug Enable debug mode
-v, --verbose Verbose mode
-l [dir], --libdir [dir] Use alternate library dir (default /usr/lib/metro)
-N, --notrigger Disable build triggers
-k [key], --key [key] Print value of [key], ie. "distfiles"
[FILE] File(s) to parse and evaluate
"""
def version():
print " "+__app__,"version",__version__
print
print " Copyright 2008-2009 Funtoo Technologies, LLC; Portions copyright 2003-2007 Gentoo Foundation"
print " Maintainer:",__maintainer__
print
print " Web: http://www.funtoo.org"
print " Project: http://github.com/funtoo/metro/wikis"
print
print __license__
def find_target(settings):
"""
Use the "metro/class" setting in our metadata to initialize the proper class defined in the modules/targets.py module.
The targets.__dict__ dictionary contains all the objects in the targets module. We look inside it to see if the class
defined in "metro/class" exists in there and is a class. If not, we raise an exception.
"""
if not targets.__dict__.has_key(settings["metro/class"]):
raise MetroError, "Metro class "+settings["metro/class"]+" not defined in modules/targets.py."
if type(targets.__dict__[settings["metro/class"]]) != types.ClassType:
raise MetroError, "Metro class "+settings["metro/class"]+" does not appear to be a class."
return targets.__dict__[settings["metro/class"]](settings)
debug=False
def initSettings(configfile,args,extraargs={}):
settings=flexdata.collection()
if os.path.exists(configfile):
settings.collect(configfile,None)
else:
print "Error: config file %s not found." % configfile
sys.exit(1)
# parse command-line supplied configuration files and spec files in the order they were specified
apos = 0
while apos < len(args):
if args[apos][-1] == ":":
# args such as: target/version: 2008.10.12 - parse both of these args
if apos+1 >= len(args):
raise MetroError, "Missing value argument for %s" % args[apos]
settings[args[apos][:-1]] = args[apos+1]
apos += 2
else:
raise MetroError, "cmdline argument '%s' invalid - does not end in a colon" % args[apos]
for arg in extraargs.keys():
settings[arg]=extraargs[arg]
settings.runCollector()
return settings
def main():
if os.getuid() != 0:
print __app__ + ": This script requires root privileges to operate."
sys.exit(2)
# we need some options in order to work correctly
if len(sys.argv) < 2:
usage()
sys.exit(2)
# parse out the command line arguments
try:
opts,args = getopt.getopt(sys.argv[1:], "dhvxVk:l:", ["debug","help", "verbose", "version","key=","libdir="])
except getopt.GetoptError:
usage()
sys.exit(2)
# defaults for commandline opts
verbose=False
myopts=[]
strict=True
# check preconditions
valueme=None
optdict={}
for opt,optarg in opts:
optdict[opt]=optarg
# Step 1: parse optional arguments that affect behavior of the program
if optdict.has_key("-d") or optdict.has_key("--debug"):
debug=True
if optdict.has_key("-v") or optdict.has_key("--verbose"):
verbose=True
binpath=os.path.abspath(sys.argv[0])
if os.path.islink(binpath):
binpath=os.readlink(binpath)
libdir=os.path.dirname(binpath)
if optdict.has_key("-l") or optdict.has_key("--libdir"):
if optdict.has_key("-l"):
libdir = optdict["-l"]
else:
libdir = optdict["--libdir"]
sys.stderr.write("Metro: Using library directory of %s.\n" % libdir)
sys.path.append(libdir+"/modules")
configfile = libdir+"/etc/metro.conf"
sys.stderr.write("Metro: Using main configuration file %s.\n" % configfile)
global flexdata
global targets
global MetroError
import flexdata
import targets
# for MetroError:
from catalyst_support import MetroError
# Step 2: check for "special" help/version options, handle them and exit:
if optdict.has_key("-h") or optdict.has_key("--help"):
usage()
sys.exit(1)
elif optdict.has_key("-V") or optdict.has_key("--version"):
version()
sys.exit(1)
# Step 3: check for duplicate main options, which is an error
mainargs=0
for x in [ "-k", "--key" ]:
if optdict.has_key(x):
mainargs += 1
if mainargs > 1:
print "Please specify only one -k or --key option at a time."
sys.exit(1)
# Step 4: parse main options
if optdict.has_key("-k") or optdict.has_key("--key"):
if optdict.has_key("-k"):
valueme=optdict["-k"]
else:
valueme=optdict["--key"]
# Step 5: Initialize Metro data:
settings = initSettings(configfile,args)
# Step 6: Create list of targets to run, checking whether "multi" mode is enabled
if valueme:
print settings[valueme]
sys.exit(1)
if settings.has_key("multi") and settings["multi"]=="yes":
targetlist=string.split(settings["multi/targets"])
# build automation mode
elif settings.has_key("target"):
targetlist=[settings["target"]]
else:
raise MetroError("Please specify a target or enable multi mode.")
for targetname in targetlist:
# Step 7a,b: Reinitialize settings, initialize target element to proper value:
print "Multi-mode: running target %s" % targetname
settings = initSettings(configfile,args,{"target":targetname})
# Step 7c: find and run target
target = find_target(settings)
print __app__+": running target \""+settings["target"]+"\"."
target.run()
print __app__+": complete."
try:
main()
except KeyboardInterrupt:
print "\n" + __app__ +" build aborted due to user interrupt (ctrl-C)"
print
print __app__,"aborting..."
raise
sys.exit(2)