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