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