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