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