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