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