1e0078d86dcc923dbe951c44e94d562da748971a
[catalyst.git] / modules / generic_stage_target.py
1
2 """
3 This class does all of the chroot setup, copying of files, etc. It is
4 the driver class for pretty much everything that Catalyst does.
5 """
6
7 import os,string,imp,types,shutil
8 from catalyst_support import *
9 from generic_target import *
10 from stat import *
11 import catalyst_lock
12 class generic_stage_target(generic_target):
13
14         def __init__(self,myspec,addlargs):
15                 self.required_values.extend(["version_stamp","target","subarch",\
16                         "rel_type","profile","snapshot","source_subpath"])
17
18                 self.valid_values.extend(["version_stamp","target","subarch",\
19                         "rel_type","profile","snapshot","source_subpath","portage_confdir",\
20                         "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
21                         "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
22
23                 self.set_valid_build_kernel_vars(addlargs)
24                 generic_target.__init__(self,myspec,addlargs)
25
26                 """
27                 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
28                 work better with vapier's CBUILD stuff. I've removed the "monolithic"
29                 machinemap from this file and split up its contents amongst the
30                 various arch/foo.py files.
31
32                 When register() is called on each module in the arch/ dir, it now
33                 returns a tuple instead of acting on the subarchmap dict that is
34                 passed to it. The tuple contains the values that were previously
35                 added to subarchmap as well as a new list of CHOSTs that go along
36                 with that arch. This allows us to build machinemap on the fly based
37                 on the keys in subarchmap and the values of the 2nd list returned
38                 (tmpmachinemap).
39
40                 Also, after talking with vapier. I have a slightly better idea of what
41                 certain variables are used for and what they should be set to. Neither
42                 'buildarch' or 'hostarch' are used directly, so their value doesn't
43                 really matter. They are just compared to determine if we are
44                 cross-compiling. Because of this, they are just set to the name of the
45                 module in arch/ that the subarch is part of to make things simpler.
46                 The entire build process is still based off of 'subarch' like it was
47                 previously. -agaffney
48                 """
49
50                 self.archmap = {}
51                 self.subarchmap = {}
52                 machinemap = {}
53                 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
54                         "/arch/") if x.endswith(".py")]:
55                         try:
56                                 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
57                                 """
58                                 This next line loads the plugin as a module and assigns it to
59                                 archmap[x]
60                                 """
61                                 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
62                                         ".py",(".py","r",imp.PY_SOURCE))
63                                 """
64                                 This next line registers all the subarches supported in the
65                                 plugin
66                                 """
67                                 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
68                                 self.subarchmap.update(tmpsubarchmap)
69                                 for machine in tmpmachinemap:
70                                         machinemap[machine] = x
71                                 for subarch in tmpsubarchmap:
72                                         machinemap[subarch] = x
73                                 fh.close()
74                         except IOError:
75                                 """
76                                 This message should probably change a bit, since everything in
77                                 the dir should load just fine. If it doesn't, it's probably a
78                                 syntax error in the module
79                                 """
80                                 msg("Can't find/load "+x+".py plugin in "+\
81                                         self.settings["sharedir"]+"/arch/")
82
83                 if self.settings.has_key("chost"):
84                         hostmachine = self.settings["chost"].split("-")[0]
85                         if not machinemap.has_key(hostmachine):
86                                 raise CatalystError, "Unknown host machine type "+hostmachine
87                         self.settings["hostarch"]=machinemap[hostmachine]
88                 else:
89                         hostmachine = self.settings["subarch"]
90                         if machinemap.has_key(hostmachine):
91                                 hostmachine = machinemap[hostmachine]
92                         self.settings["hostarch"]=hostmachine
93                 if self.settings.has_key("cbuild"):
94                         buildmachine = self.settings["cbuild"].split("-")[0]
95                 else:
96                         buildmachine = os.uname()[4]
97                 if not machinemap.has_key(buildmachine):
98                         raise CatalystError, "Unknown build machine type "+buildmachine
99                 self.settings["buildarch"]=machinemap[buildmachine]
100                 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
101                         self.settings["buildarch"])
102
103                 """ Call arch constructor, pass our settings """
104                 try:
105                         self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
106                 except KeyError:
107                         print "Invalid subarch: "+self.settings["subarch"]
108                         print "Choose one of the following:",
109                         for x in self.subarchmap:
110                                 print x,
111                         print
112                         sys.exit(2)
113
114                 print "Using target:",self.settings["target"]
115                 """ Print a nice informational message """
116                 if self.settings["buildarch"]==self.settings["hostarch"]:
117                         print "Building natively for",self.settings["hostarch"]
118                 elif self.settings["crosscompile"]:
119                         print "Cross-compiling on",self.settings["buildarch"],\
120                                 "for different machine type",self.settings["hostarch"]
121                 else:
122                         print "Building on",self.settings["buildarch"],\
123                                 "for alternate personality type",self.settings["hostarch"]
124
125                 """ This must be set first as other set_ options depend on this """
126                 self.set_spec_prefix()
127
128                 """ Define all of our core variables """
129                 self.set_target_profile()
130                 self.set_target_subpath()
131                 self.set_source_subpath()
132
133                 """ Set paths """
134                 self.set_snapshot_path()
135                 self.set_root_path()
136                 self.set_source_path()
137                 self.set_snapcache_path()
138                 self.set_chroot_path()
139                 self.set_autoresume_path()
140                 self.set_dest_path()
141                 self.set_stage_path()
142                 self.set_target_path()
143
144                 self.set_controller_file()
145                 self.set_action_sequence()
146                 self.set_use()
147                 self.set_cleanables()
148                 self.set_iso_volume_id()
149                 self.set_build_kernel_vars()
150                 self.set_fsscript()
151                 # TODO: Remove archscript/runscript from next major version
152                 self.set_archscript()
153                 self.set_runscript()
154                 self.set_install_mask()
155                 self.set_rcadd()
156                 self.set_rcdel()
157                 self.set_cdtar()
158                 self.set_fstype()
159                 self.set_fsops()
160                 self.set_iso()
161                 self.set_packages()
162                 self.set_rm()
163                 self.set_linuxrc()
164                 self.set_overlay()
165                 self.set_portage_overlay()
166                 self.set_root_overlay()
167
168                 """
169                 This next line checks to make sure that the specified variables exist
170                 on disk.
171                 """
172                 #pdb.set_trace()
173                 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
174                         expand=0)
175                 """ If we are using portage_confdir, check that as well. """
176                 if self.settings.has_key("portage_confdir"):
177                         file_locate(self.settings,["portage_confdir"],expand=0)
178
179                 """ Setup our mount points """
180                 if self.settings.has_key("SNAPCACHE"):
181                         self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
182                         self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
183                                 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
184                                 "/usr/portage/distfiles":self.settings["distdir"]}
185                 else:
186                         self.mounts=["/proc","/dev","/usr/portage/distfiles"]
187                         self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
188                                 "/usr/portage/distfiles":self.settings["distdir"]}
189                 if os.uname()[0] == "Linux":
190                         self.mounts.append("/dev/pts")
191
192                 self.set_mounts()
193
194                 """
195                 Configure any user specified options (either in catalyst.conf or on
196                 the command line).
197                 """
198                 if self.settings.has_key("PKGCACHE"):
199                         self.set_pkgcache_path()
200                         print "Location of the package cache is "+\
201                                 self.settings["pkgcache_path"]
202                         self.mounts.append("/usr/portage/packages")
203                         self.mountmap["/usr/portage/packages"]=\
204                                 self.settings["pkgcache_path"]
205
206                 if self.settings.has_key("KERNCACHE"):
207                         self.set_kerncache_path()
208                         print "Location of the kerncache is "+\
209                                 self.settings["kerncache_path"]
210                         self.mounts.append("/tmp/kerncache")
211                         self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
212
213                 if self.settings.has_key("CCACHE"):
214                         if os.environ.has_key("CCACHE_DIR"):
215                                 ccdir=os.environ["CCACHE_DIR"]
216                                 del os.environ["CCACHE_DIR"]
217                         else:
218                                 ccdir="/root/.ccache"
219                         if not os.path.isdir(ccdir):
220                                 raise CatalystError,\
221                                         "Compiler cache support can't be enabled (can't find "+\
222                                         ccdir+")"
223                         self.mounts.append("/var/tmp/ccache")
224                         self.mountmap["/var/tmp/ccache"]=ccdir
225                         """ for the chroot: """
226                         self.env["CCACHE_DIR"]="/var/tmp/ccache"
227
228                 if self.settings.has_key("ICECREAM"):
229                         self.mounts.append("/var/cache/icecream")
230                         self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
231                         self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
232
233         def override_cbuild(self):
234                 if self.makeconf.has_key("CBUILD"):
235                         self.settings["CBUILD"]=self.makeconf["CBUILD"]
236
237         def override_chost(self):
238                 if self.makeconf.has_key("CHOST"):
239                         self.settings["CHOST"]=self.makeconf["CHOST"]
240
241         def override_cflags(self):
242                 if self.makeconf.has_key("CFLAGS"):
243                         self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
244
245         def override_cxxflags(self):
246                 if self.makeconf.has_key("CXXFLAGS"):
247                         self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
248
249         def override_ldflags(self):
250                 if self.makeconf.has_key("LDFLAGS"):
251                         self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
252
253         def set_install_mask(self):
254                 if self.settings.has_key("install_mask"):
255                         if type(self.settings["install_mask"])!=types.StringType:
256                                 self.settings["install_mask"]=\
257                                         string.join(self.settings["install_mask"])
258
259         def set_spec_prefix(self):
260                 self.settings["spec_prefix"]=self.settings["target"]
261
262         def set_target_profile(self):
263                 self.settings["target_profile"]=self.settings["profile"]
264
265         def set_target_subpath(self):
266                 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
267                                 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
268                                 self.settings["version_stamp"]
269
270         def set_source_subpath(self):
271                 if type(self.settings["source_subpath"])!=types.StringType:
272                         raise CatalystError,\
273                                 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
274
275         def set_pkgcache_path(self):
276                 if self.settings.has_key("pkgcache_path"):
277                         if type(self.settings["pkgcache_path"])!=types.StringType:
278                                 self.settings["pkgcache_path"]=\
279                                         normpath(string.join(self.settings["pkgcache_path"]))
280                 else:
281                         self.settings["pkgcache_path"]=\
282                                 normpath(self.settings["storedir"]+"/packages/"+\
283                                 self.settings["target_subpath"]+"/")
284
285         def set_kerncache_path(self):
286                 if self.settings.has_key("kerncache_path"):
287                         if type(self.settings["kerncache_path"])!=types.StringType:
288                                 self.settings["kerncache_path"]=\
289                                         normpath(string.join(self.settings["kerncache_path"]))
290                 else:
291                         self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
292                                 "/kerncache/"+self.settings["target_subpath"]+"/")
293
294         def set_target_path(self):
295                 self.settings["target_path"]=normpath(self.settings["storedir"]+\
296                         "/builds/"+self.settings["target_subpath"]+".tar.bz2")
297                 if self.settings.has_key("AUTORESUME")\
298                         and os.path.exists(self.settings["autoresume_path"]+\
299                                 "setup_target_path"):
300                         print \
301                                 "Resume point detected, skipping target path setup operation..."
302                 else:
303                         """ First clean up any existing target stuff """
304                         if os.path.isfile(self.settings["target_path"]):
305                                 cmd("rm -f "+self.settings["target_path"],\
306                                         "Could not remove existing file: "\
307                                         +self.settings["target_path"],env=self.env)
308                                 touch(self.settings["autoresume_path"]+"setup_target_path")
309
310                         if not os.path.exists(self.settings["storedir"]+"/builds/"):
311                                 os.makedirs(self.settings["storedir"]+"/builds/")
312
313         def set_archscript(self):
314                 if self.settings.has_key(self.settings["spec_prefix"]+"/archscript"):
315                         # TODO: remove this warning/code with the next major version
316                         print "\nWarning!!!  "
317                         print "\t"+self.settings["spec_prefix"]+"/archscript"+\
318                                 " is deprecated and no longer used.\n"
319
320         def set_runscript(self):
321                 if self.settings.has_key(self.settings["spec_prefix"]+"/runscript"):
322                         # TODO: remove this warning/code with the next major version
323                         print "\nWarning!!!  "
324                         print "\t"+self.settings["spec_prefix"]+"/runscript"+\
325                                 " is deprecated and no longer used.\n"
326
327         def set_fsscript(self):
328                 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
329                         self.settings["fsscript"]=\
330                                 self.settings[self.settings["spec_prefix"]+"/fsscript"]
331                         del self.settings[self.settings["spec_prefix"]+"/fsscript"]
332
333         def set_rcadd(self):
334                 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
335                         self.settings["rcadd"]=\
336                                 self.settings[self.settings["spec_prefix"]+"/rcadd"]
337                         del self.settings[self.settings["spec_prefix"]+"/rcadd"]
338
339         def set_rcdel(self):
340                 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
341                         self.settings["rcdel"]=\
342                                 self.settings[self.settings["spec_prefix"]+"/rcdel"]
343                         del self.settings[self.settings["spec_prefix"]+"/rcdel"]
344
345         def set_cdtar(self):
346                 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
347                         self.settings["cdtar"]=\
348                                 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
349                         del self.settings[self.settings["spec_prefix"]+"/cdtar"]
350
351         def set_iso(self):
352                 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
353                         self.settings["iso"]=\
354                                 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
355                         del self.settings[self.settings["spec_prefix"]+"/iso"]
356
357         def set_fstype(self):
358                 if self.settings.has_key(self.settings["spec_prefix"]+"/cdfstype"):
359                         # TODO: remove this warning/code with the next major version
360                         print "\nWarning!!!  "
361                         print self.settings["spec_prefix"]+"/cdfstype"+\
362                                 " is deprecated and will be removed."
363                         print "\tUse "+self.settings["spec_prefix"]+"/fstype"+" instead."
364                         print "\tConverting to "+self.settings["spec_prefix"]+"/fstype"+\
365                                 " internally."
366                         print "\tContinuing ....\n"
367                         self.settings["fstype"]=\
368                                 self.settings[self.settings["spec_prefix"]+"/cdfstype"]
369                         del self.settings[self.settings["spec_prefix"]+"/cdfstype"]
370
371                 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
372                         self.settings["fstype"]=\
373                                 self.settings[self.settings["spec_prefix"]+"/fstype"]
374                         del self.settings[self.settings["spec_prefix"]+"/fstype"]
375
376                 if not self.settings.has_key("fstype"):
377                         self.settings["fstype"]="normal"
378                         for x in self.valid_values:
379                                 if x ==  self.settings["spec_prefix"]+"/fstype"\
380                                         or x == self.settings["spec_prefix"]+"/cdfstype":
381                                         print "\n"+self.settings["spec_prefix"]+\
382                                                 "/fstype is being set to the default of \"normal\"\n"
383
384         def set_fsops(self):
385                 if self.settings.has_key("fstype"):
386                         self.valid_values.append("fsops")
387                         if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
388                                 self.settings["fsops"]=\
389                                         self.settings[self.settings["spec_prefix"]+"/fsops"]
390                                 del self.settings[self.settings["spec_prefix"]+"/fsops"]
391
392         def set_source_path(self):
393                 if self.settings.has_key("SEEDCACHE")\
394                         and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
395                                 self.settings["source_subpath"]+"/")):
396                         self.settings["source_path"]=normpath(self.settings["storedir"]+\
397                                 "/tmp/"+self.settings["source_subpath"]+"/")
398                 else:
399                         self.settings["source_path"]=normpath(self.settings["storedir"]+\
400                                 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
401                         if os.path.isfile(self.settings["source_path"]):
402                                 # XXX: Is this even necessary if the previous check passes?
403                                 if os.path.exists(self.settings["source_path"]):
404                                         self.settings["source_path_hash"]=\
405                                                 generate_hash(self.settings["source_path"],\
406                                                 hash_function=self.settings["hash_function"],\
407                                                 verbose=False)
408                 print "Source path set to "+self.settings["source_path"]
409                 if os.path.isdir(self.settings["source_path"]):
410                         print "\tIf this is not desired, remove this directory or turn off"
411                         print "\tseedcache in the options of catalyst.conf the source path"
412                         print "\twill then be "+\
413                                 normpath(self.settings["storedir"]+"/builds/"+\
414                                 self.settings["source_subpath"]+".tar.bz2\n")
415
416         def set_dest_path(self):
417                 if self.settings.has_key("root_path"):
418                         self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
419                                 self.settings["root_path"])
420                 else:
421                         self.settings["destpath"]=normpath(self.settings["chroot_path"])
422
423         def set_cleanables(self):
424                 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
425                         "/root/*","/usr/portage"]
426
427         def set_snapshot_path(self):
428                 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
429                         "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
430
431                 if os.path.exists(self.settings["snapshot_path"]):
432                         self.settings["snapshot_path_hash"]=\
433                                 generate_hash(self.settings["snapshot_path"],\
434                                 hash_function=self.settings["hash_function"],verbose=False)
435
436         def set_snapcache_path(self):
437                 if self.settings.has_key("SNAPCACHE"):
438                         self.settings["snapshot_cache_path"]=\
439                                 normpath(self.settings["snapshot_cache"]+"/"+\
440                                 self.settings["snapshot"]+"/")
441                         self.snapcache_lock=\
442                                 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
443                         print "Caching snapshot to "+self.settings["snapshot_cache_path"]
444
445         def set_chroot_path(self):
446                 """
447                 NOTE: the trailing slash is very important!
448                 Things *will* break without it!
449                 """
450                 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
451                         "/tmp/"+self.settings["target_subpath"]+"/")
452                 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
453
454         def set_autoresume_path(self):
455                 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
456                         "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
457                         self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
458                         self.settings["version_stamp"]+"/")
459                 if self.settings.has_key("AUTORESUME"):
460                         print "The autoresume path is " + self.settings["autoresume_path"]
461                 if not os.path.exists(self.settings["autoresume_path"]):
462                         os.makedirs(self.settings["autoresume_path"],0755)
463
464         def set_controller_file(self):
465                 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
466                         "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
467                         "-controller.sh")
468
469         def set_iso_volume_id(self):
470                 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
471                         self.settings["iso_volume_id"]=\
472                                 self.settings[self.settings["spec_prefix"]+"/volid"]
473                         if len(self.settings["iso_volume_id"])>32:
474                                 raise CatalystError,\
475                                         "ISO volume ID must not exceed 32 characters."
476                 else:
477                         self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"] 
478
479         def set_action_sequence(self):
480                 """ Default action sequence for run method """
481                 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
482                                 "config_profile_link","setup_confdir","portage_overlay",\
483                                 "base_dirs","bind","chroot_setup","setup_environment",\
484                                 "run_local","preclean","unbind","clean"]
485 #               if self.settings.has_key("TARBALL") or \
486 #                       not self.settings.has_key("FETCH"):
487                 if not self.settings.has_key("FETCH"):
488                         self.settings["action_sequence"].append("capture")
489                 self.settings["action_sequence"].append("clear_autoresume")
490
491         def set_use(self):
492                 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
493                         self.settings["use"]=\
494                                 self.settings[self.settings["spec_prefix"]+"/use"]
495                         del self.settings[self.settings["spec_prefix"]+"/use"]
496                 if self.settings.has_key("use"):
497                         if type(self.settings["use"])==types.StringType:
498                                 self.settings["use"]=self.settings["use"].split()
499                                 self.settings["use"].append("bindist")
500
501         def set_stage_path(self):
502                 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
503
504         def set_mounts(self):
505                 pass
506
507         def set_packages(self):
508                 pass
509
510         def set_rm(self):
511                 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
512                         if type(self.settings[self.settings["spec_prefix"]+\
513                                 "/rm"])==types.StringType:
514                                 self.settings[self.settings["spec_prefix"]+"/rm"]=\
515                                         self.settings[self.settings["spec_prefix"]+"/rm"].split()
516
517         def set_linuxrc(self):
518                 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
519                         if type(self.settings[self.settings["spec_prefix"]+\
520                                 "/linuxrc"])==types.StringType:
521                                 self.settings["linuxrc"]=\
522                                         self.settings[self.settings["spec_prefix"]+"/linuxrc"]
523                                 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
524
525         def set_portage_overlay(self):
526                 if self.settings.has_key("portage_overlay"):
527                         if type(self.settings["portage_overlay"])==types.StringType:
528                                 self.settings["portage_overlay"]=\
529                                         self.settings["portage_overlay"].split()
530                         print "portage_overlay directories are set to: \""+\
531                                 string.join(self.settings["portage_overlay"])+"\""
532
533         def set_overlay(self):
534                 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
535                         if type(self.settings[self.settings["spec_prefix"]+\
536                                 "/overlay"])==types.StringType:
537                                 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
538                                         self.settings[self.settings["spec_prefix"]+\
539                                         "/overlay"].split()
540
541         def set_root_overlay(self):
542                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
543                         if type(self.settings[self.settings["spec_prefix"]+\
544                                 "/root_overlay"])==types.StringType:
545                                 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
546                                         self.settings[self.settings["spec_prefix"]+\
547                                         "/root_overlay"].split()
548
549         def set_root_path(self):
550                 """ ROOT= variable for emerges """
551                 self.settings["root_path"]="/"
552
553         def set_valid_build_kernel_vars(self,addlargs):
554                 if addlargs.has_key("boot/kernel"):
555                         if type(addlargs["boot/kernel"])==types.StringType:
556                                 loopy=[addlargs["boot/kernel"]]
557                         else:
558                                 loopy=addlargs["boot/kernel"]
559
560                         for x in loopy:
561                                 self.valid_values.append("boot/kernel/"+x+"/aliases")
562                                 self.valid_values.append("boot/kernel/"+x+"/config")
563                                 self.valid_values.append("boot/kernel/"+x+"/console")
564                                 self.valid_values.append("boot/kernel/"+x+"/extraversion")
565                                 self.valid_values.append("boot/kernel/"+x+"/gk_action")
566                                 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
567                                 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
568                                 self.valid_values.append("boot/kernel/"+x+"/machine_type")
569                                 self.valid_values.append("boot/kernel/"+x+"/sources")
570                                 self.valid_values.append("boot/kernel/"+x+"/softlevel")
571                                 self.valid_values.append("boot/kernel/"+x+"/use")
572                                 self.valid_values.append("boot/kernel/"+x+"/packages")
573                                 if addlargs.has_key("boot/kernel/"+x+"/packages"):
574                                         if type(addlargs["boot/kernel/"+x+\
575                                                 "/packages"])==types.StringType:
576                                                 addlargs["boot/kernel/"+x+"/packages"]=\
577                                                         [addlargs["boot/kernel/"+x+"/packages"]]
578                                 # TODO: remove this warning/code with the next major version
579                                 self.valid_values.append("boot/kernel/"+x+"/postconf")
580                                 if addlargs.has_key("boot/kernel/"+x+"/postconf"):
581                                         print "boot/kernel/"+x+"/postconf is deprecated"
582                                         print "\tInternally moving these ebuilds to boot/kernel/"+\
583                                                 x+"/packages"
584                                         print "\tPlease move them to boot/kernel/"+x+\
585                                                 "/packages in your specfile"
586                                         if type(addlargs["boot/kernel/"+x+\
587                                                 "/postconf"])==types.StringType:
588                                                 loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
589                                         else:
590                                                 loop2=addlargs["boot/kernel/"+x+"/postconf"]
591                                 
592                                         for y in loop2:
593                                                 if not addlargs.has_key("boot/kernel/"+x+"/packages"):
594                                                         addlargs["boot/kernel/"+x+"/packages"]=[y]
595                                                 else:
596                                                         addlargs["boot/kernel/"+x+"/packages"].append(y)
597
598         def set_build_kernel_vars(self):
599                 if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
600                         # TODO: remove this warning/code with the next major version
601                         print self.settings["spec_prefix"]+\
602                                 "/devmanager is deprecated and will be removed."
603                         self.settings["devmanager"]=\
604                                 self.settings[self.settings["spec_prefix"]+"/devmanager"]
605                         del self.settings[self.settings["spec_prefix"]+"/devmanager"]
606
607                 if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
608                         # TODO: remove this warning/code with the next major version
609                         print self.settings["spec_prefix"]+\
610                                 "/splashtype is deprecated and will be removed."
611                         self.settings["splashtype"]=\
612                                 self.settings[self.settings["spec_prefix"]+"/splashtype"]
613                         del self.settings[self.settings["spec_prefix"]+"/splashtype"]
614
615                 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
616                         self.settings["gk_mainargs"]=\
617                                 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
618                         del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
619
620         def kill_chroot_pids(self):
621                 print "Checking for processes running in chroot and killing them."
622
623                 """
624                 Force environment variables to be exported so script can see them
625                 """
626                 self.setup_environment()
627
628                 if os.path.exists(self.settings["sharedir"]+\
629                         "/targets/support/kill-chroot-pids.sh"):
630                         cmd("/bin/bash "+self.settings["sharedir"]+\
631                                 "/targets/support/kill-chroot-pids.sh",\
632                                 "kill-chroot-pids script failed.",env=self.env)
633
634         def mount_safety_check(self):
635                 mypath=self.settings["chroot_path"]
636
637                 """
638                 Check and verify that none of our paths in mypath are mounted. We don't
639                 want to clean up with things still mounted, and this allows us to check. 
640                 Returns 1 on ok, 0 on "something is still mounted" case.
641                 """
642
643                 if not os.path.exists(mypath):
644                         return
645
646                 for x in self.mounts:
647                         if not os.path.exists(mypath+x):
648                                 continue
649
650                         if ismount(mypath+x):
651                                 """ Something is still mounted "" """
652                                 try:
653                                         print x+" is still mounted; performing auto-bind-umount...",
654                                         """ Try to umount stuff ourselves """
655                                         self.unbind()
656                                         if ismount(mypath+x):
657                                                 raise CatalystError, "Auto-unbind failed for "+x
658                                         else:
659                                                 print "Auto-unbind successful..."
660                                 except CatalystError:
661                                         raise CatalystError, "Unable to auto-unbind "+x
662
663         def unpack(self):
664                 unpack=True
665
666                 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
667                         "unpack")
668
669                 if self.settings.has_key("SEEDCACHE"):
670                         if os.path.isdir(self.settings["source_path"]): 
671                                 """ SEEDCACHE Is a directory, use rsync """
672                                 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
673                                         " "+self.settings["chroot_path"]
674                                 display_msg="\nStarting rsync from "+\
675                                         self.settings["source_path"]+"\nto "+\
676                                         self.settings["chroot_path"]+\
677                                         " (This may take some time) ...\n"
678                                 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
679                                         self.settings["chroot_path"]+" failed."
680                         else:
681                                 """ SEEDCACHE is a not a directory, try untar'ing """
682                                 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
683                                 display_msg="\nStarting tar extract from "+\
684                                         self.settings["source_path"]+"\nto "+\
685                                         self.settings["chroot_path"]+\
686                                                 " (This may take some time) ...\n"
687                                 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
688                                         self.settings["chroot_path"]
689                                 error_msg="Tarball extraction of "+\
690                                         self.settings["source_path"]+" to "+\
691                                         self.settings["chroot_path"]+" failed."
692                 else:
693                         """ No SEEDCACHE, use tar """
694                         display_msg="\nStarting tar extract from "+\
695                                 self.settings["source_path"]+"\nto "+\
696                                 self.settings["chroot_path"]+\
697                                 " (This may take some time) ...\n"
698                         unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
699                                 self.settings["chroot_path"]
700                         error_msg="Tarball extraction of "+self.settings["source_path"]+\
701                                 " to "+self.settings["chroot_path"]+" failed."
702
703                 if self.settings.has_key("AUTORESUME"):
704                         if os.path.isdir(self.settings["source_path"]) \
705                                 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
706                                 """ Autoresume is valid, SEEDCACHE is valid """
707                                 unpack=False
708                                 invalid_snapshot=False
709
710                         elif os.path.isfile(self.settings["source_path"]) \
711                                 and self.settings["source_path_hash"]==clst_unpack_hash:
712                                 """ Autoresume is valid, tarball is valid """
713                                 unpack=False
714                                 invalid_snapshot=True
715                         
716                         elif os.path.isdir(self.settings["source_path"]) \
717                                 and not os.path.exists(self.settings["autoresume_path"]+\
718                                 "unpack"):
719                                 """ Autoresume is invalid, SEEDCACHE """
720                                 unpack=True
721                                 invalid_snapshot=False
722
723                         elif os.path.isfile(self.settings["source_path"]) \
724                                 and self.settings["source_path_hash"]!=clst_unpack_hash:
725                                 """ Autoresume is invalid, tarball """
726                                 unpack=True
727                                 invalid_snapshot=True
728                 else:
729                         """ No autoresume, SEEDCACHE """
730                         if self.settings.has_key("SEEDCACHE"):
731                                 """ SEEDCACHE so let's run rsync and let it clean up """
732                                 if os.path.isdir(self.settings["source_path"]):
733                                         unpack=True
734                                         invalid_snapshot=False
735                                 elif os.path.isfile(self.settings["source_path"]):
736                                         """ Tarball so unpack and remove anything already there """
737                                         unpack=True
738                                         invalid_snapshot=True
739                                 """ No autoresume, no SEEDCACHE """
740                         else:
741                                 """ Tarball so unpack and remove anything already there """
742                                 if os.path.isfile(self.settings["source_path"]):
743                                         unpack=True
744                                         invalid_snapshot=True
745                                 elif os.path.isdir(self.settings["source_path"]):
746                                         """ We should never reach this, so something is very wrong """
747                                         raise CatalystError,\
748                                                 "source path is a dir but seedcache is not enabled"
749
750                 if unpack:
751                         self.mount_safety_check()
752
753                         if invalid_snapshot:
754                                 if self.settings.has_key("AUTORESUME"):
755                                         print "No Valid Resume point detected, cleaning up..."
756
757                                 self.clear_autoresume()
758                                 self.clear_chroot()
759
760                         if not os.path.exists(self.settings["chroot_path"]):
761                                 os.makedirs(self.settings["chroot_path"])
762
763                         if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
764                                 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
765
766                         if self.settings.has_key("PKGCACHE"):
767                                 if not os.path.exists(self.settings["pkgcache_path"]):
768                                         os.makedirs(self.settings["pkgcache_path"],0755)
769
770                         if self.settings.has_key("KERNCACHE"):
771                                 if not os.path.exists(self.settings["kerncache_path"]):
772                                         os.makedirs(self.settings["kerncache_path"],0755)
773
774                         print display_msg
775                         cmd(unpack_cmd,error_msg,env=self.env)
776
777                         if self.settings.has_key("source_path_hash"):
778                                 myf=open(self.settings["autoresume_path"]+"unpack","w")
779                                 myf.write(self.settings["source_path_hash"])
780                                 myf.close()
781                         else:
782                                 touch(self.settings["autoresume_path"]+"unpack")
783                 else:
784                         print "Resume point detected, skipping unpack operation..."
785
786         def unpack_snapshot(self):
787                 unpack=True
788                 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
789                         "unpack_portage")
790
791                 if self.settings.has_key("SNAPCACHE"): 
792                         snapshot_cache_hash=\
793                                 read_from_clst(self.settings["snapshot_cache_path"]+\
794                                 "catalyst-hash")
795                         destdir=self.settings["snapshot_cache_path"]
796                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
797                         unpack_errmsg="Error unpacking snapshot"
798                         cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
799                                 self.settings["snapshot_cache_path"]+\
800                                 " (This can take a long time)..."
801                         cleanup_errmsg="Error removing existing snapshot cache directory."
802                         self.snapshot_lock_object=self.snapcache_lock
803
804                         if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
805                                 print "Valid snapshot cache, skipping unpack of portage tree..."
806                                 unpack=False
807                 else:
808                         destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
809                         cleanup_errmsg="Error removing existing snapshot directory."
810                         cleanup_msg=\
811                                 "Cleaning up existing portage tree (This can take a long time)..."
812                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
813                                 self.settings["chroot_path"]+"/usr"
814                         unpack_errmsg="Error unpacking snapshot"
815
816                         if self.settings.has_key("AUTORESUME") \
817                                 and os.path.exists(self.settings["chroot_path"]+\
818                                         "/usr/portage/") \
819                                 and os.path.exists(self.settings["autoresume_path"]\
820                                         +"unpack_portage") \
821                                 and self.settings["snapshot_path_hash"] == snapshot_hash:
822                                         print \
823                                                 "Valid Resume point detected, skipping unpack of portage tree..."
824                                         unpack=False
825
826                 if unpack:
827                         if self.settings.has_key("SNAPCACHE"): 
828                                 self.snapshot_lock_object.write_lock()
829                         if os.path.exists(destdir):
830                                 print cleanup_msg
831                                 cleanup_cmd="rm -rf "+destdir
832                                 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
833                         if not os.path.exists(destdir):
834                                 os.makedirs(destdir,0755)
835
836                         print "Unpacking portage tree (This can take a long time) ..."
837                         cmd(unpack_cmd,unpack_errmsg,env=self.env)
838
839                         if self.settings.has_key("SNAPCACHE"): 
840                                 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
841                                 myf.write(self.settings["snapshot_path_hash"])
842                                 myf.close()
843                         else:
844                                 print "Setting snapshot autoresume point"
845                                 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
846                                 myf.write(self.settings["snapshot_path_hash"])
847                                 myf.close()
848
849                         if self.settings.has_key("SNAPCACHE"): 
850                                 self.snapshot_lock_object.unlock()
851
852         def config_profile_link(self):
853                 if self.settings.has_key("AUTORESUME") \
854                         and os.path.exists(self.settings["autoresume_path"]+\
855                                 "config_profile_link"):
856                         print \
857                                 "Resume point detected, skipping config_profile_link operation..."
858                 else:
859                         # TODO: zmedico and I discussed making this a directory and pushing
860                         # in a parent file, as well as other user-specified configuration.
861                         print "Configuring profile link..."
862                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
863                                         "Error zapping profile link",env=self.env)
864                         cmd("ln -sf ../usr/portage/profiles/"+\
865                                 self.settings["target_profile"]+" "+\
866                                 self.settings["chroot_path"]+"/etc/make.profile",\
867                                 "Error creating profile link",env=self.env)
868                         touch(self.settings["autoresume_path"]+"config_profile_link")
869
870         def setup_confdir(self):
871                 if self.settings.has_key("AUTORESUME") \
872                         and os.path.exists(self.settings["autoresume_path"]+\
873                                 "setup_confdir"):
874                         print "Resume point detected, skipping setup_confdir operation..."
875                 else:
876                         if self.settings.has_key("portage_confdir"):
877                                 print "Configuring /etc/portage..."
878                                 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
879                                         "Error zapping /etc/portage",env=self.env)
880                                 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
881                                         self.settings["chroot_path"]+"/etc/portage",\
882                                         "Error copying /etc/portage",env=self.env)
883                                 touch(self.settings["autoresume_path"]+"setup_confdir")
884
885         def portage_overlay(self):
886                 """ We copy the contents of our overlays to /usr/local/portage """
887                 if self.settings.has_key("portage_overlay"):
888                         for x in self.settings["portage_overlay"]: 
889                                 if os.path.exists(x):
890                                         print "Copying overlay dir " +x
891                                         cmd("mkdir -p "+self.settings["chroot_path"]+\
892                                                 "/usr/local/portage",\
893                                                 "Could not make portage_overlay dir",env=self.env)
894                                         cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
895                                                 "/usr/local/portage",\
896                                                 "Could not copy portage_overlay",env=self.env)
897
898         def root_overlay(self):
899                 """ Copy over the root_overlay """
900                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
901                         for x in self.settings[self.settings["spec_prefix"]+\
902                                 "/root_overlay"]: 
903                                 if os.path.exists(x):
904                                         print "Copying root_overlay: "+x
905                                         cmd("rsync -a "+x+"/ "+\
906                                                 self.settings["chroot_path"],\
907                                                 self.settings["spec_prefix"]+"/root_overlay: "+x+\
908                                                 " copy failed.",env=self.env)
909
910         def base_dirs(self):
911                 pass
912
913         def bind(self):
914                 for x in self.mounts: 
915                         if not os.path.exists(self.settings["chroot_path"]+x):
916                                 os.makedirs(self.settings["chroot_path"]+x,0755)
917
918                         if not os.path.exists(self.mountmap[x]):
919                                 os.makedirs(self.mountmap[x],0755)
920
921                         src=self.mountmap[x]
922                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
923                                 self.snapshot_lock_object.read_lock()
924                         if os.uname()[0] == "FreeBSD":
925                                 if src == "/dev":
926                                         retval=os.system("mount -t devfs none "+\
927                                                 self.settings["chroot_path"]+x)
928                                 else:
929                                         retval=os.system("mount_nullfs "+src+" "+\
930                                                 self.settings["chroot_path"]+x)
931                         else:
932                                 retval=os.system("mount --bind "+src+" "+\
933                                         self.settings["chroot_path"]+x)
934                         if retval!=0:
935                                 self.unbind()
936                                 raise CatalystError,"Couldn't bind mount "+src
937
938         def unbind(self):
939                 ouch=0
940                 mypath=self.settings["chroot_path"]
941                 myrevmounts=self.mounts[:]
942                 myrevmounts.reverse()
943                 """ Unmount in reverse order for nested bind-mounts """
944                 for x in myrevmounts:
945                         if not os.path.exists(mypath+x):
946                                 continue
947
948                         if not ismount(mypath+x):
949                                 continue
950
951                         retval=os.system("umount "+\
952                                 os.path.join(mypath,x.lstrip(os.path.sep)))
953
954                         if retval!=0:
955                                 warn("First attempt to unmount: "+mypath+x+" failed.")
956                                 warn("Killing any pids still running in the chroot")
957
958                                 self.kill_chroot_pids()
959
960                                 retval2=os.system("umount "+mypath+x)
961                                 if retval2!=0:
962                                         ouch=1
963                                         warn("Couldn't umount bind mount: "+mypath+x)
964
965                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
966                                 try:
967                                         """
968                                         It's possible the snapshot lock object isn't created yet.
969                                         This is because mount safety check calls unbind before the
970                                         target is fully initialized
971                                         """
972                                         self.snapshot_lock_object.unlock()
973                                 except:
974                                         pass
975                 if ouch:
976                         """
977                         if any bind mounts really failed, then we need to raise
978                         this to potentially prevent an upcoming bash stage cleanup script
979                         from wiping our bind mounts.
980                         """
981                         raise CatalystError,\
982                                 "Couldn't umount one or more bind-mounts; aborting for safety."
983
984         def chroot_setup(self):
985                 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
986                         "/etc/make.conf")
987                 self.override_cbuild()
988                 self.override_chost()
989                 self.override_cflags()
990                 self.override_cxxflags()        
991                 self.override_ldflags() 
992                 if self.settings.has_key("AUTORESUME") \
993                         and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
994                         print "Resume point detected, skipping chroot_setup operation..."
995                 else:
996                         print "Setting up chroot..."
997                         
998                         #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
999                         
1000                         cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1001                                 "Could not copy resolv.conf into place.",env=self.env)
1002                 
1003                         """ Copy over the envscript, if applicable """
1004                         if self.settings.has_key("ENVSCRIPT"):
1005                                 if not os.path.exists(self.settings["ENVSCRIPT"]):
1006                                         raise CatalystError,\
1007                                                 "Can't find envscript "+self.settings["ENVSCRIPT"]
1008
1009                                 print "\nWarning!!!!"
1010                                 print "\tOverriding certain env variables may cause catastrophic failure."
1011                                 print "\tIf your build fails look here first as the possible problem."
1012                                 print "\tCatalyst assumes you know what you are doing when setting"
1013                                 print "\t\tthese variables."
1014                                 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1015                                 print "\tYou have been warned\n"
1016
1017                                 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1018                                         self.settings["chroot_path"]+"/tmp/envscript",\
1019                                         "Could not copy envscript into place.",env=self.env)
1020
1021                         """ Setup metadata_overlay """
1022                         if self.settings.has_key("METADATA_OVERLAY") \
1023                                 and not self.settings.has_key("portage_confdir"):
1024                                 if not os.path.exists(self.settings["chroot_path"]+\
1025                                         "/etc/portage"):
1026                                         cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
1027                                 myf=open(self.settings["chroot_path"]+\
1028                                         "/etc/portage/modules","a")
1029                                 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
1030                                 myf.close()
1031
1032
1033                         """
1034                         Copy over /etc/hosts from the host in case there are any
1035                         specialties in there
1036                         """
1037                         if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1038                                 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1039                                         self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1040                                         "Could not backup /etc/hosts",env=self.env)
1041                                 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1042                                         "Could not copy /etc/hosts",env=self.env)
1043
1044                         """ Modify and write out make.conf (for the chroot) """
1045                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
1046                                 "Could not remove "+self.settings["chroot_path"]+\
1047                                 "/etc/make.conf",env=self.env)
1048                         myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1049                         myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1050                         myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1051                         if self.settings.has_key("CFLAGS"):
1052                                 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1053                         if self.settings.has_key("CXXFLAGS"):
1054                                 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1055                         else:
1056                                 myf.write('CXXFLAGS="${CFLAGS}"\n')
1057
1058                         if self.settings.has_key("LDFLAGS"):
1059                                 myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
1060                                 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1061                         if self.settings.has_key("CBUILD"):
1062                                 myf.write("# This should not be changed unless you know exactly what you are doing.  You\n# should probably be using a different stage, instead.\n")
1063                                 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1064
1065                         myf.write("# WARNING: Changing your CHOST is not something that should be done lightly.\n# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.\n")
1066                         myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1067
1068                         """ Figure out what our USE vars are for building """
1069                         myusevars=[]
1070                         if self.settings.has_key("HOSTUSE"):
1071                                 myusevars.extend(self.settings["HOSTUSE"])
1072
1073                         if self.settings.has_key("use"):
1074                                 myusevars.extend(self.settings["use"])
1075
1076                         if myusevars:
1077                                 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1078                                 myusevars = sorted(set(myusevars))
1079                                 myf.write('USE="'+string.join(myusevars)+'"\n')
1080                                 if '-*' in myusevars:
1081                                         print "\nWarning!!!  "
1082                                         print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1083                                                 "/use will cause portage to ignore"
1084                                         print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1085
1086                         """ Setup the portage overlay """
1087                         if self.settings.has_key("portage_overlay"):
1088                                 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1089
1090                         myf.close()
1091                         cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1092                                 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1093                                 "Could not backup /etc/make.conf",env=self.env)
1094                         touch(self.settings["autoresume_path"]+"chroot_setup")
1095
1096         def fsscript(self):
1097                 if self.settings.has_key("AUTORESUME") \
1098                         and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1099                         print "Resume point detected, skipping fsscript operation..."
1100                 else:
1101                         if self.settings.has_key("fsscript"):
1102                                 if os.path.exists(self.settings["controller_file"]):
1103                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1104                                                 " fsscript","fsscript script failed.",env=self.env)
1105                                         touch(self.settings["autoresume_path"]+"fsscript")
1106
1107         def rcupdate(self):
1108                 if self.settings.has_key("AUTORESUME") \
1109                         and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1110                         print "Resume point detected, skipping rcupdate operation..."
1111                 else:
1112                         if os.path.exists(self.settings["controller_file"]):
1113                                 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1114                                         "rc-update script failed.",env=self.env)
1115                                 touch(self.settings["autoresume_path"]+"rcupdate")
1116
1117         def clean(self):
1118                 if self.settings.has_key("AUTORESUME") \
1119                         and os.path.exists(self.settings["autoresume_path"]+"clean"):
1120                         print "Resume point detected, skipping clean operation..."
1121                 else:
1122                         for x in self.settings["cleanables"]: 
1123                                 print "Cleaning chroot: "+x+"... "
1124                                 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1125                                         x,env=self.env)
1126
1127                 """ Put /etc/hosts back into place """
1128                 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1129                         cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1130                                 self.settings["chroot_path"]+"/etc/hosts",\
1131                                 "Could not replace /etc/hosts",env=self.env)
1132
1133                 """ Remove our overlay """
1134                 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1135                         cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1136                                 "Could not remove /usr/local/portage",env=self.env)
1137                         cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1138                                 "/etc/make.conf",\
1139                                 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1140
1141                 """ Clean up old and obsoleted files in /etc """
1142                 if os.path.exists(self.settings["stage_path"]+"/etc"):
1143                         cmd("find "+self.settings["stage_path"]+\
1144                                 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1145                                 "Could not remove stray files in /etc",env=self.env)
1146
1147                 if os.path.exists(self.settings["controller_file"]):
1148                         cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1149                                 "clean script failed.",env=self.env)
1150                         touch(self.settings["autoresume_path"]+"clean")
1151
1152         def empty(self):
1153                 if self.settings.has_key("AUTORESUME") \
1154                         and os.path.exists(self.settings["autoresume_path"]+"empty"):
1155                         print "Resume point detected, skipping empty operation..."
1156                 else:
1157                         if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1158                                 if type(self.settings[self.settings["spec_prefix"]+\
1159                                         "/empty"])==types.StringType:
1160                                         self.settings[self.settings["spec_prefix"]+"/empty"]=\
1161                                                 self.settings[self.settings["spec_prefix"]+\
1162                                                 "/empty"].split()
1163                                 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1164                                         myemp=self.settings["destpath"]+x
1165                                         if not os.path.isdir(myemp):
1166                                                 print x,"not a directory or does not exist, skipping 'empty' operation."
1167                                                 continue
1168                                         print "Emptying directory",x
1169                                         """ 
1170                                         stat the dir, delete the dir, recreate the dir and set
1171                                         the proper perms and ownership
1172                                         """
1173                                         mystat=os.stat(myemp)
1174                                         shutil.rmtree(myemp)
1175                                         os.makedirs(myemp,0755)
1176                                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1177                                         os.chmod(myemp,mystat[ST_MODE])
1178                         touch(self.settings["autoresume_path"]+"empty")
1179
1180         def remove(self):
1181                 if self.settings.has_key("AUTORESUME") \
1182                         and os.path.exists(self.settings["autoresume_path"]+"remove"):
1183                         print "Resume point detected, skipping remove operation..."
1184                 else:
1185                         if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1186                                 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1187                                         """
1188                                         We're going to shell out for all these cleaning
1189                                         operations, so we get easy glob handling.
1190                                         """
1191                                         print "livecd: removing "+x
1192                                         os.system("rm -rf "+self.settings["chroot_path"]+x)
1193                                 try:
1194                                         if os.path.exists(self.settings["controller_file"]):
1195                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1196                                                         " clean","Clean  failed.",env=self.env)
1197                                                 touch(self.settings["autoresume_path"]+"remove")
1198                                 except:
1199                                         self.unbind()
1200                                         raise
1201
1202         def preclean(self):
1203                 if self.settings.has_key("AUTORESUME") \
1204                         and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1205                         print "Resume point detected, skipping preclean operation..."
1206                 else:
1207                         try:
1208                                 if os.path.exists(self.settings["controller_file"]):
1209                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1210                                                 " preclean","preclean script failed.",env=self.env)
1211                                         touch(self.settings["autoresume_path"]+"preclean")
1212                 
1213                         except:
1214                                 self.unbind()
1215                                 raise CatalystError, "Build failed, could not execute preclean"
1216
1217         def capture(self):
1218                 if self.settings.has_key("AUTORESUME") \
1219                         and os.path.exists(self.settings["autoresume_path"]+"capture"):
1220                         print "Resume point detected, skipping capture operation..."
1221                 else:
1222                         """ Capture target in a tarball """
1223                         mypath=self.settings["target_path"].split("/")
1224                         """ Remove filename from path """
1225                         mypath=string.join(mypath[:-1],"/")
1226
1227                         """ Now make sure path exists """
1228                         if not os.path.exists(mypath):
1229                                 os.makedirs(mypath)
1230
1231                         print "Creating stage tarball..."
1232
1233                         cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1234                                 self.settings["stage_path"]+" .",\
1235                                 "Couldn't create stage tarball",env=self.env)
1236
1237                         self.gen_contents_file(self.settings["target_path"])
1238                         self.gen_digest_file(self.settings["target_path"])
1239
1240                         touch(self.settings["autoresume_path"]+"capture")
1241
1242         def run_local(self):
1243                 if self.settings.has_key("AUTORESUME") \
1244                         and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1245                         print "Resume point detected, skipping run_local operation..."
1246                 else:
1247                         try:
1248                                 if os.path.exists(self.settings["controller_file"]):
1249                                         cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1250                                                 "run script failed.",env=self.env)
1251                                         touch(self.settings["autoresume_path"]+"run_local")
1252
1253                         except CatalystError:
1254                                 self.unbind()
1255                                 raise CatalystError,"Stage build aborting due to error."
1256
1257         def setup_environment(self):
1258                 """
1259                 Modify the current environment. This is an ugly hack that should be
1260                 fixed. We need this to use the os.system() call since we can't
1261                 specify our own environ
1262                 """
1263                 for x in self.settings.keys():
1264                         """ Sanitize var names by doing "s|/-.|_|g" """
1265                         varname="clst_"+string.replace(x,"/","_")
1266                         varname=string.replace(varname,"-","_")
1267                         varname=string.replace(varname,".","_")
1268                         if type(self.settings[x])==types.StringType:
1269                                 """ Prefix to prevent namespace clashes """
1270                                 #os.environ[varname]=self.settings[x]
1271                                 self.env[varname]=self.settings[x]
1272                         elif type(self.settings[x])==types.ListType:
1273                                 #os.environ[varname]=string.join(self.settings[x])
1274                                 self.env[varname]=string.join(self.settings[x])
1275                         elif type(self.settings[x])==types.BooleanType:
1276                                 if self.settings[x]:
1277                                         self.env[varname]="true"
1278                                 else:
1279                                         self.env[varname]="false"
1280                 if self.settings.has_key("makeopts"):
1281                         self.env["MAKEOPTS"]=self.settings["makeopts"]
1282
1283         def run(self):
1284                 self.chroot_lock.write_lock()
1285
1286                 """ Kill any pids in the chroot "" """
1287                 self.kill_chroot_pids()
1288
1289                 """ Check for mounts right away and abort if we cannot unmount them """
1290                 self.mount_safety_check()
1291
1292                 if self.settings.has_key("CLEAR_AUTORESUME"):
1293                         self.clear_autoresume()
1294                 if self.settings.has_key("PURGE"):
1295                         self.purge()
1296
1297                 for x in self.settings["action_sequence"]:
1298                         print "--- Running action sequence: "+x
1299                         sys.stdout.flush()
1300                         try:
1301                                 apply(getattr(self,x))
1302                         except:
1303                                 self.mount_safety_check()
1304                                 raise
1305                 
1306                 self.chroot_lock.unlock()
1307
1308         def unmerge(self):
1309                 if self.settings.has_key("AUTORESUME") \
1310                         and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1311                         print "Resume point detected, skipping unmerge operation..."
1312                 else:
1313                         if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1314                                 if type(self.settings[self.settings["spec_prefix"]+\
1315                                         "/unmerge"])==types.StringType:
1316                                         self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1317                                                 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1318                                 myunmerge=\
1319                                         self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1320
1321                                 for x in range(0,len(myunmerge)):
1322                                         """
1323                                         Surround args with quotes for passing to bash, allows
1324                                         things like "<" to remain intact
1325                                         """
1326                                         myunmerge[x]="'"+myunmerge[x]+"'"
1327                                 myunmerge=string.join(myunmerge)
1328
1329                                 """ Before cleaning, unmerge stuff """
1330                                 try:
1331                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1332                                                 " unmerge "+ myunmerge,"Unmerge script failed.",\
1333                                                 env=self.env)
1334                                         print "unmerge shell script"
1335                                 except CatalystError:
1336                                         self.unbind()
1337                                         raise
1338                                 touch(self.settings["autoresume_path"]+"unmerge")
1339
1340         def target_setup(self):
1341                 if self.settings.has_key("AUTORESUME") \
1342                         and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1343                         print "Resume point detected, skipping target_setup operation..."
1344                 else:
1345                         print "Setting up filesystems per filesystem type"
1346                         cmd("/bin/bash "+self.settings["controller_file"]+\
1347                                 " target_image_setup "+ self.settings["target_path"],\
1348                                 "target_image_setup script failed.",env=self.env)
1349                         touch(self.settings["autoresume_path"]+"target_setup")
1350
1351         def setup_overlay(self):
1352                 if self.settings.has_key("AUTORESUME") \
1353                 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1354                         print "Resume point detected, skipping setup_overlay operation..."
1355                 else:
1356                         if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1357                                 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]: 
1358                                         if os.path.exists(x):
1359                                                 cmd("rsync -a "+x+"/ "+\
1360                                                         self.settings["target_path"],\
1361                                                         self.settings["spec_prefix"]+"overlay: "+x+\
1362                                                         " copy failed.",env=self.env)
1363                                 touch(self.settings["autoresume_path"]+"setup_overlay")
1364
1365         def create_iso(self):
1366                 if self.settings.has_key("AUTORESUME") \
1367                         and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1368                         print "Resume point detected, skipping create_iso operation..."
1369                 else:
1370                         """ Create the ISO """
1371                         if self.settings.has_key("iso"):
1372                                 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1373                                         self.settings["iso"],"ISO creation script failed.",\
1374                                         env=self.env)
1375                                 self.gen_contents_file(self.settings["iso"])
1376                                 self.gen_digest_file(self.settings["iso"])
1377                                 touch(self.settings["autoresume_path"]+"create_iso")
1378                         else:
1379                                 print "WARNING: livecd/iso was not defined."
1380                                 print "An ISO Image will not be created."
1381
1382         def build_packages(self):
1383                 if self.settings.has_key("AUTORESUME") \
1384                         and os.path.exists(self.settings["autoresume_path"]+\
1385                                 "build_packages"):
1386                         print "Resume point detected, skipping build_packages operation..."
1387                 else:
1388                         if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1389                                 if self.settings.has_key("AUTORESUME") \
1390                                         and os.path.exists(self.settings["autoresume_path"]+\
1391                                                 "build_packages"):
1392                                         print "Resume point detected, skipping build_packages operation..."
1393                                 else:
1394                                         mypack=\
1395                                                 list_bashify(self.settings[self.settings["spec_prefix"]\
1396                                                 +"/packages"])
1397                                         try:
1398                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1399                                                         " build_packages "+mypack,\
1400                                                         "Error in attempt to build packages",env=self.env)
1401                                                 touch(self.settings["autoresume_path"]+"build_packages")
1402                                         except CatalystError:
1403                                                 self.unbind()
1404                                                 raise CatalystError,self.settings["spec_prefix"]+\
1405                                                         "build aborting due to error."
1406
1407         def build_kernel(self):
1408                 if self.settings.has_key("AUTORESUME") \
1409                         and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1410                         print "Resume point detected, skipping build_kernel operation..."
1411                 else:
1412                         if self.settings.has_key("boot/kernel"):
1413                                 try:
1414                                         mynames=self.settings["boot/kernel"]
1415                                         if type(mynames)==types.StringType:
1416                                                 mynames=[mynames]
1417                                         """
1418                                         Execute the script that sets up the kernel build environment
1419                                         """
1420                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1421                                                 " pre-kmerge ","Runscript pre-kmerge failed",\
1422                                                 env=self.env)
1423
1424                                         for kname in mynames:
1425                                                 if self.settings.has_key("AUTORESUME") \
1426                                                         and os.path.exists(self.settings["autoresume_path"]\
1427                                                                 +"build_kernel_"+kname):
1428                                                         print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1429                                                 else: # TODO: make this not require a kernel config
1430                                                         try:
1431                                                                 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1432                                                                         self.unbind()
1433                                                                         raise CatalystError,\
1434                                                                                 "Can't find kernel config: "+\
1435                                                                                 self.settings["boot/kernel/"+kname+\
1436                                                                                 "/config"]
1437
1438                                                         except TypeError:
1439                                                                 raise CatalystError,\
1440                                                                         "Required value boot/kernel/config not specified"
1441
1442                                                         try:
1443                                                                 cmd("cp "+self.settings["boot/kernel/"+kname+\
1444                                                                         "/config"]+" "+\
1445                                                                         self.settings["chroot_path"]+"/var/tmp/"+\
1446                                                                         kname+".config",\
1447                                                                         "Couldn't copy kernel config: "+\
1448                                                                         self.settings["boot/kernel/"+kname+\
1449                                                                         "/config"],env=self.env)
1450
1451                                                         except CatalystError:
1452                                                                 self.unbind()
1453
1454                                                         """
1455                                                         If we need to pass special options to the bootloader
1456                                                         for this kernel put them into the environment
1457                                                         """
1458                                                         if self.settings.has_key("boot/kernel/"+kname+\
1459                                                                 "/kernelopts"):
1460                                                                 myopts=self.settings["boot/kernel/"+kname+\
1461                                                                         "/kernelopts"]
1462
1463                                                                 if type(myopts) != types.StringType:
1464                                                                         myopts = string.join(myopts)
1465                                                                         self.env[kname+"_kernelopts"]=myopts
1466
1467                                                                 else:
1468                                                                         self.env[kname+"_kernelopts"]=""
1469
1470                                                         if not self.settings.has_key("boot/kernel/"+kname+\
1471                                                                 "/extraversion"):
1472                                                                 self.settings["boot/kernel/"+kname+\
1473                                                                         "/extraversion"]=""
1474
1475                                                         self.env["clst_kextraversion"]=\
1476                                                                 self.settings["boot/kernel/"+kname+\
1477                                                                 "/extraversion"]
1478
1479                                                         if self.settings.has_key("boot/kernel/"+kname+\
1480                                                                 "/initramfs_overlay"):
1481                                                                 if os.path.exists(self.settings["boot/kernel/"+\
1482                                                                         kname+"/initramfs_overlay"]):
1483                                                                         print "Copying initramfs_overlay dir "+\
1484                                                                                 self.settings["boot/kernel/"+kname+\
1485                                                                                 "/initramfs_overlay"]
1486
1487                                                                         cmd("mkdir -p "+\
1488                                                                                 self.settings["chroot_path"]+\
1489                                                                                 "/tmp/initramfs_overlay/"+\
1490                                                                                 self.settings["boot/kernel/"+kname+\
1491                                                                                 "/initramfs_overlay"],env=self.env)
1492
1493                                                                         cmd("cp -R "+self.settings["boot/kernel/"+\
1494                                                                                 kname+"/initramfs_overlay"]+"/* "+\
1495                                                                                 self.settings["chroot_path"]+\
1496                                                                                 "/tmp/initramfs_overlay/"+\
1497                                                                                 self.settings["boot/kernel/"+kname+\
1498                                                                                 "/initramfs_overlay"],env=self.env)
1499
1500                                                         """ Execute the script that builds the kernel """
1501                                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1502                                                                 " kernel "+kname,\
1503                                                                 "Runscript kernel build failed",env=self.env)
1504
1505                                                         if self.settings.has_key("boot/kernel/"+kname+\
1506                                                                 "/initramfs_overlay"):
1507                                                                 if os.path.exists(self.settings["chroot_path"]+\
1508                                                                         "/tmp/initramfs_overlay/"):
1509                                                                         print "Cleaning up temporary overlay dir"
1510                                                                         cmd("rm -R "+self.settings["chroot_path"]+\
1511                                                                                 "/tmp/initramfs_overlay/",env=self.env)
1512
1513                                                         touch(self.settings["autoresume_path"]+\
1514                                                                 "build_kernel_"+kname)
1515
1516                                                         """
1517                                                         Execute the script that cleans up the kernel build
1518                                                         environment
1519                                                         """
1520                                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1521                                                                 " post-kmerge ",
1522                                                                 "Runscript post-kmerge failed",env=self.env)
1523
1524                                         touch(self.settings["autoresume_path"]+"build_kernel")
1525
1526                                 except CatalystError:
1527                                         self.unbind()
1528                                         raise CatalystError,\
1529                                                 "build aborting due to kernel build error."
1530
1531         def bootloader(self):
1532                 if self.settings.has_key("AUTORESUME") \
1533                         and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1534                         print "Resume point detected, skipping bootloader operation..."
1535                 else:
1536                         try:
1537                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1538                                         " bootloader " + self.settings["target_path"],\
1539                                         "Bootloader runscript failed.",env=self.env)
1540                                 touch(self.settings["autoresume_path"]+"bootloader")
1541                         except CatalystError:
1542                                 self.unbind()
1543                                 raise CatalystError,"Runscript aborting due to error."
1544
1545         def livecd_update(self):
1546                 if self.settings.has_key("AUTORESUME") \
1547                         and os.path.exists(self.settings["autoresume_path"]+\
1548                                 "livecd_update"):
1549                         print "Resume point detected, skipping build_packages operation..."
1550                 else:
1551                         try:
1552                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1553                                         " livecd-update","livecd-update failed.",env=self.env)
1554                                 touch(self.settings["autoresume_path"]+"livecd_update")
1555
1556                         except CatalystError:
1557                                 self.unbind()
1558                                 raise CatalystError,"build aborting due to livecd_update error."
1559
1560         def clear_chroot(self):
1561                 myemp=self.settings["chroot_path"]
1562                 if os.path.isdir(myemp):
1563                         print "Emptying directory",myemp
1564                         """
1565                         stat the dir, delete the dir, recreate the dir and set
1566                         the proper perms and ownership
1567                         """
1568                         mystat=os.stat(myemp)
1569                         #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1570                         """ There's no easy way to change flags recursively in python """
1571                         if os.uname()[0] == "FreeBSD":
1572                                 os.system("chflags -R noschg "+myemp)
1573                         shutil.rmtree(myemp)
1574                         os.makedirs(myemp,0755)
1575                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1576                         os.chmod(myemp,mystat[ST_MODE])
1577
1578         def clear_packages(self):
1579                 if self.settings.has_key("PKGCACHE"):
1580                         print "purging the pkgcache ..."
1581
1582                         myemp=self.settings["pkgcache_path"]
1583                         if os.path.isdir(myemp):
1584                                 print "Emptying directory",myemp
1585                                 """
1586                                 stat the dir, delete the dir, recreate the dir and set
1587                                 the proper perms and ownership
1588                                 """
1589                                 mystat=os.stat(myemp)
1590                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1591                                 shutil.rmtree(myemp)
1592                                 os.makedirs(myemp,0755)
1593                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1594                                 os.chmod(myemp,mystat[ST_MODE])
1595
1596         def clear_kerncache(self):
1597                 if self.settings.has_key("KERNCACHE"):
1598                         print "purging the kerncache ..."
1599
1600                         myemp=self.settings["kerncache_path"]
1601                         if os.path.isdir(myemp):
1602                                 print "Emptying directory",myemp
1603                                 """
1604                                 stat the dir, delete the dir, recreate the dir and set
1605                                 the proper perms and ownership
1606                                 """
1607                                 mystat=os.stat(myemp)
1608                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1609                                 shutil.rmtree(myemp)
1610                                 os.makedirs(myemp,0755)
1611                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1612                                 os.chmod(myemp,mystat[ST_MODE])
1613
1614         def clear_autoresume(self):
1615                 """ Clean resume points since they are no longer needed """
1616                 if self.settings.has_key("AUTORESUME"):
1617                         print "Removing AutoResume Points: ..."
1618                 myemp=self.settings["autoresume_path"]
1619                 if os.path.isdir(myemp):
1620                                 if self.settings.has_key("AUTORESUME"):
1621                                         print "Emptying directory",myemp
1622                                 """
1623                                 stat the dir, delete the dir, recreate the dir and set
1624                                 the proper perms and ownership
1625                                 """
1626                                 mystat=os.stat(myemp)
1627                                 if os.uname()[0] == "FreeBSD":
1628                                         cmd("chflags -R noschg "+myemp,\
1629                                                 "Could not remove immutable flag for file "\
1630                                                 +myemp)
1631                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1632                                 shutil.rmtree(myemp)
1633                                 os.makedirs(myemp,0755)
1634                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1635                                 os.chmod(myemp,mystat[ST_MODE])
1636
1637         def gen_contents_file(self,file):
1638                 if os.path.exists(file+".CONTENTS"):
1639                         os.remove(file+".CONTENTS")
1640                 if self.settings.has_key("contents"):
1641                         if os.path.exists(file):
1642                                 myf=open(file+".CONTENTS","w")
1643                                 keys={}
1644                                 for i in self.settings["contents"].split():
1645                                         keys[i]=1
1646                                         array=keys.keys()
1647                                         array.sort()
1648                                 for j in array:
1649                                         contents=generate_contents(file,contents_function=j,\
1650                                                 verbose=self.settings.has_key("VERBOSE"))
1651                                         if contents:
1652                                                 myf.write(contents)
1653                                 myf.close()
1654
1655         def gen_digest_file(self,file):
1656                 if os.path.exists(file+".DIGESTS"):
1657                         os.remove(file+".DIGESTS")
1658                 if self.settings.has_key("digests"):
1659                         if os.path.exists(file):
1660                                 myf=open(file+".DIGESTS","w")
1661                                 keys={}
1662                                 for i in self.settings["digests"].split():
1663                                         keys[i]=1
1664                                         array=keys.keys()
1665                                         array.sort()
1666                                 for f in [file, file+'.CONTENTS']:
1667                                         if os.path.exists(f):
1668                                                 for j in array:
1669                                                         hash=generate_hash(f,hash_function=j,verbose=\
1670                                                                 self.settings.has_key("VERBOSE"))
1671                                                         myf.write(hash)
1672                                 myf.close()
1673
1674         def purge(self):
1675                 countdown(10,"Purging Caches ...")
1676                 if self.settings.has_key("PURGE"):
1677                         print "clearing autoresume ..."
1678                         self.clear_autoresume()
1679
1680                         print "clearing chroot ..."
1681                         self.clear_chroot()
1682
1683                         print "clearing package cache ..."
1684                         self.clear_packages()
1685
1686                         print "clearing kerncache ..."
1687                         self.clear_kerncache()
1688
1689 # vim: ts=4 sw=4 sta et sts=4 ai