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