Condense code that checks for various things in 'options' to use a loop
[catalyst.git] / catalyst
1 #!/usr/bin/python -OO
2
3 # Maintained in full by:
4 # Andrew Gaffney <agaffney@gentoo.org>
5 # Chris Gianelloni <wolf31o2@gentoo.org>
6
7 import os, sys, getopt
8
9 # This assumes that our modules are in a sub-dir named "modules" in the
10 # directory that the main catalyst binary is in
11 __selfpath__ = os.path.abspath(os.path.dirname(__file__))
12 sys.path.append(__selfpath__ + "/modules")
13
14 import catalyst.config
15 import catalyst.util
16 import catalyst.target
17 from catalyst.support import *
18
19 __maintainer__="Chris Gianelloni <wolf31o2@gentoo.org>"
20 __version__="2.99"
21
22 conf_values={}
23
24 def usage():
25         print "Usage catalyst [options] [-C variable=value...] [ -s identifier]"
26         print " -a --clear-autoresume   clear autoresume flags"
27         print " -c --config     use specified configuration file"
28         print " -C --cli        catalyst commandline (MUST BE LAST OPTION)"
29         print " -d --debug      enable debugging"
30         print " -f --file       read specfile"
31         print " -F --fetchonly  fetch files only"
32         print " -h --help       print this help message"
33         print " -p --purge      clear tmp dirs,package cache and autoresume flags"
34         print " -P --purgeonly  clear tmp dirs,package cache and autoresume flags and exit"
35         print " -s --snapshot   generate a release snapshot"
36         print " -V --version    display version information"
37         print " -v --verbose    verbose output"
38         print
39         print "Usage examples:"
40         print
41         print "Using the commandline option (-C, --cli) to build a Portage snapshot:"
42         print "catalyst -C target=snapshot version_stamp=my_date"
43         print
44         print "Using the snapshot option (-s, --snapshot) to build a release snapshot:"
45         print "catalyst -s 20071121"
46         print
47         print "Using the specfile option (-f, --file) to build a stage target:"
48         print "catalyst -f stage1-specfile.spec"
49
50 def show_version():
51         print "Catalyst, version "+__version__
52         print "Copyright 2003-2008 Gentoo Foundation"
53         print "Copyright 2008 various authors"
54         print "Distributed under the GNU General Public License version 2.1\n"
55
56 def parse_config(myconfig):
57         # search a couple of different areas for the main config file
58         myconf={}
59         config_file=""
60
61         confdefaults={ "storedir":"/var/tmp/catalyst",\
62                 "sharedir":"/usr/share/catalyst","distdir":"/usr/portage/distfiles",\
63                 "portdir":"/usr/portage","options":"",\
64                 "snapshot_cache":"/var/tmp/catalyst/snapshot_cache",\
65                 "hash_function":"crc32"}
66
67         # first, try the one passed (presumably from the cmdline)
68         if myconfig:
69                 if os.path.exists(myconfig):
70                         print "Using command line specified Catalyst configuration file, "+myconfig
71                         config_file=myconfig
72
73                 else:
74                         print "!!! catalyst: Could not use specified configuration file "+\
75                                 myconfig
76                         sys.exit(1)
77
78         # next, try the default location
79         elif os.path.exists("/etc/catalyst/catalyst.conf"):
80                 print "Using default Catalyst configuration file, /etc/catalyst/catalyst.conf"
81                 config_file="/etc/catalyst/catalyst.conf"
82
83         # can't find a config file (we are screwed), so bail out
84         else:
85                 print "!!! catalyst: Could not find a suitable configuration file"
86                 sys.exit(1)
87
88         # now, try and parse the config file "config_file"
89         try:
90 #               execfile(config_file, myconf, myconf)
91                 myconfig = catalyst.config.ConfigParser(config_file)
92                 myconf.update(myconfig.get_values())
93
94         except:
95                 print "!!! catalyst: Unable to parse configuration file, "+myconfig
96                 sys.exit(1)
97
98         # now, load up the values into conf_values so that we can use them
99         for x in confdefaults.keys():
100                 if x in myconf:
101                         print "Setting",x,"to config file value \""+myconf[x]+"\""
102                         conf_values[x]=myconf[x]
103                 else:
104                         print "Setting",x,"to default value \""+confdefaults[x]+"\""
105                         conf_values[x]=confdefaults[x]
106
107         options = (
108                 ("autoresume", "AUTORESUME", "Autoresuming support enabled."),
109                 ("ccache", "CCACHE", "Compiler cache support enabled."),
110                 ("clear-autoresume", "CLEAR_AUTORESUME", "Cleaning autoresume flags support enabled"),
111 #               ("compress", "COMPRESS", "Compression enabled."),
112                 ("distcc", "DISTCC", "Distcc support enabled."),
113                 ("icecream", "ICECREAM", "Icecream compiler cluster support enabled."),
114                 ("kerncache", "KERNCACHE", "Kernel cache support enabled."),
115                 ("pkgcache", "PKGCACHE", "Package cache support enabled."),
116                 ("purge", "PURGE", "Purge support enabled."),
117                 ("seedcache", "SEEDCACHE", "Seed cache support enabled."),
118                 ("snapcache", "SNAPCACHE", "Snapshot cache support enabled."),
119                 ("metadata_overlay", "METADATA_OVERLAY", "Use of metadata_overlay module for portage enabled."),
120 #               ("tarball", "TARBALL", "Tarball creation enabled.")
121         )
122
123         split_options = conf_values["options"].split()
124
125         # parse out the rest of the options from the config file
126         for x in options:
127                 if x[0] in split_options:
128                         print x[2]
129                         conf_values[x[1]] = "1"
130
131         if "digests" in myconf:
132                 conf_values["digests"]=myconf["digests"]
133         if "contents" in myconf:
134                 conf_values["contents"]=myconf["contents"]
135
136         if "envscript" in myconf:
137                 print "Envscript support enabled."
138                 conf_values["ENVSCRIPT"]=myconf["envscript"]
139
140 def build_target(addlargs, targetmap):
141         try:
142                 if not addlargs["target"] in targetmap:
143                         raise CatalystError,"Target \""+addlargs["target"]+"\" not available."
144
145                 mytarget=targetmap[addlargs["target"]](conf_values, addlargs)
146
147                 mytarget.run()
148
149         except:
150                 catalyst.util.print_traceback()
151                 print "!!! catalyst: Error encountered during run of target " + addlargs["target"]
152 #               sys.exit(1)
153                 raise
154
155 def verify_digest_and_hash_functions():
156         # Start checking that digests are valid now that the hash_map was imported from catalyst_support
157         if "digests" in conf_values:
158                 for i in conf_values["digests"].split():
159                         if not i in hash_map:
160                                 print
161                                 print i+" is not a valid digest entry"
162                                 print "Valid digest entries:"
163                                 print hash_map.keys()
164                                 print
165                                 print "Catalyst aborting...."
166                                 sys.exit(2)
167                         if find_binary(hash_map[i][1]) == None:
168                                 print
169                                 print "digest="+i
170                                 print "\tThe "+hash_map[i][1]+\
171                                         " binary was not found. It needs to be in your system path"
172                                 print
173                                 print "Catalyst aborting...."
174                                 sys.exit(2)
175
176         if "hash_function" in conf_values:
177                 if not conf_values["hash_function"] in hash_map:
178                         print
179                         print conf_values["hash_function"]+" is not a valid hash_function entry"
180                         print "Valid hash_function entries:"
181                         print hash_map.keys()
182                         print
183                         print "Catalyst aborting...."
184                         sys.exit(2)
185                 if find_binary(hash_map[conf_values["hash_function"]][1]) == None:
186                         print
187                         print "hash_function="+conf_values["hash_function"]
188                         print "\tThe "+hash_map[conf_values["hash_function"]][1]+\
189                                 " binary was not found. It needs to be in your system path"
190                         print
191                         print "Catalyst aborting...."
192                         sys.exit(2)
193
194 if __name__ == "__main__":
195
196         show_version()
197
198         if os.getuid() != 0:
199                 # catalyst cannot be run as a normal user due to chroots, mounts, etc
200                 print "!!! catalyst: This script requires root privileges to operate"
201                 sys.exit(2)
202
203         # parse out the command line arguments
204         try:
205                 opts,args = getopt.getopt(sys.argv[1:], "apPhvdc:C:f:FVs:", ["purge", "purgeonly", "help", "version", "debug",\
206                         "clear-autoresume", "config=", "cli=", "file=", "fetch", "verbose","snapshot="])
207
208         except getopt.GetoptError:
209                 usage()
210                 sys.exit(2)
211
212         # defaults for commandline opts
213         debug=False
214         verbose=False
215         fetch=False
216         myconfig=""
217         myspecfile=""
218         mycmdline=[]
219         myopts=[]
220
221         # check preconditions
222         if len(opts) == 0:
223                 print "!!! catalyst: please specify one of either -f or -C\n"
224                 usage()
225                 sys.exit(2)
226
227         run = False
228         for o, a in opts:
229                 if o in ("-h", "--help"):
230                         usage()
231                         sys.exit(1)
232
233                 if o in ("-V", "--version"):
234                         print "Catalyst version "+__version__
235                         sys.exit(1)
236
237                 if o in ("-d", "--debug"):
238                         conf_values["DEBUG"]="1"
239                         conf_values["VERBOSE"]="1"
240
241                 if o in ("-c", "--config"):
242                         myconfig=a
243
244                 if o in ("-C", "--cli"):
245                         run = True
246                         x=sys.argv.index(o)+1
247                         while x < len(sys.argv):
248                                 mycmdline.append(sys.argv[x])
249                                 x=x+1
250
251                 if o in ("-f", "--file"):
252                         run = True
253                         myspecfile=a
254
255                 if o in ("-F", "--fetchonly"):
256                         conf_values["FETCH"]="1"
257
258                 if o in ("-v", "--verbose"):
259                         conf_values["VERBOSE"]="1"
260
261                 if o in ("-s", "--snapshot"):
262                         if len(sys.argv) < 3:
263                                 print "!!! catalyst: missing snapshot identifier\n"
264                                 usage()
265                                 sys.exit(2)
266                         else:
267                                 run = True
268                                 mycmdline.append("target=snapshot")
269                                 mycmdline.append("version_stamp="+a)
270
271                 if o in ("-p", "--purge"):
272                         conf_values["PURGE"] = "1"
273
274                 if o in ("-P", "--purgeonly"):
275                         conf_values["PURGEONLY"] = "1"
276
277                 if o in ("-a", "--clear-autoresume"):
278                         conf_values["CLEAR_AUTORESUME"] = "1"
279
280         if not run:
281                 print "!!! catalyst: please specify one of either -f or -C\n"
282                 usage()
283                 sys.exit(2)
284
285         parse_config(myconfig)
286
287         verify_digest_and_hash_functions()
288
289         targetmap = catalyst.target.build_target_map()
290
291         addlargs={}
292
293         if myspecfile:
294                 spec = catalyst.config.SpecParser(myspecfile)
295                 addlargs.update(spec.get_values())
296
297         if mycmdline:
298                 try:
299                         cmdline = catalyst.config.ConfigParser()
300                         cmdline.parse_lines(mycmdline)
301                         addlargs.update(cmdline.get_values())
302                 except CatalystError:
303                         print "!!! catalyst: Could not parse commandline, exiting."
304                         sys.exit(1)
305
306         if not "target" in addlargs:
307                 raise CatalystError, "Required value \"target\" not specified."
308
309         # everything is setup, so the build is a go
310         try:
311                 build_target(addlargs, targetmap)
312
313         except CatalystError:
314                 print
315                 print "Catalyst aborting...."
316                 sys.exit(2)
317
318         except KeyboardInterrupt:
319                 print "\nCatalyst build aborted due to user interrupt ( Ctrl-C )"
320                 print
321                 print "Catalyst aborting...."
322                 sys.exit(2)
323
324         except LockInUse:
325                 print "Catalyst aborting...."
326                 sys.exit(2)
327
328         except:
329                 print "Catalyst aborting...."
330                 raise
331                 sys.exit(2)
332
333         #except KeyError:
334         #       print "\nproblem with command line or spec file ( Key Error )"
335         #       print "Key: "+str(sys.exc_value)+" was not found"
336         #       print "Catalyst aborting...."
337         #       sys.exit(2)
338         #except UnboundLocalError:
339         #       print
340         #       print "UnboundLocalError: "+str(sys.exc_value)+" was not found"
341         #       raise
342         #       print
343         #       print "Catalyst aborting...."
344         #       sys.exit(2)