1 # Distributed under the GNU General Public License version 2
2 # Copyright 2003-2004 Gentoo Technologies, Inc.
3 # $Header: /var/cvsroot/gentoo/src/catalyst/modules/catalyst_support.py,v 1.23 2004/06/16 18:34:23 zhen Exp $
5 import sys,string,os,types
7 # these should never be touched
8 required_build_targets=["generic_target","generic_stage_target"]
10 # new build types should be added here
11 valid_build_targets=["stage1_target","stage2_target","stage3_target","grp_target",
12 "livecd_stage1_target","livecd_stage2_target","embedded_target",
13 "tinderbox_target","snapshot_target"]
15 required_config_file_values=["storedir","sharedir","distdir","portdir"]
16 valid_config_file_values=required_config_file_values[:]
17 valid_config_file_values.append("PKGCACHE")
18 valid_config_file_values.append("CCACHE")
19 valid_config_file_values.append("DISTCC")
20 valid_config_file_values.append("ENVSCRIPT")
21 valid_config_file_values.append("options")
25 def list_bashify(mylist):
26 if type(mylist)==types.StringType:
30 for x in range(0,len(mypack)):
31 # surround args with quotes for passing to bash,
32 # allows things like "<" to remain intact
33 mypack[x]="'"+mypack[x]+"'"
34 mypack=string.join(mypack)
37 class CatalystError(Exception):
38 def __init__(self, message):
41 print "!!! catalyst: "+message
48 print "!!! catalyst: "+msg
50 def spawn(mystring,debug=0,fd_pipes=None):
52 apparently, os.system mucks up return values, so this code
55 Taken from portage.py - thanks to carpaski@gentoo.org
57 print "Running command \""+mystring+"\""
59 mycommand = "/bin/bash"
61 myargs=["bash","-x","-c",mystring]
63 myargs=["bash","-c",mystring]
68 os.dup2(fd_pipes[0], 0) # stdin -- (Read)/Write
69 os.dup2(fd_pipes[1], 1) # stdout -- Read/(Write)
70 os.dup2(fd_pipes[2], 2) # stderr -- Read/(Write)
72 os.execvp(mycommand,myargs)
74 raise CatalystError,myexc
76 # If the execve fails, we need to report it, and exit
77 # *carefully* --- report error here
80 return # should never get reached
81 retval=os.waitpid(mypid,0)[1]
82 if (retval & 0xff)==0:
83 return (retval >> 8) # return exit code
85 return ((retval & 0xff) << 8) # interrupted by signal
87 def cmd(mycmd,myexc=""):
91 raise CatalystError,myexc
92 except KeyboardInterrupt:
93 raise CatalystError,"Build aborting due to user intervention"
95 def file_locate(settings,filelist,expand=1):
96 #if expand=1, non-absolute paths will be accepted and
97 # expanded to os.getcwd()+"/"+localpath if file exists
98 for myfile in filelist:
99 if not settings.has_key(myfile):
100 #filenames such as cdtar are optional, so we don't assume the variable is defined.
102 if len(settings[myfile])==0:
103 raise CatalystError, "File variable \""+myfile+"\" has a length of zero (not specified.)"
104 if settings[myfile][0]=="/":
105 if not os.path.exists(settings[myfile]):
106 raise CatalystError, "Cannot locate specified "+myfile+": "+settings[myfile]
107 elif expand and os.path.exists(os.getcwd()+"/"+settings[myfile]):
108 settings[myfile]=os.getcwd()+"/"+settings[myfile]
110 raise CatalystError, "Cannot locate specified "+myfile+": "+settings[myfile]+" (2nd try)"
115 The spec file format is a very simple and easy-to-use format for storing data. Here's an example
125 This file would be interpreted as defining three items: item1, item2 and item3. item1 would contain
126 the string value "value1". Item2 would contain an ordered list [ "foo", "bar", "oni" ]. item3
127 would contain an ordered list as well: [ "meep", "bark", "gleep", "moop" ]. It's important to note
128 that the order of multiple-value items is preserved, but the order that the items themselves are
129 defined are not preserved. In other words, "foo", "bar", "oni" ordering is preserved but "item1"
130 "item2" "item3" ordering is not, as the item strings are stored in a dictionary (hash).
133 def parse_spec(mylines):
136 while pos<len(mylines):
137 if len(mylines[pos])<=1:
141 if mylines[pos][0] in ["#"," ","\t"]:
142 #skip indented lines, comments
146 myline=mylines[pos].split()
148 if (len(myline)==0) or (myline[0][-1] != ":"):
149 msg("Skipping invalid spec line "+repr(pos))
151 myline[0]=myline[0][:-1]
153 #foo: bar --> foo:"bar"
154 myspec[myline[0]]=myline[1]
157 #foo: bar oni --> foo: [ "bar", "oni" ]
158 myspec[myline[0]]=myline[1:]
164 # --> foo: [ "bar", "oni", "meep" ]
167 while (pos<len(mylines)):
168 if len(mylines[pos])<=1:
172 if mylines[pos][0] == "#":
176 if mylines[pos][0] in [" ","\t"]:
177 #indented line, add to accumulator
178 accum.extend(mylines[pos].split())
181 #we've hit the next item, break out
183 myspec[myline[0]]=accum
186 def read_spec(myspecfile):
188 myf=open(myspecfile,"r")
190 raise CatalystError, "Could not open spec file "+myspecfile
191 mylines=myf.readlines()
193 return parse_spec(mylines)
195 def msg(mymsg,verblevel=1):
196 if verbosity>=verblevel:
200 "enhanced to handle bind mounts"
201 if os.path.ismount(path):
203 a=open("/proc/mounts","r")
204 mylines=a.readlines()
208 if path == mysplit[1]:
212 def arg_parse(mydict,remaining,argv):
213 "grab settings from argv, storing 'target' in mydict, and everything in remaining for later parsing"
214 global required_config_file_values
216 foo=string.split(x,"=")
218 raise CatalystError, "Invalid arg syntax: "+x
219 remaining[foo[0]]=foo[1]
220 if not remaining.has_key("target"):
221 raise CatalystError, "Required value \"target\" not specified."
222 mydict["target"]=remaining["target"]
223 for x in required_config_file_values:
224 if not mydict.has_key(x):
225 raise CatalystError, "Required config file value \""+x+"\" not found."
228 def addl_arg_parse(myspec,addlargs,requiredspec,validspec):
229 "helper function to help targets parse additional arguments"
230 global valid_config_file_values
231 for x in addlargs.keys():
232 if x not in validspec and x not in valid_config_file_values:
233 raise CatalystError, "Argument \""+x+"\" not recognized."
235 myspec[x]=addlargs[x]
236 for x in requiredspec:
237 if not myspec.has_key(x):
238 raise CatalystError, "Required argument \""+x+"\" not specified."
240 def spec_dump(myspec):
241 for x in myspec.keys():
242 print x+": "+repr(myspec[x])
249 raise CatalystError, "Could not touch "+myfile+"."