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