Added TODO. Changed create_handbook_icon call to only be called if /docs/handbook...
[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 seedcache in the options of catalyst.conf"
411                         print "\tthe source path will then be "+\
412                                 normpath(self.settings["storedir"]+"/builds/"+\
413                                 self.settings["source_subpath"]+".tar.bz2\n")
414
415         def set_dest_path(self):
416                 if self.settings.has_key("root_path"):
417                         self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
418                                 self.settings["root_path"])
419                 else:
420                         self.settings["destpath"]=normpath(self.settings["chroot_path"])
421
422         def set_cleanables(self):
423                 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
424                         "/root/*","/usr/portage"]
425
426         def set_snapshot_path(self):
427                 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
428                         "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
429
430                 if os.path.exists(self.settings["snapshot_path"]):
431                         self.settings["snapshot_path_hash"]=\
432                                 generate_hash(self.settings["snapshot_path"],\
433                                 hash_function=self.settings["hash_function"],verbose=False)
434
435         def set_snapcache_path(self):
436                 if self.settings.has_key("SNAPCACHE"):
437                         self.settings["snapshot_cache_path"]=\
438                                 normpath(self.settings["snapshot_cache"]+"/"+\
439                                 self.settings["snapshot"]+"/")
440                         self.snapcache_lock=\
441                                 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
442                         print "Caching snapshot to "+self.settings["snapshot_cache_path"]
443
444         def set_chroot_path(self):
445                 """
446                 NOTE: the trailing slash is very important!
447                 Things *will* break without it!
448                 """
449                 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
450                         "/tmp/"+self.settings["target_subpath"]+"/")
451                 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
452
453         def set_autoresume_path(self):
454                 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
455                         "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
456                         self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
457                         self.settings["version_stamp"]+"/")
458                 if self.settings.has_key("AUTORESUME"):
459                         print "The autoresume path is " + self.settings["autoresume_path"]
460                 if not os.path.exists(self.settings["autoresume_path"]):
461                         os.makedirs(self.settings["autoresume_path"],0755)
462
463         def set_controller_file(self):
464                 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
465                         "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
466                         "-controller.sh")
467
468         def set_iso_volume_id(self):
469                 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
470                         self.settings["iso_volume_id"]=\
471                                 self.settings[self.settings["spec_prefix"]+"/volid"]
472                         if len(self.settings["iso_volume_id"])>32:
473                                 raise CatalystError,\
474                                         "ISO volume ID must not exceed 32 characters."
475                 else:
476                         self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"] 
477
478         def set_action_sequence(self):
479                 """ Default action sequence for run method """
480                 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
481                                 "config_profile_link","setup_confdir","portage_overlay",\
482                                 "base_dirs","bind","chroot_setup","setup_environment",\
483                                 "run_local","preclean","unbind","clean"]
484 #               if self.settings.has_key("TARBALL") or \
485 #                       not self.settings.has_key("FETCH"):
486                 if not self.settings.has_key("FETCH"):
487                         self.settings["action_sequence"].append("capture")
488                 self.settings["action_sequence"].append("clear_autoresume")
489
490         def set_use(self):
491                 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
492                         self.settings["use"]=\
493                                 self.settings[self.settings["spec_prefix"]+"/use"]
494                         del self.settings[self.settings["spec_prefix"]+"/use"]
495                 if self.settings.has_key("use"):
496                         if type(self.settings["use"])==types.StringType:
497                                 self.settings["use"]=self.settings["use"].split()
498                                 self.settings["use"].append("bindist")
499
500         def set_stage_path(self):
501                 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
502
503         def set_mounts(self):
504                 pass
505
506         def set_packages(self):
507                 pass
508
509         def set_rm(self):
510                 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
511                         if type(self.settings[self.settings["spec_prefix"]+\
512                                 "/rm"])==types.StringType:
513                                 self.settings[self.settings["spec_prefix"]+"/rm"]=\
514                                         self.settings[self.settings["spec_prefix"]+"/rm"].split()
515
516         def set_linuxrc(self):
517                 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
518                         if type(self.settings[self.settings["spec_prefix"]+\
519                                 "/linuxrc"])==types.StringType:
520                                 self.settings["linuxrc"]=\
521                                         self.settings[self.settings["spec_prefix"]+"/linuxrc"]
522                                 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
523
524         def set_portage_overlay(self):
525                 if self.settings.has_key("portage_overlay"):
526                         if type(self.settings["portage_overlay"])==types.StringType:
527                                 self.settings["portage_overlay"]=\
528                                         self.settings["portage_overlay"].split()
529                         print "portage_overlay directories are set to: \""+\
530                                 string.join(self.settings["portage_overlay"])+"\""
531
532         def set_overlay(self):
533                 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
534                         if type(self.settings[self.settings["spec_prefix"]+\
535                                 "/overlay"])==types.StringType:
536                                 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
537                                         self.settings[self.settings["spec_prefix"]+\
538                                         "/overlay"].split()
539
540         def set_root_overlay(self):
541                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
542                         if type(self.settings[self.settings["spec_prefix"]+\
543                                 "/root_overlay"])==types.StringType:
544                                 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
545                                         self.settings[self.settings["spec_prefix"]+\
546                                         "/root_overlay"].split()
547
548         def set_root_path(self):
549                 """ ROOT= variable for emerges """
550                 self.settings["root_path"]="/"
551
552         def set_valid_build_kernel_vars(self,addlargs):
553                 if addlargs.has_key("boot/kernel"):
554                         if type(addlargs["boot/kernel"])==types.StringType:
555                                 loopy=[addlargs["boot/kernel"]]
556                         else:
557                                 loopy=addlargs["boot/kernel"]
558
559                         for x in loopy:
560                                 self.valid_values.append("boot/kernel/"+x+"/aliases")
561                                 self.valid_values.append("boot/kernel/"+x+"/config")
562                                 self.valid_values.append("boot/kernel/"+x+"/console")
563                                 self.valid_values.append("boot/kernel/"+x+"/extraversion")
564                                 self.valid_values.append("boot/kernel/"+x+"/gk_action")
565                                 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
566                                 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
567                                 self.valid_values.append("boot/kernel/"+x+"/machine_type")
568                                 self.valid_values.append("boot/kernel/"+x+"/sources")
569                                 self.valid_values.append("boot/kernel/"+x+"/softlevel")
570                                 self.valid_values.append("boot/kernel/"+x+"/use")
571                                 self.valid_values.append("boot/kernel/"+x+"/packages")
572                                 if addlargs.has_key("boot/kernel/"+x+"/packages"):
573                                         if type(addlargs["boot/kernel/"+x+\
574                                                 "/packages"])==types.StringType:
575                                                 addlargs["boot/kernel/"+x+"/packages"]=\
576                                                         [addlargs["boot/kernel/"+x+"/packages"]]
577                                 # TODO: remove this warning/code with the next major version
578                                 self.valid_values.append("boot/kernel/"+x+"/postconf")
579                                 if addlargs.has_key("boot/kernel/"+x+"/postconf"):
580                                         print "boot/kernel/"+x+"/postconf is deprecated"
581                                         print "\tInternally moving these ebuilds to boot/kernel/"+\
582                                                 x+"/packages"
583                                         print "\tPlease move them to boot/kernel/"+x+\
584                                                 "/packages in your specfile"
585                                         if type(addlargs["boot/kernel/"+x+\
586                                                 "/postconf"])==types.StringType:
587                                                 loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
588                                         else:
589                                                 loop2=addlargs["boot/kernel/"+x+"/postconf"]
590                                 
591                                         for y in loop2:
592                                                 if not addlargs.has_key("boot/kernel/"+x+"/packages"):
593                                                         addlargs["boot/kernel/"+x+"/packages"]=[y]
594                                                 else:
595                                                         addlargs["boot/kernel/"+x+"/packages"].append(y)
596
597         def set_build_kernel_vars(self):
598                 if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
599                         # TODO: remove this warning/code with the next major version
600                         print self.settings["spec_prefix"]+\
601                                 "/devmanager is deprecated and will be removed."
602                         self.settings["devmanager"]=\
603                                 self.settings[self.settings["spec_prefix"]+"/devmanager"]
604                         del self.settings[self.settings["spec_prefix"]+"/devmanager"]
605
606                 if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
607                         # TODO: remove this warning/code with the next major version
608                         print self.settings["spec_prefix"]+\
609                                 "/splashtype is deprecated and will be removed."
610                         self.settings["splashtype"]=\
611                                 self.settings[self.settings["spec_prefix"]+"/splashtype"]
612                         del self.settings[self.settings["spec_prefix"]+"/splashtype"]
613
614                 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
615                         self.settings["gk_mainargs"]=\
616                                 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
617                         del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
618
619         def kill_chroot_pids(self):
620                 print "Checking for processes running in chroot and killing them."
621
622                 """
623                 Force environment variables to be exported so script can see them
624                 """
625                 self.setup_environment()
626
627                 if os.path.exists(self.settings["sharedir"]+\
628                         "/targets/support/kill-chroot-pids.sh"):
629                         cmd("/bin/bash "+self.settings["sharedir"]+\
630                                 "/targets/support/kill-chroot-pids.sh",\
631                                 "kill-chroot-pids script failed.",env=self.env)
632
633         def mount_safety_check(self):
634                 mypath=self.settings["chroot_path"]
635
636                 """
637                 Check and verify that none of our paths in mypath are mounted. We don't
638                 want to clean up with things still mounted, and this allows us to check. 
639                 Returns 1 on ok, 0 on "something is still mounted" case.
640                 """
641
642                 if not os.path.exists(mypath):
643                         return
644
645                 for x in self.mounts:
646                         if not os.path.exists(mypath+x):
647                                 continue
648
649                         if ismount(mypath+x):
650                                 """ Something is still mounted "" """
651                                 try:
652                                         print x+" is still mounted; performing auto-bind-umount...",
653                                         """ Try to umount stuff ourselves """
654                                         self.unbind()
655                                         if ismount(mypath+x):
656                                                 raise CatalystError, "Auto-unbind failed for "+x
657                                         else:
658                                                 print "Auto-unbind successful..."
659                                 except CatalystError:
660                                         raise CatalystError, "Unable to auto-unbind "+x
661
662         def unpack(self):
663                 unpack=True
664
665                 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
666                         "unpack")
667
668                 if self.settings.has_key("SEEDCACHE"):
669                         if os.path.isdir(self.settings["source_path"]): 
670                                 """ SEEDCACHE Is a directory, use rsync """
671                                 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
672                                         " "+self.settings["chroot_path"]
673                                 display_msg="\nStarting rsync from "+\
674                                         self.settings["source_path"]+"\nto "+\
675                                         self.settings["chroot_path"]+\
676                                         " (This may take some time) ...\n"
677                                 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
678                                         self.settings["chroot_path"]+" failed."
679                         else:
680                                 """ SEEDCACHE is a not a directory, try untar'ing """
681                                 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
682                                 display_msg="\nStarting tar extract from "+\
683                                         self.settings["source_path"]+"\nto "+\
684                                         self.settings["chroot_path"]+\
685                                                 " (This may take some time) ...\n"
686                                 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
687                                         self.settings["chroot_path"]
688                                 error_msg="Tarball extraction of "+\
689                                         self.settings["source_path"]+" to "+\
690                                         self.settings["chroot_path"]+" failed."
691                 else:
692                         """ No SEEDCACHE, use tar """
693                         display_msg="\nStarting tar extract from "+\
694                                 self.settings["source_path"]+"\nto "+\
695                                 self.settings["chroot_path"]+\
696                                 " (This may take some time) ...\n"
697                         unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
698                                 self.settings["chroot_path"]
699                         error_msg="Tarball extraction of "+self.settings["source_path"]+\
700                                 " to "+self.settings["chroot_path"]+" failed."
701
702                 if self.settings.has_key("AUTORESUME"):
703                         if os.path.isdir(self.settings["source_path"]) \
704                                 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
705                                 """ Autoresume is valid, SEEDCACHE is valid """
706                                 unpack=False
707                                 invalid_snapshot=False
708
709                         elif os.path.isfile(self.settings["source_path"]) \
710                                 and self.settings["source_path_hash"]==clst_unpack_hash:
711                                 """ Autoresume is valid, tarball is valid """
712                                 unpack=False
713                                 invalid_snapshot=True
714                         
715                         elif os.path.isdir(self.settings["source_path"]) \
716                                 and not os.path.exists(self.settings["autoresume_path"]+\
717                                 "unpack"):
718                                 """ Autoresume is invalid, SEEDCACHE """
719                                 unpack=True
720                                 invalid_snapshot=False
721
722                         elif os.path.isfile(self.settings["source_path"]) \
723                                 and self.settings["source_path_hash"]!=clst_unpack_hash:
724                                 """ Autoresume is invalid, tarball """
725                                 unpack=True
726                                 invalid_snapshot=True
727                 else:
728                         """ No autoresume, SEEDCACHE """
729                         if self.settings.has_key("SEEDCACHE"):
730                                 """ SEEDCACHE so let's run rsync and let it clean up """
731                                 if os.path.isdir(self.settings["source_path"]):
732                                         unpack=True
733                                         invalid_snapshot=False
734                                 elif os.path.isfile(self.settings["source_path"]):
735                                         """ Tarball so unpack and remove anything already there """
736                                         unpack=True
737                                         invalid_snapshot=True
738                                 """ No autoresume, no SEEDCACHE """
739                         else:
740                                 """ Tarball so unpack and remove anything already there """
741                                 if os.path.isfile(self.settings["source_path"]):
742                                         unpack=True
743                                         invalid_snapshot=True
744                                 elif os.path.isdir(self.settings["source_path"]):
745                                         """ We should never reach this, so something is very wrong """
746                                         raise CatalystError,\
747                                                 "source path is a dir but seedcache is not enabled"
748
749                 if unpack:
750                         self.mount_safety_check()
751
752                         if invalid_snapshot:
753                                 if self.settings.has_key("AUTORESUME"):
754                                         print "No Valid Resume point detected, cleaning up..."
755
756                                 self.clear_autoresume()
757                                 self.clear_chroot()
758
759                         if not os.path.exists(self.settings["chroot_path"]):
760                                 os.makedirs(self.settings["chroot_path"])
761
762                         if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
763                                 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
764
765                         if self.settings.has_key("PKGCACHE"):
766                                 if not os.path.exists(self.settings["pkgcache_path"]):
767                                         os.makedirs(self.settings["pkgcache_path"],0755)
768
769                         if self.settings.has_key("KERNCACHE"):
770                                 if not os.path.exists(self.settings["kerncache_path"]):
771                                         os.makedirs(self.settings["kerncache_path"],0755)
772
773                         print display_msg
774                         cmd(unpack_cmd,error_msg,env=self.env)
775
776                         if self.settings.has_key("source_path_hash"):
777                                 myf=open(self.settings["autoresume_path"]+"unpack","w")
778                                 myf.write(self.settings["source_path_hash"])
779                                 myf.close()
780                         else:
781                                 touch(self.settings["autoresume_path"]+"unpack")
782                 else:
783                         print "Resume point detected, skipping unpack operation..."
784
785         def unpack_snapshot(self):
786                 unpack=True
787                 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
788                         "unpack_portage")
789
790                 if self.settings.has_key("SNAPCACHE"): 
791                         snapshot_cache_hash=\
792                                 read_from_clst(self.settings["snapshot_cache_path"]+\
793                                 "catalyst-hash")
794                         destdir=self.settings["snapshot_cache_path"]
795                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
796                         unpack_errmsg="Error unpacking snapshot"
797                         cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
798                                 self.settings["snapshot_cache_path"]+\
799                                 " (This can take a long time)..."
800                         cleanup_errmsg="Error removing existing snapshot cache directory."
801                         self.snapshot_lock_object=self.snapcache_lock
802
803                         if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
804                                 print "Valid snapshot cache, skipping unpack of portage tree..."
805                                 unpack=False
806                 else:
807                         destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
808                         cleanup_errmsg="Error removing existing snapshot directory."
809                         cleanup_msg=\
810                                 "Cleaning up existing portage tree (This can take a long time)..."
811                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
812                                 self.settings["chroot_path"]+"/usr"
813                         unpack_errmsg="Error unpacking snapshot"
814
815                         if self.settings.has_key("AUTORESUME") \
816                                 and os.path.exists(self.settings["chroot_path"]+\
817                                         "/usr/portage/") \
818                                 and os.path.exists(self.settings["autoresume_path"]\
819                                         +"unpack_portage") \
820                                 and self.settings["snapshot_path_hash"] == snapshot_hash:
821                                         print \
822                                                 "Valid Resume point detected, skipping unpack of portage tree..."
823                                         unpack=False
824
825                 if unpack:
826                         if self.settings.has_key("SNAPCACHE"): 
827                                 self.snapshot_lock_object.write_lock()
828                         if os.path.exists(destdir):
829                                 print cleanup_msg
830                                 cleanup_cmd="rm -rf "+destdir
831                                 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
832                         if not os.path.exists(destdir):
833                                 os.makedirs(destdir,0755)
834
835                         print "Unpacking portage tree (This can take a long time) ..."
836                         cmd(unpack_cmd,unpack_errmsg,env=self.env)
837
838                         if self.settings.has_key("SNAPCACHE"): 
839                                 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
840                                 myf.write(self.settings["snapshot_path_hash"])
841                                 myf.close()
842                         else:
843                                 print "Setting snapshot autoresume point"
844                                 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
845                                 myf.write(self.settings["snapshot_path_hash"])
846                                 myf.close()
847
848                         if self.settings.has_key("SNAPCACHE"): 
849                                 self.snapshot_lock_object.unlock()
850
851         def config_profile_link(self):
852                 if self.settings.has_key("AUTORESUME") \
853                         and os.path.exists(self.settings["autoresume_path"]+\
854                                 "config_profile_link"):
855                         print \
856                                 "Resume point detected, skipping config_profile_link operation..."
857                 else:
858                         # TODO: zmedico and I discussed making this a directory and pushing
859                         # in a parent file, as well as other user-specified configuration.
860                         print "Configuring profile link..."
861                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
862                                         "Error zapping profile link",env=self.env)
863                         cmd("ln -sf ../usr/portage/profiles/"+\
864                                 self.settings["target_profile"]+" "+\
865                                 self.settings["chroot_path"]+"/etc/make.profile",\
866                                 "Error creating profile link",env=self.env)
867                         touch(self.settings["autoresume_path"]+"config_profile_link")
868
869         def setup_confdir(self):
870                 if self.settings.has_key("AUTORESUME") \
871                         and os.path.exists(self.settings["autoresume_path"]+\
872                                 "setup_confdir"):
873                         print "Resume point detected, skipping setup_confdir operation..."
874                 else:
875                         if self.settings.has_key("portage_confdir"):
876                                 print "Configuring /etc/portage..."
877                                 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
878                                         "Error zapping /etc/portage",env=self.env)
879                                 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
880                                         self.settings["chroot_path"]+"/etc/portage",\
881                                         "Error copying /etc/portage",env=self.env)
882                                 touch(self.settings["autoresume_path"]+"setup_confdir")
883
884         def portage_overlay(self):
885                 """ We copy the contents of our overlays to /usr/local/portage """
886                 if self.settings.has_key("portage_overlay"):
887                         for x in self.settings["portage_overlay"]: 
888                                 if os.path.exists(x):
889                                         print "Copying overlay dir " +x
890                                         cmd("mkdir -p "+self.settings["chroot_path"]+\
891                                                 "/usr/local/portage",\
892                                                 "Could not make portage_overlay dir",env=self.env)
893                                         cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
894                                                 "/usr/local/portage",\
895                                                 "Could not copy portage_overlay",env=self.env)
896
897         def root_overlay(self):
898                 """ Copy over the root_overlay """
899                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
900                         for x in self.settings[self.settings["spec_prefix"]+\
901                                 "/root_overlay"]: 
902                                 if os.path.exists(x):
903                                         print "Copying root_overlay: "+x
904                                         cmd("rsync -a "+x+"/ "+\
905                                                 self.settings["chroot_path"],\
906                                                 self.settings["spec_prefix"]+"/root_overlay: "+x+\
907                                                 " copy failed.",env=self.env)
908
909         def base_dirs(self):
910                 pass
911
912         def bind(self):
913                 for x in self.mounts: 
914                         if not os.path.exists(self.settings["chroot_path"]+x):
915                                 os.makedirs(self.settings["chroot_path"]+x,0755)
916
917                         if not os.path.exists(self.mountmap[x]):
918                                 os.makedirs(self.mountmap[x],0755)
919
920                         src=self.mountmap[x]
921                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
922                                 self.snapshot_lock_object.read_lock()
923                         if os.uname()[0] == "FreeBSD":
924                                 if src == "/dev":
925                                         retval=os.system("mount -t devfs none "+\
926                                                 self.settings["chroot_path"]+x)
927                                 else:
928                                         retval=os.system("mount_nullfs "+src+" "+\
929                                                 self.settings["chroot_path"]+x)
930                         else:
931                                 retval=os.system("mount --bind "+src+" "+\
932                                         self.settings["chroot_path"]+x)
933                         if retval!=0:
934                                 self.unbind()
935                                 raise CatalystError,"Couldn't bind mount "+src
936
937         def unbind(self):
938                 ouch=0
939                 mypath=self.settings["chroot_path"]
940                 myrevmounts=self.mounts[:]
941                 myrevmounts.reverse()
942                 """ Unmount in reverse order for nested bind-mounts """
943                 for x in myrevmounts:
944                         if not os.path.exists(mypath+x):
945                                 continue
946
947                         if not ismount(mypath+x):
948                                 continue
949
950                         retval=os.system("umount "+\
951                                 os.path.join(mypath,x.lstrip(os.path.sep)))
952
953                         if retval!=0:
954                                 warn("First attempt to unmount: "+mypath+x+" failed.")
955                                 warn("Killing any pids still running in the chroot")
956
957                                 self.kill_chroot_pids()
958
959                                 retval2=os.system("umount "+mypath+x)
960                                 if retval2!=0:
961                                         ouch=1
962                                         warn("Couldn't umount bind mount: "+mypath+x)
963
964                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
965                                 try:
966                                         """
967                                         It's possible the snapshot lock object isn't created yet.
968                                         This is because mount safety check calls unbind before the
969                                         target is fully initialized
970                                         """
971                                         self.snapshot_lock_object.unlock()
972                                 except:
973                                         pass
974                 if ouch:
975                         """
976                         if any bind mounts really failed, then we need to raise
977                         this to potentially prevent an upcoming bash stage cleanup script
978                         from wiping our bind mounts.
979                         """
980                         raise CatalystError,\
981                                 "Couldn't umount one or more bind-mounts; aborting for safety."
982
983         def chroot_setup(self):
984                 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
985                         "/etc/make.conf")
986                 self.override_cbuild()
987                 self.override_chost()
988                 self.override_cflags()
989                 self.override_cxxflags()        
990                 self.override_ldflags() 
991                 if self.settings.has_key("AUTORESUME") \
992                         and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
993                         print "Resume point detected, skipping chroot_setup operation..."
994                 else:
995                         print "Setting up chroot..."
996                         
997                         #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
998                         
999                         cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1000                                 "Could not copy resolv.conf into place.",env=self.env)
1001                 
1002                         """ Copy over the envscript, if applicable """
1003                         if self.settings.has_key("ENVSCRIPT"):
1004                                 if not os.path.exists(self.settings["ENVSCRIPT"]):
1005                                         raise CatalystError,\
1006                                                 "Can't find envscript "+self.settings["ENVSCRIPT"]
1007
1008                                 print "\nWarning!!!!"
1009                                 print "\tOverriding certain env variables may cause catastrophic failure."
1010                                 print "\tIf your build fails look here first as the possible problem."
1011                                 print "\tCatalyst assumes you know what you are doing when setting"
1012                                 print "\t\tthese variables."
1013                                 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1014                                 print "\tYou have been warned\n"
1015
1016                                 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1017                                         self.settings["chroot_path"]+"/tmp/envscript",\
1018                                         "Could not copy envscript into place.",env=self.env)
1019
1020                         """ Setup metadata_overlay """
1021                         if self.settings.has_key("METADATA_OVERLAY") \
1022                                 and not self.settings.has_key("portage_confdir"):
1023                                 if not os.path.exists(self.settings["chroot_path"]+\
1024                                         "/etc/portage"):
1025                                         cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
1026                                 myf=open(self.settings["chroot_path"]+\
1027                                         "/etc/portage/modules","a")
1028                                 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
1029                                 myf.close()
1030
1031
1032                         """
1033                         Copy over /etc/hosts from the host in case there are any
1034                         specialties in there
1035                         """
1036                         if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1037                                 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1038                                         self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1039                                         "Could not backup /etc/hosts",env=self.env)
1040                                 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1041                                         "Could not copy /etc/hosts",env=self.env)
1042
1043                         """ Modify and write out make.conf (for the chroot) """
1044                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
1045                                 "Could not remove "+self.settings["chroot_path"]+\
1046                                 "/etc/make.conf",env=self.env)
1047                         myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1048                         myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1049                         myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1050                         if self.settings.has_key("CFLAGS"):
1051                                 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1052                         if self.settings.has_key("CXXFLAGS"):
1053                                 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1054                         else:
1055                                 myf.write('CXXFLAGS="${CFLAGS}"\n')
1056
1057                         if self.settings.has_key("LDFLAGS"):
1058                                 myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
1059                                 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1060                         if self.settings.has_key("CBUILD"):
1061                                 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")
1062                                 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1063
1064                         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")
1065                         myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1066
1067                         """ Figure out what our USE vars are for building """
1068                         myusevars=[]
1069                         if self.settings.has_key("HOSTUSE"):
1070                                 myusevars.extend(self.settings["HOSTUSE"])
1071
1072                         if self.settings.has_key("use"):
1073                                 myusevars.extend(self.settings["use"])
1074
1075                         if myusevars:
1076                                 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1077                                 myusevars = sorted(set(myusevars))
1078                                 myf.write('USE="'+string.join(myusevars)+'"\n')
1079                                 if '-*' in myusevars:
1080                                         print "\nWarning!!!  "
1081                                         print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1082                                                 "/use will cause portage to ignore"
1083                                         print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1084
1085                         """ Setup the portage overlay """
1086                         if self.settings.has_key("portage_overlay"):
1087                                 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1088
1089                         myf.close()
1090                         cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1091                                 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1092                                 "Could not backup /etc/make.conf",env=self.env)
1093                         touch(self.settings["autoresume_path"]+"chroot_setup")
1094
1095         def fsscript(self):
1096                 if self.settings.has_key("AUTORESUME") \
1097                         and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1098                         print "Resume point detected, skipping fsscript operation..."
1099                 else:
1100                         if self.settings.has_key("fsscript"):
1101                                 if os.path.exists(self.settings["controller_file"]):
1102                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1103                                                 " fsscript","fsscript script failed.",env=self.env)
1104                                         touch(self.settings["autoresume_path"]+"fsscript")
1105
1106         def rcupdate(self):
1107                 if self.settings.has_key("AUTORESUME") \
1108                         and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1109                         print "Resume point detected, skipping rcupdate operation..."
1110                 else:
1111                         if os.path.exists(self.settings["controller_file"]):
1112                                 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1113                                         "rc-update script failed.",env=self.env)
1114                                 touch(self.settings["autoresume_path"]+"rcupdate")
1115
1116         def clean(self):
1117                 if self.settings.has_key("AUTORESUME") \
1118                         and os.path.exists(self.settings["autoresume_path"]+"clean"):
1119                         print "Resume point detected, skipping clean operation..."
1120                 else:
1121                         for x in self.settings["cleanables"]: 
1122                                 print "Cleaning chroot: "+x+"... "
1123                                 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1124                                         x,env=self.env)
1125
1126                 """ Put /etc/hosts back into place """
1127                 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1128                         cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1129                                 self.settings["chroot_path"]+"/etc/hosts",\
1130                                 "Could not replace /etc/hosts",env=self.env)
1131
1132                 """ Remove our overlay """
1133                 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1134                         cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1135                                 "Could not remove /usr/local/portage",env=self.env)
1136                         cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1137                                 "/etc/make.conf",\
1138                                 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1139
1140                 """ Clean up old and obsoleted files in /etc """
1141                 if os.path.exists(self.settings["stage_path"]+"/etc"):
1142                         cmd("find "+self.settings["stage_path"]+\
1143                                 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1144                                 "Could not remove stray files in /etc",env=self.env)
1145
1146                 if os.path.exists(self.settings["controller_file"]):
1147                         cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1148                                 "clean script failed.",env=self.env)
1149                         touch(self.settings["autoresume_path"]+"clean")
1150
1151         def empty(self):
1152                 if self.settings.has_key("AUTORESUME") \
1153                         and os.path.exists(self.settings["autoresume_path"]+"empty"):
1154                         print "Resume point detected, skipping empty operation..."
1155                 else:
1156                         if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1157                                 if type(self.settings[self.settings["spec_prefix"]+\
1158                                         "/empty"])==types.StringType:
1159                                         self.settings[self.settings["spec_prefix"]+"/empty"]=\
1160                                                 self.settings[self.settings["spec_prefix"]+\
1161                                                 "/empty"].split()
1162                                 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1163                                         myemp=self.settings["destpath"]+x
1164                                         if not os.path.isdir(myemp):
1165                                                 print x,"not a directory or does not exist, skipping 'empty' operation."
1166                                                 continue
1167                                         print "Emptying directory",x
1168                                         """ 
1169                                         stat the dir, delete the dir, recreate the dir and set
1170                                         the proper perms and ownership
1171                                         """
1172                                         mystat=os.stat(myemp)
1173                                         shutil.rmtree(myemp)
1174                                         os.makedirs(myemp,0755)
1175                                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1176                                         os.chmod(myemp,mystat[ST_MODE])
1177                         touch(self.settings["autoresume_path"]+"empty")
1178
1179         def remove(self):
1180                 if self.settings.has_key("AUTORESUME") \
1181                         and os.path.exists(self.settings["autoresume_path"]+"remove"):
1182                         print "Resume point detected, skipping remove operation..."
1183                 else:
1184                         if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1185                                 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1186                                         """
1187                                         We're going to shell out for all these cleaning
1188                                         operations, so we get easy glob handling.
1189                                         """
1190                                         print "livecd: removing "+x
1191                                         os.system("rm -rf "+self.settings["chroot_path"]+x)
1192                                 try:
1193                                         if os.path.exists(self.settings["controller_file"]):
1194                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1195                                                         " clean","Clean  failed.",env=self.env)
1196                                                 touch(self.settings["autoresume_path"]+"remove")
1197                                 except:
1198                                         self.unbind()
1199                                         raise
1200
1201         def preclean(self):
1202                 if self.settings.has_key("AUTORESUME") \
1203                         and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1204                         print "Resume point detected, skipping preclean operation..."
1205                 else:
1206                         try:
1207                                 if os.path.exists(self.settings["controller_file"]):
1208                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1209                                                 " preclean","preclean script failed.",env=self.env)
1210                                         touch(self.settings["autoresume_path"]+"preclean")
1211                 
1212                         except:
1213                                 self.unbind()
1214                                 raise CatalystError, "Build failed, could not execute preclean"
1215
1216         def capture(self):
1217                 if self.settings.has_key("AUTORESUME") \
1218                         and os.path.exists(self.settings["autoresume_path"]+"capture"):
1219                         print "Resume point detected, skipping capture operation..."
1220                 else:
1221                         """ Capture target in a tarball """
1222                         mypath=self.settings["target_path"].split("/")
1223                         """ Remove filename from path """
1224                         mypath=string.join(mypath[:-1],"/")
1225
1226                         """ Now make sure path exists """
1227                         if not os.path.exists(mypath):
1228                                 os.makedirs(mypath)
1229
1230                         print "Creating stage tarball..."
1231
1232                         cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1233                                 self.settings["stage_path"]+" .",\
1234                                 "Couldn't create stage tarball",env=self.env)
1235
1236                         self.gen_contents_file(self.settings["target_path"])
1237                         self.gen_digest_file(self.settings["target_path"])
1238
1239                         touch(self.settings["autoresume_path"]+"capture")
1240
1241         def run_local(self):
1242                 if self.settings.has_key("AUTORESUME") \
1243                         and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1244                         print "Resume point detected, skipping run_local operation..."
1245                 else:
1246                         try:
1247                                 if os.path.exists(self.settings["controller_file"]):
1248                                         cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1249                                                 "run script failed.",env=self.env)
1250                                         touch(self.settings["autoresume_path"]+"run_local")
1251
1252                         except CatalystError:
1253                                 self.unbind()
1254                                 raise CatalystError,"Stage build aborting due to error."
1255
1256         def setup_environment(self):
1257                 """
1258                 Modify the current environment. This is an ugly hack that should be
1259                 fixed. We need this to use the os.system() call since we can't
1260                 specify our own environ
1261                 """
1262                 for x in self.settings.keys():
1263                         """ Sanitize var names by doing "s|/-.|_|g" """
1264                         varname="clst_"+string.replace(x,"/","_")
1265                         varname=string.replace(varname,"-","_")
1266                         varname=string.replace(varname,".","_")
1267                         if type(self.settings[x])==types.StringType:
1268                                 """ Prefix to prevent namespace clashes """
1269                                 #os.environ[varname]=self.settings[x]
1270                                 self.env[varname]=self.settings[x]
1271                         elif type(self.settings[x])==types.ListType:
1272                                 #os.environ[varname]=string.join(self.settings[x])
1273                                 self.env[varname]=string.join(self.settings[x])
1274                         elif type(self.settings[x])==types.BooleanType:
1275                                 if self.settings[x]:
1276                                         self.env[varname]="true"
1277                                 else:
1278                                         self.env[varname]="false"
1279                 if self.settings.has_key("makeopts"):
1280                         self.env["MAKEOPTS"]=self.settings["makeopts"]
1281
1282         def run(self):
1283                 self.chroot_lock.write_lock()
1284
1285                 """ Kill any pids in the chroot "" """
1286                 self.kill_chroot_pids()
1287
1288                 """ Check for mounts right away and abort if we cannot unmount them """
1289                 self.mount_safety_check()
1290
1291                 if self.settings.has_key("CLEAR_AUTORESUME"):
1292                         self.clear_autoresume()
1293                 if self.settings.has_key("PURGE"):
1294                         self.purge()
1295
1296                 for x in self.settings["action_sequence"]:
1297                         print "--- Running action sequence: "+x
1298                         sys.stdout.flush()
1299                         try:
1300                                 apply(getattr(self,x))
1301                         except:
1302                                 self.mount_safety_check()
1303                                 raise
1304                 
1305                 self.chroot_lock.unlock()
1306
1307         def unmerge(self):
1308                 if self.settings.has_key("AUTORESUME") \
1309                         and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1310                         print "Resume point detected, skipping unmerge operation..."
1311                 else:
1312                         if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1313                                 if type(self.settings[self.settings["spec_prefix"]+\
1314                                         "/unmerge"])==types.StringType:
1315                                         self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1316                                                 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1317                                 myunmerge=\
1318                                         self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1319
1320                                 for x in range(0,len(myunmerge)):
1321                                         """
1322                                         Surround args with quotes for passing to bash, allows
1323                                         things like "<" to remain intact
1324                                         """
1325                                         myunmerge[x]="'"+myunmerge[x]+"'"
1326                                 myunmerge=string.join(myunmerge)
1327
1328                                 """ Before cleaning, unmerge stuff """
1329                                 try:
1330                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1331                                                 " unmerge "+ myunmerge,"Unmerge script failed.",\
1332                                                 env=self.env)
1333                                         print "unmerge shell script"
1334                                 except CatalystError:
1335                                         self.unbind()
1336                                         raise
1337                                 touch(self.settings["autoresume_path"]+"unmerge")
1338
1339         def target_setup(self):
1340                 if self.settings.has_key("AUTORESUME") \
1341                         and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1342                         print "Resume point detected, skipping target_setup operation..."
1343                 else:
1344                         print "Setting up filesystems per filesystem type"
1345                         cmd("/bin/bash "+self.settings["controller_file"]+\
1346                                 " target_image_setup "+ self.settings["target_path"],\
1347                                 "target_image_setup script failed.",env=self.env)
1348                         touch(self.settings["autoresume_path"]+"target_setup")
1349
1350         def setup_overlay(self):
1351                 if self.settings.has_key("AUTORESUME") \
1352                 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1353                         print "Resume point detected, skipping setup_overlay operation..."
1354                 else:
1355                         if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1356                                 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]: 
1357                                         if os.path.exists(x):
1358                                                 cmd("rsync -a "+x+"/ "+\
1359                                                         self.settings["target_path"],\
1360                                                         self.settings["spec_prefix"]+"overlay: "+x+\
1361                                                         " copy failed.",env=self.env)
1362                                 touch(self.settings["autoresume_path"]+"setup_overlay")
1363
1364         def create_iso(self):
1365                 if self.settings.has_key("AUTORESUME") \
1366                         and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1367                         print "Resume point detected, skipping create_iso operation..."
1368                 else:
1369                         """ Create the ISO """
1370                         if self.settings.has_key("iso"):
1371                                 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1372                                         self.settings["iso"],"ISO creation script failed.",\
1373                                         env=self.env)
1374                                 self.gen_contents_file(self.settings["iso"])
1375                                 self.gen_digest_file(self.settings["iso"])
1376                                 touch(self.settings["autoresume_path"]+"create_iso")
1377                         else:
1378                                 print "WARNING: livecd/iso was not defined."
1379                                 print "An ISO Image will not be created."
1380
1381         def build_packages(self):
1382                 if self.settings.has_key("AUTORESUME") \
1383                         and os.path.exists(self.settings["autoresume_path"]+\
1384                                 "build_packages"):
1385                         print "Resume point detected, skipping build_packages operation..."
1386                 else:
1387                         if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1388                                 if self.settings.has_key("AUTORESUME") \
1389                                         and os.path.exists(self.settings["autoresume_path"]+\
1390                                                 "build_packages"):
1391                                         print "Resume point detected, skipping build_packages operation..."
1392                                 else:
1393                                         mypack=\
1394                                                 list_bashify(self.settings[self.settings["spec_prefix"]\
1395                                                 +"/packages"])
1396                                         try:
1397                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1398                                                         " build_packages "+mypack,\
1399                                                         "Error in attempt to build packages",env=self.env)
1400                                                 touch(self.settings["autoresume_path"]+"build_packages")
1401                                         except CatalystError:
1402                                                 self.unbind()
1403                                                 raise CatalystError,self.settings["spec_prefix"]+\
1404                                                         "build aborting due to error."
1405
1406         def build_kernel(self):
1407                 if self.settings.has_key("AUTORESUME") \
1408                         and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1409                         print "Resume point detected, skipping build_kernel operation..."
1410                 else:
1411                         if self.settings.has_key("boot/kernel"):
1412                                 try:
1413                                         mynames=self.settings["boot/kernel"]
1414                                         if type(mynames)==types.StringType:
1415                                                 mynames=[mynames]
1416                                         """
1417                                         Execute the script that sets up the kernel build environment
1418                                         """
1419                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1420                                                 " pre-kmerge ","Runscript pre-kmerge failed",\
1421                                                 env=self.env)
1422
1423                                         for kname in mynames:
1424                                                 if self.settings.has_key("AUTORESUME") \
1425                                                         and os.path.exists(self.settings["autoresume_path"]\
1426                                                                 +"build_kernel_"+kname):
1427                                                         print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1428                                                 else: # TODO: make this not require a kernel config
1429                                                         try:
1430                                                                 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1431                                                                         self.unbind()
1432                                                                         raise CatalystError,\
1433                                                                                 "Can't find kernel config: "+\
1434                                                                                 self.settings["boot/kernel/"+kname+\
1435                                                                                 "/config"]
1436
1437                                                         except TypeError:
1438                                                                 raise CatalystError,\
1439                                                                         "Required value boot/kernel/config not specified"
1440
1441                                                         try:
1442                                                                 cmd("cp "+self.settings["boot/kernel/"+kname+\
1443                                                                         "/config"]+" "+\
1444                                                                         self.settings["chroot_path"]+"/var/tmp/"+\
1445                                                                         kname+".config",\
1446                                                                         "Couldn't copy kernel config: "+\
1447                                                                         self.settings["boot/kernel/"+kname+\
1448                                                                         "/config"],env=self.env)
1449
1450                                                         except CatalystError:
1451                                                                 self.unbind()
1452
1453                                                         """
1454                                                         If we need to pass special options to the bootloader
1455                                                         for this kernel put them into the environment
1456                                                         """
1457                                                         if self.settings.has_key("boot/kernel/"+kname+\
1458                                                                 "/kernelopts"):
1459                                                                 myopts=self.settings["boot/kernel/"+kname+\
1460                                                                         "/kernelopts"]
1461
1462                                                                 if type(myopts) != types.StringType:
1463                                                                         myopts = string.join(myopts)
1464                                                                         self.env[kname+"_kernelopts"]=myopts
1465
1466                                                                 else:
1467                                                                         self.env[kname+"_kernelopts"]=""
1468
1469                                                         if not self.settings.has_key("boot/kernel/"+kname+\
1470                                                                 "/extraversion"):
1471                                                                 self.settings["boot/kernel/"+kname+\
1472                                                                         "/extraversion"]=""
1473
1474                                                         self.env["clst_kextraversion"]=\
1475                                                                 self.settings["boot/kernel/"+kname+\
1476                                                                 "/extraversion"]
1477
1478                                                         if self.settings.has_key("boot/kernel/"+kname+\
1479                                                                 "/initramfs_overlay"):
1480                                                                 if os.path.exists(self.settings["boot/kernel/"+\
1481                                                                         kname+"/initramfs_overlay"]):
1482                                                                         print "Copying initramfs_overlay dir "+\
1483                                                                                 self.settings["boot/kernel/"+kname+\
1484                                                                                 "/initramfs_overlay"]
1485
1486                                                                         cmd("mkdir -p "+\
1487                                                                                 self.settings["chroot_path"]+\
1488                                                                                 "/tmp/initramfs_overlay/"+\
1489                                                                                 self.settings["boot/kernel/"+kname+\
1490                                                                                 "/initramfs_overlay"],env=self.env)
1491
1492                                                                         cmd("cp -R "+self.settings["boot/kernel/"+\
1493                                                                                 kname+"/initramfs_overlay"]+"/* "+\
1494                                                                                 self.settings["chroot_path"]+\
1495                                                                                 "/tmp/initramfs_overlay/"+\
1496                                                                                 self.settings["boot/kernel/"+kname+\
1497                                                                                 "/initramfs_overlay"],env=self.env)
1498
1499                                                         """ Execute the script that builds the kernel """
1500                                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1501                                                                 " kernel "+kname,\
1502                                                                 "Runscript kernel build failed",env=self.env)
1503
1504                                                         if self.settings.has_key("boot/kernel/"+kname+\
1505                                                                 "/initramfs_overlay"):
1506                                                                 if os.path.exists(self.settings["chroot_path"]+\
1507                                                                         "/tmp/initramfs_overlay/"):
1508                                                                         print "Cleaning up temporary overlay dir"
1509                                                                         cmd("rm -R "+self.settings["chroot_path"]+\
1510                                                                                 "/tmp/initramfs_overlay/",env=self.env)
1511
1512                                                         touch(self.settings["autoresume_path"]+\
1513                                                                 "build_kernel_"+kname)
1514
1515                                                         """
1516                                                         Execute the script that cleans up the kernel build
1517                                                         environment
1518                                                         """
1519                                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1520                                                                 " post-kmerge ",
1521                                                                 "Runscript post-kmerge failed",env=self.env)
1522
1523                                         touch(self.settings["autoresume_path"]+"build_kernel")
1524
1525                                 except CatalystError:
1526                                         self.unbind()
1527                                         raise CatalystError,\
1528                                                 "build aborting due to kernel build error."
1529
1530         def bootloader(self):
1531                 if self.settings.has_key("AUTORESUME") \
1532                         and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1533                         print "Resume point detected, skipping bootloader operation..."
1534                 else:
1535                         try:
1536                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1537                                         " bootloader " + self.settings["target_path"],\
1538                                         "Bootloader runscript failed.",env=self.env)
1539                                 touch(self.settings["autoresume_path"]+"bootloader")
1540                         except CatalystError:
1541                                 self.unbind()
1542                                 raise CatalystError,"Runscript aborting due to error."
1543
1544         def livecd_update(self):
1545                 if self.settings.has_key("AUTORESUME") \
1546                         and os.path.exists(self.settings["autoresume_path"]+\
1547                                 "livecd_update"):
1548                         print "Resume point detected, skipping build_packages operation..."
1549                 else:
1550                         try:
1551                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1552                                         " livecd-update","livecd-update failed.",env=self.env)
1553                                 touch(self.settings["autoresume_path"]+"livecd_update")
1554
1555                         except CatalystError:
1556                                 self.unbind()
1557                                 raise CatalystError,"build aborting due to livecd_update error."
1558
1559         def clear_chroot(self):
1560                 myemp=self.settings["chroot_path"]
1561                 if os.path.isdir(myemp):
1562                         print "Emptying directory",myemp
1563                         """
1564                         stat the dir, delete the dir, recreate the dir and set
1565                         the proper perms and ownership
1566                         """
1567                         mystat=os.stat(myemp)
1568                         #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1569                         """ There's no easy way to change flags recursively in python """
1570                         if os.uname()[0] == "FreeBSD":
1571                                 os.system("chflags -R noschg "+myemp)
1572                         shutil.rmtree(myemp)
1573                         os.makedirs(myemp,0755)
1574                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1575                         os.chmod(myemp,mystat[ST_MODE])
1576
1577         def clear_packages(self):
1578                 if self.settings.has_key("PKGCACHE"):
1579                         print "purging the pkgcache ..."
1580
1581                         myemp=self.settings["pkgcache_path"]
1582                         if os.path.isdir(myemp):
1583                                 print "Emptying directory",myemp
1584                                 """
1585                                 stat the dir, delete the dir, recreate the dir and set
1586                                 the proper perms and ownership
1587                                 """
1588                                 mystat=os.stat(myemp)
1589                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1590                                 shutil.rmtree(myemp)
1591                                 os.makedirs(myemp,0755)
1592                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1593                                 os.chmod(myemp,mystat[ST_MODE])
1594
1595         def clear_kerncache(self):
1596                 if self.settings.has_key("KERNCACHE"):
1597                         print "purging the kerncache ..."
1598
1599                         myemp=self.settings["kerncache_path"]
1600                         if os.path.isdir(myemp):
1601                                 print "Emptying directory",myemp
1602                                 """
1603                                 stat the dir, delete the dir, recreate the dir and set
1604                                 the proper perms and ownership
1605                                 """
1606                                 mystat=os.stat(myemp)
1607                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1608                                 shutil.rmtree(myemp)
1609                                 os.makedirs(myemp,0755)
1610                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1611                                 os.chmod(myemp,mystat[ST_MODE])
1612
1613         def clear_autoresume(self):
1614                 """ Clean resume points since they are no longer needed """
1615                 if self.settings.has_key("AUTORESUME"):
1616                         print "Removing AutoResume Points: ..."
1617                 myemp=self.settings["autoresume_path"]
1618                 if os.path.isdir(myemp):
1619                                 if self.settings.has_key("AUTORESUME"):
1620                                         print "Emptying directory",myemp
1621                                 """
1622                                 stat the dir, delete the dir, recreate the dir and set
1623                                 the proper perms and ownership
1624                                 """
1625                                 mystat=os.stat(myemp)
1626                                 if os.uname()[0] == "FreeBSD":
1627                                         cmd("chflags -R noschg "+myemp,\
1628                                                 "Could not remove immutable flag for file "\
1629                                                 +myemp)
1630                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1631                                 shutil.rmtree(myemp)
1632                                 os.makedirs(myemp,0755)
1633                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1634                                 os.chmod(myemp,mystat[ST_MODE])
1635
1636         def gen_contents_file(self,file):
1637                 if os.path.exists(file+".CONTENTS"):
1638                         os.remove(file+".CONTENTS")
1639                 if self.settings.has_key("contents"):
1640                         if os.path.exists(file):
1641                                 myf=open(file+".CONTENTS","w")
1642                                 keys={}
1643                                 for i in self.settings["contents"].split():
1644                                         keys[i]=1
1645                                         array=keys.keys()
1646                                         array.sort()
1647                                 for j in array:
1648                                         contents=generate_contents(file,contents_function=j,\
1649                                                 verbose=self.settings.has_key("VERBOSE"))
1650                                         if contents:
1651                                                 myf.write(contents)
1652                                 myf.close()
1653
1654         def gen_digest_file(self,file):
1655                 if os.path.exists(file+".DIGESTS"):
1656                         os.remove(file+".DIGESTS")
1657                 if self.settings.has_key("digests"):
1658                         if os.path.exists(file):
1659                                 myf=open(file+".DIGESTS","w")
1660                                 keys={}
1661                                 for i in self.settings["digests"].split():
1662                                         keys[i]=1
1663                                         array=keys.keys()
1664                                         array.sort()
1665                                 for f in [file, file+'.CONTENTS']:
1666                                         if os.path.exists(f):
1667                                                 for j in array:
1668                                                         hash=generate_hash(f,hash_function=j,verbose=\
1669                                                                 self.settings.has_key("VERBOSE"))
1670                                                         myf.write(hash)
1671                                 myf.close()
1672
1673         def purge(self):
1674                 countdown(10,"Purging Caches ...")
1675                 if self.settings.has_key("PURGE"):
1676                         print "clearing autoresume ..."
1677                         self.clear_autoresume()
1678
1679                         print "clearing chroot ..."
1680                         self.clear_chroot()
1681
1682                         print "clearing package cache ..."
1683                         self.clear_packages()
1684
1685                         print "clearing kerncache ..."
1686                         self.clear_kerncache()
1687
1688 # vim: ts=4 sw=4 sta et sts=4 ai