This is 2.0_rc27.
[catalyst.git] / catalyst
1 #!/usr/bin/python -OO
2 # Copyright 1999-2005 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header: /var/cvsroot/gentoo/src/catalyst/catalyst,v 1.135 2006/01/29 08:32:05 wolf31o2 Exp $
5
6 # Maintained in full by:
7 # Eric Edgar <rocket@gentoo.org>
8 # Chris Gianelloni <wolf31o2@gentoo.org>
9
10 import os,sys,imp,string,getopt
11 import pdb
12
13 __maintainer__="Chris Gianelloni <wolf31o2@gentoo.org>"
14 __version__="2.0_rc27"
15
16 conf_values={}
17
18 def usage():
19         print "Usage catalyst [options] [-C variable=value...] [ -s identifier]"
20         print " -a --clear-autoresume   clear autoresume flags"
21         print " -c --config             use specified configuration file"
22         print " -C --cli                catalyst commandline (MUST BE LAST OPTION)"
23         print " -d --debug              enable debugging"
24         print " -f --file               read specfile"
25         print " -F --fetchonly          fetch files only"
26         print " -h --help               print this help message"
27         print " -p --purge              clear tmp dirs,package cache and autoresume flags"
28         print " -s --snapshot           generate a Portage snapshot"
29         print " -V --version            display version information"
30         print " -v --verbose            verbose output"
31         print
32         print "Usage examples:"
33         print
34         print "Using the commandline option (-C, --cli) to build a Portage snapshot:"
35         print "catalyst -C target=snapshot version_stamp=my_date"
36         print
37         print "Using the snapshot option (-s, --snapshot) to build a Portage snapshot:"
38         print "catalyst -s 20051208"
39         print
40         print "Using the specfile option (-f, --file) to build a stage target:"
41         print "catalyst -f stage1-specfile.spec"
42
43 def version():
44         print "Gentoo Catalyst, version "+__version__
45         print "Copyright 2003-2005 The Gentoo Foundation"
46         print "Distributed under the GNU General Public License version 2\n"
47         
48
49 def parse_config(myconfig):
50         # search a couple of different areas for the main config file
51         myconf={}
52         config_file=""
53
54         confdefaults={ "storedir":"/var/tmp/catalyst",\
55                 "sharedir":"/usr/share/catalyst","distdir":"/usr/portage/distfiles",\
56                 "portdir":"/usr/portage","options":"",\
57                 "snapshot_cache":"/var/tmp/catalyst/snapshot_cache",\
58                 "hash_function":"crc32"}
59                 
60         # first, try the one passed (presumably from the cmdline)
61         if myconfig:
62                 if os.path.exists(myconfig):
63                         print "Using command line specified Catalyst configuration file, "+myconfig
64                         config_file=myconfig
65
66                 else:
67                         print "!!! catalyst: Could not use specified configuration file "+\
68                                 myconfig
69                         sys.exit(1)
70         
71         # next, try the default location
72         elif os.path.exists("/etc/catalyst/catalyst.conf"):
73                 print "Using default Catalyst configuration file, /etc/catalyst/catalyst.conf"
74                 config_file="/etc/catalyst/catalyst.conf"
75         
76         # can't find a config file (we are screwed), so bail out
77         else:
78                 print "!!! catalyst: Could not find a suitable configuration file"
79                 sys.exit(1)
80
81         # now, try and parse the config file "config_file"
82         try:
83                 execfile(config_file, myconf, myconf)
84         
85         except:
86                 print "!!! catalyst: Unable to parse configuration file, "+myconfig
87                 sys.exit(1)
88         
89         # now, load up the values into conf_values so that we can use them
90         for x in confdefaults.keys():
91                 if myconf.has_key(x):
92                         print "Setting",x,"to config file value \""+myconf[x]+"\""
93                         conf_values[x]=myconf[x]
94                 else:
95                         print "Setting",x,"to default value \""+confdefaults[x]+"\""
96                         conf_values[x]=confdefaults[x]
97
98         # parse out the rest of the options from the config file
99         if "ccache" in string.split(conf_values["options"]):
100                 print "Compiler cache support enabled."
101                 conf_values["CCACHE"]="1"
102
103         if "pkgcache" in string.split(conf_values["options"]):
104                 print "Package cache support enabled."
105                 conf_values["PKGCACHE"]="1"
106         
107         if "snapcache" in string.split(conf_values["options"]):
108                 print "Snapshot cache support enabled."
109                 conf_values["SNAPCACHE"]="1"
110         
111         if "seedcache" in string.split(conf_values["options"]):
112                 print "Seed cache support enabled."
113                 conf_values["SEEDCACHE"]="1"
114
115         if "kerncache" in string.split(conf_values["options"]):
116                 print "Kernel cache support enabled."
117                 conf_values["KERNCACHE"]="1"
118         
119         if "distcc" in string.split(conf_values["options"]):
120                 print "Distcc support enabled."
121                 conf_values["DISTCC"]="1"
122
123         if "autoresume" in string.split(conf_values["options"]):
124                 print "Autoresuming support enabled."
125                 conf_values["AUTORESUME"]="1"
126
127         if "purge" in string.split(conf_values["options"]):
128                 print "Purge support enabled."
129                 conf_values["PURGE"]="1"
130         
131         if "clear-autoresume" in string.split(conf_values["options"]):
132                 print "Cleaning autoresume flags support enabled."
133                 conf_values["CLEAR_AUTORESUME"]="1"
134         
135         if myconf.has_key("envscript"):
136                 print "Envscript support enabled."
137                 conf_values["ENVSCRIPT"]=myconf["envscript"]
138         
139         if myconf.has_key("digests"):
140                 conf_values["digests"]=myconf["digests"]
141
142 def import_modules():
143         # import catalyst's own modules (i.e. catalyst_support and the arch modules)
144         targetmap={}
145         
146         try:
147                 for x in required_build_targets:
148                         try:
149                                 fh=open(conf_values["sharedir"]+"/modules/"+x+".py")
150                                 module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE))
151                                 fh.close()
152                 
153                         except IOError:
154                                 raise CatalystError,"Can't find "+x+".py plugin in "+\
155                                         conf_values.settings["sharedir"]+"/modules/"
156
157                 for x in valid_build_targets:
158                         try:
159                                 fh=open(conf_values["sharedir"]+"/modules/"+x+".py")
160                                 module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE))
161                                 module.register(targetmap)
162                                 fh.close()
163                 
164                         except IOError:
165                                 raise CatalystError,"Can't find "+x+".py plugin in "+\
166                                         conf_values.settings["sharedir"]+"/modules/"
167
168         except ImportError:
169                 print "!!! catalyst: Python modules not found in "+\
170                         conf_values["sharedir"]+"/modules; exiting."
171                 sys.exit(1)
172
173         return targetmap
174
175 def do_spec(myspecfile):
176         try:
177                 addlargs=read_spec(myspecfile)
178         except:
179                 sys.exit(1)
180                 
181         return addlargs
182
183 def do_cli(cmdline):
184         try:
185                 return arg_parse(cmdline)
186         
187         except CatalystError:
188                 print "!!! catalyst: Could not parse commandline, exiting."
189                 sys.exit(1)
190         
191 def build_target(addlargs, targetmap):
192         try:
193                 if not targetmap.has_key(addlargs["target"]):
194                         raise CatalystError,"Target \""+addlargs["target"]+"\" not available."
195                 
196                 mytarget=targetmap[addlargs["target"]](conf_values, addlargs)
197         
198                 mytarget.run()
199
200         except:
201                 raise
202
203 if __name__ == "__main__":
204         targetmap={}
205         
206         version()
207         if os.getuid() != 0:
208                 # catalyst cannot be run as a normal user due to chroots, mounts, etc
209                 print "!!! catalyst: This script requires root privileges to operate"
210                 sys.exit(2)
211
212         # we need some options in order to work correctly
213         if len(sys.argv) < 2:
214                 usage()
215                 sys.exit(2)
216
217         # parse out the command line arguments
218         try:
219                 opts,args = getopt.getopt(sys.argv[1:], "apxhvdc:C:f:FVs:", ["purge","help", "version", "debug",\
220                         "clear_autoresume", "config=", "cli=", "file=", "fetch", "verbose","snapshot="])
221         
222         except getopt.GetoptError:
223                 usage()
224                 sys.exit(2)
225         
226         # defaults for commandline opts
227         debug=False
228         verbose=False
229         fetch=False
230         myconfig=""
231         myspecfile=""
232         mycmdline=[]
233         myopts=[]
234
235         # check preconditions
236         if len(opts) == 0:
237                 print "!!! catalyst: please specify one of either -f or -C\n"
238                 usage()
239                 sys.exit(2)
240         run=0   
241         for o, a in opts:
242                 if o in ("-h", "--help"):
243                         usage()
244                         sys.exit(1)
245                 
246                 if o in ("-V", "--version"):
247                         print "Catalyst version "+__version__
248                         sys.exit(1)
249
250                 if o in ("-d", "--debug"):
251                         if len(sys.argv) < 3:
252                                 print "!!! catalyst: please specify one of either -f or -C\n"
253                                 usage()
254                                 sys.exit(2)
255                         else:
256                                 conf_values["DEBUG"]="1"
257
258                 if o in ("-c", "--config"):
259                         if len(sys.argv) < 3:
260                                 print "!!! catalyst: please specify one of either -f or -C\n"
261                                 usage()
262                                 sys.exit(2)
263                         else:
264                                 myconfig=a
265
266                 if o in ("-C", "--cli"):
267                         run=1   
268                         x=sys.argv.index(o)+1
269                         while x < len(sys.argv):
270                                 mycmdline.append(sys.argv[x])
271                                 x=x+1
272                         
273                 if o in ("-f", "--file"):
274                         run=1   
275                         myspecfile=a
276
277                 if o in ("-F", "--fetchonly"):
278                         if len(sys.argv) < 3:
279                                 print "!!! catalyst: please specify one of either -f or -C\n"
280                                 usage()
281                                 sys.exit(2)
282                         else:
283                                 conf_values["FETCH"]="1"
284                         
285                 if o in ("-v", "--verbose"):
286                         if len(sys.argv) < 3:
287                                 print "!!! catalyst: please specify one of either -f or -C\n"
288                                 usage()
289                                 sys.exit(2)
290                         else:
291                                 conf_values["VERBOSE"]="1"
292
293                 if o in ("-s", "--snapshot"):
294                         if len(sys.argv) < 3:
295                                 print "!!! catalyst: missing snapshot identifier\n"
296                                 usage()
297                                 sys.exit(2)
298                         else:
299                                 run=1
300                                 mycmdline.append("target=snapshot")
301                                 mycmdline.append("version_stamp="+a)
302                 
303                 if o in ("-p", "--purge"):
304                         if len(sys.argv) < 3:
305                                 print "!!! catalyst: please specify one of either -f or -C\n"
306                                 usage()
307                                 sys.exit(2)
308                         else:
309                                 conf_values["PURGE"]="1"
310                 if o in ("-a", "--clear-autoresume"):
311                         if len(sys.argv) < 3:
312                                 print "!!! catalyst: please specify one of either -f or -C\n"
313                                 usage()
314                                 sys.exit(2)
315                         else:
316                                 conf_values["CLEAR_AUTORESUME"]="1"
317         if run != 1:
318                 print "!!! catalyst: please specify one of either -f or -C\n"
319                 usage()
320                 sys.exit(2)
321
322         # import configuration file and import our main module using those settings
323         parse_config(myconfig)
324         sys.path.append(conf_values["sharedir"]+"/modules")
325         from catalyst_support import *
326         
327         # Start checking that digests are valid now that the hash_map was imported from catalyst_support
328         if conf_values.has_key("digests"):
329                 for i in conf_values["digests"].split():
330                         if not hash_map.has_key(i):
331                                 print
332                                 print i+" is not a valid digest entry"
333                                 print "Valid digest entries:"
334                                 print hash_map.keys()
335                                 print
336                                 print "Catalyst aborting...."
337                                 sys.exit(2)
338                         if find_binary(hash_map[i][1]) == None:
339                                 print
340                                 print "digest="+i
341                                 print "\tThe "+hash_map[i][1]+\
342                                         " binary was not found. It needs to be in your system path"
343                                 print
344                                 print "Catalyst aborting...."
345                                 sys.exit(2)
346         if conf_values.has_key("hash_function"):
347                 if not hash_map.has_key(conf_values["hash_function"]):
348                         print
349                         print conf_values["hash_function"]+" is not a valid hash_function entry"
350                         print "Valid hash_function entries:"
351                         print hash_map.keys()
352                         print
353                         print "Catalyst aborting...."
354                         sys.exit(2)
355                 if find_binary(hash_map[conf_values["hash_function"]][1]) == None:
356                         print
357                         print "hash_function="+conf_values["hash_function"]
358                         print "\tThe "+hash_map[conf_values["hash_function"]][1]+\
359                                 " binary was not found. It needs to be in your system path"
360                         print
361                         print "Catalyst aborting...."
362                         sys.exit(2)
363
364         # import the rest of the catalyst modules
365         targetmap=import_modules()
366
367         addlargs={}
368         
369         if myspecfile:
370                 addlargs.update(do_spec(myspecfile))
371         
372         if mycmdline:
373                 addlargs.update(do_cli(mycmdline))
374         
375         if not addlargs.has_key("target"):
376                 raise CatalystError, "Required value \"target\" not specified."
377
378         # everything is setup, so the build is a go
379         try:
380                 build_target(addlargs, targetmap)
381                         
382         except CatalystError:
383                 print
384                 print "Catalyst aborting...."
385                 sys.exit(2)
386         except KeyboardInterrupt:
387                 print "\nCatalyst build aborted due to user interrupt ( Ctrl-C )"
388                 print
389                 print "Catalyst aborting...."
390                 sys.exit(2)
391         except LockInUse:
392                 print "Catalyst aborting...."
393                 sys.exit(2)
394         except:
395                 print "Catalyst aborting...."
396                 raise
397                 sys.exit(2)
398
399         #except CatalystError:
400         #       print
401         #       print "Catalyst aborting...."
402         #       sys.exit(2)
403         #except KeyError:
404         #       print "\nproblem with command line or spec file ( Key Error )"
405         #       print "Key: "+str(sys.exc_value)+" was not found"
406         #       print "Catalyst aborting...."
407         #       sys.exit(2)
408         #except UnboundLocalError:
409         #       print
410         #       print "UnboundLocalError: "+str(sys.exc_value)+" was not found"
411         #       raise
412         #       print
413         #       print "Catalyst aborting...."
414         #       sys.exit(2)