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