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