livecdfs-update.sh: Escape ampersands in STARTX sed expression
[catalyst.git] / modules / generic_stage_target.py
index c4e81d14b0b9ada6edb680cfe75917c92a86faaa..31cb025e6745a3858acacdf583d6df7dbaaf330c 100644 (file)
@@ -1,16 +1,14 @@
-
-"""
-This class does all of the chroot setup, copying of files, etc. It is
-the driver class for pretty much everything that Catalyst does.
-"""
-
 import os,string,imp,types,shutil
 from catalyst_support import *
 from generic_target import *
 from stat import *
 import catalyst_lock
-class generic_stage_target(generic_target):
 
+class generic_stage_target(generic_target):
+       """
+       This class does all of the chroot setup, copying of files, etc. It is
+       the driver class for pretty much everything that Catalyst does.
+       """
        def __init__(self,myspec,addlargs):
                self.required_values.extend(["version_stamp","target","subarch",\
                        "rel_type","profile","snapshot","source_subpath"])
@@ -80,21 +78,21 @@ class generic_stage_target(generic_target):
                                msg("Can't find/load "+x+".py plugin in "+\
                                        self.settings["sharedir"]+"/arch/")
 
-               if self.settings.has_key("chost"):
+               if "chost" in self.settings:
                        hostmachine = self.settings["chost"].split("-")[0]
-                       if not machinemap.has_key(hostmachine):
+                       if hostmachine not in machinemap:
                                raise CatalystError, "Unknown host machine type "+hostmachine
                        self.settings["hostarch"]=machinemap[hostmachine]
                else:
                        hostmachine = self.settings["subarch"]
-                       if machinemap.has_key(hostmachine):
+                       if hostmachine in machinemap:
                                hostmachine = machinemap[hostmachine]
                        self.settings["hostarch"]=hostmachine
-               if self.settings.has_key("cbuild"):
+               if "cbuild" in self.settings:
                        buildmachine = self.settings["cbuild"].split("-")[0]
                else:
                        buildmachine = os.uname()[4]
-               if not machinemap.has_key(buildmachine):
+               if buildmachine not in machinemap:
                        raise CatalystError, "Unknown build machine type "+buildmachine
                self.settings["buildarch"]=machinemap[buildmachine]
                self.settings["crosscompile"]=(self.settings["hostarch"]!=\
@@ -148,9 +146,6 @@ class generic_stage_target(generic_target):
                self.set_iso_volume_id()
                self.set_build_kernel_vars()
                self.set_fsscript()
-               # TODO: Remove archscript/runscript from next major version
-               self.set_archscript()
-               self.set_runscript()
                self.set_install_mask()
                self.set_rcadd()
                self.set_rcdel()
@@ -161,6 +156,7 @@ class generic_stage_target(generic_target):
                self.set_packages()
                self.set_rm()
                self.set_linuxrc()
+               self.set_busybox_config()
                self.set_overlay()
                self.set_portage_overlay()
                self.set_root_overlay()
@@ -173,19 +169,19 @@ class generic_stage_target(generic_target):
                file_locate(self.settings,["source_path","snapshot_path","distdir"],\
                        expand=0)
                """ If we are using portage_confdir, check that as well. """
-               if self.settings.has_key("portage_confdir"):
+               if "portage_confdir" in self.settings:
                        file_locate(self.settings,["portage_confdir"],expand=0)
 
                """ Setup our mount points """
-               if self.settings.has_key("SNAPCACHE"):
-                       self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
+               if "SNAPCACHE" in self.settings:
+                       self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles","/var/tmp/portage"]
                        self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
                                "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
-                               "/usr/portage/distfiles":self.settings["distdir"]}
+                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
                else:
-                       self.mounts=["/proc","/dev","/usr/portage/distfiles"]
+                       self.mounts=["/proc","/dev","/usr/portage/distfiles","/var/tmp/portage"]
                        self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
-                               "/usr/portage/distfiles":self.settings["distdir"]}
+                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
                if os.uname()[0] == "Linux":
                        self.mounts.append("/dev/pts")
 
@@ -195,7 +191,7 @@ class generic_stage_target(generic_target):
                Configure any user specified options (either in catalyst.conf or on
                the command line).
                """
-               if self.settings.has_key("PKGCACHE"):
+               if "PKGCACHE" in self.settings:
                        self.set_pkgcache_path()
                        print "Location of the package cache is "+\
                                self.settings["pkgcache_path"]
@@ -203,15 +199,15 @@ class generic_stage_target(generic_target):
                        self.mountmap["/usr/portage/packages"]=\
                                self.settings["pkgcache_path"]
 
-               if self.settings.has_key("KERNCACHE"):
+               if "KERNCACHE" in self.settings:
                        self.set_kerncache_path()
                        print "Location of the kerncache is "+\
                                self.settings["kerncache_path"]
                        self.mounts.append("/tmp/kerncache")
                        self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
 
-               if self.settings.has_key("CCACHE"):
-                       if os.environ.has_key("CCACHE_DIR"):
+               if "CCACHE" in self.settings:
+                       if "CCACHE_DIR" in os.environ:
                                ccdir=os.environ["CCACHE_DIR"]
                                del os.environ["CCACHE_DIR"]
                        else:
@@ -225,33 +221,39 @@ class generic_stage_target(generic_target):
                        """ for the chroot: """
                        self.env["CCACHE_DIR"]="/var/tmp/ccache"
 
-               if self.settings.has_key("ICECREAM"):
+               if "ICECREAM" in self.settings:
                        self.mounts.append("/var/cache/icecream")
                        self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
                        self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
 
+               if "port_logdir" in self.settings:
+                       self.mounts.append("/var/log/portage")
+                       self.mountmap["/var/log/portage"]=self.settings["port_logdir"]
+                       self.env["PORT_LOGDIR"]="/var/log/portage"
+                       self.env["PORT_LOGDIR_CLEAN"]='find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
+
        def override_cbuild(self):
-               if self.makeconf.has_key("CBUILD"):
+               if "CBUILD" in self.makeconf:
                        self.settings["CBUILD"]=self.makeconf["CBUILD"]
 
        def override_chost(self):
-               if self.makeconf.has_key("CHOST"):
+               if "CHOST" in self.makeconf:
                        self.settings["CHOST"]=self.makeconf["CHOST"]
 
        def override_cflags(self):
-               if self.makeconf.has_key("CFLAGS"):
+               if "CFLAGS" in self.makeconf:
                        self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
 
        def override_cxxflags(self):
-               if self.makeconf.has_key("CXXFLAGS"):
+               if "CXXFLAGS" in self.makeconf:
                        self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
 
        def override_ldflags(self):
-               if self.makeconf.has_key("LDFLAGS"):
+               if "LDFLAGS" in self.makeconf:
                        self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
 
        def set_install_mask(self):
-               if self.settings.has_key("install_mask"):
+               if "install_mask" in self.settings:
                        if type(self.settings["install_mask"])!=types.StringType:
                                self.settings["install_mask"]=\
                                        string.join(self.settings["install_mask"])
@@ -273,7 +275,7 @@ class generic_stage_target(generic_target):
                                "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
 
        def set_pkgcache_path(self):
-               if self.settings.has_key("pkgcache_path"):
+               if "pkgcache_path" in self.settings:
                        if type(self.settings["pkgcache_path"])!=types.StringType:
                                self.settings["pkgcache_path"]=\
                                        normpath(string.join(self.settings["pkgcache_path"]))
@@ -283,7 +285,7 @@ class generic_stage_target(generic_target):
                                self.settings["target_subpath"]+"/")
 
        def set_kerncache_path(self):
-               if self.settings.has_key("kerncache_path"):
+               if "kerncache_path" in self.settings:
                        if type(self.settings["kerncache_path"])!=types.StringType:
                                self.settings["kerncache_path"]=\
                                        normpath(string.join(self.settings["kerncache_path"]))
@@ -294,103 +296,85 @@ class generic_stage_target(generic_target):
        def set_target_path(self):
                self.settings["target_path"]=normpath(self.settings["storedir"]+\
                        "/builds/"+self.settings["target_subpath"]+".tar.bz2")
-               if self.settings.has_key("AUTORESUME")\
+               if "AUTORESUME" in self.settings\
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "setup_target_path"):
                        print \
                                "Resume point detected, skipping target path setup operation..."
                else:
                        """ First clean up any existing target stuff """
-                       if os.path.isfile(self.settings["target_path"]):
-                               cmd("rm -f "+self.settings["target_path"],\
-                                       "Could not remove existing file: "\
-                                       +self.settings["target_path"],env=self.env)
-                               touch(self.settings["autoresume_path"]+"setup_target_path")
+                       # XXX WTF are we removing the old tarball before we start building the
+                       # XXX new one? If the build fails, you don't want to be left with
+                       # XXX nothing at all
+#                      if os.path.isfile(self.settings["target_path"]):
+#                              cmd("rm -f "+self.settings["target_path"],\
+#                                      "Could not remove existing file: "\
+#                                      +self.settings["target_path"],env=self.env)
+                       touch(self.settings["autoresume_path"]+"setup_target_path")
 
                        if not os.path.exists(self.settings["storedir"]+"/builds/"):
                                os.makedirs(self.settings["storedir"]+"/builds/")
 
-       def set_archscript(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/archscript"):
-                       # TODO: remove this warning/code with the next major version
-                       print "\nWarning!!!  "
-                       print "\t"+self.settings["spec_prefix"]+"/archscript"+\
-                               " is deprecated and no longer used.\n"
-
-       def set_runscript(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/runscript"):
-                       # TODO: remove this warning/code with the next major version
-                       print "\nWarning!!!  "
-                       print "\t"+self.settings["spec_prefix"]+"/runscript"+\
-                               " is deprecated and no longer used.\n"
-
        def set_fsscript(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
+               if self.settings["spec_prefix"]+"/fsscript" in self.settings:
                        self.settings["fsscript"]=\
                                self.settings[self.settings["spec_prefix"]+"/fsscript"]
                        del self.settings[self.settings["spec_prefix"]+"/fsscript"]
 
        def set_rcadd(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
+               if self.settings["spec_prefix"]+"/rcadd" in self.settings:
                        self.settings["rcadd"]=\
                                self.settings[self.settings["spec_prefix"]+"/rcadd"]
                        del self.settings[self.settings["spec_prefix"]+"/rcadd"]
 
        def set_rcdel(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
+               if self.settings["spec_prefix"]+"/rcdel" in self.settings:
                        self.settings["rcdel"]=\
                                self.settings[self.settings["spec_prefix"]+"/rcdel"]
                        del self.settings[self.settings["spec_prefix"]+"/rcdel"]
 
        def set_cdtar(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
+               if self.settings["spec_prefix"]+"/cdtar" in self.settings:
                        self.settings["cdtar"]=\
                                normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
                        del self.settings[self.settings["spec_prefix"]+"/cdtar"]
 
        def set_iso(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
-                       self.settings["iso"]=\
-                               normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
+               if self.settings["spec_prefix"]+"/iso" in self.settings:
+                       if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
+                               self.settings["iso"]=\
+                                       normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
+                       else:
+                               # This automatically prepends the build dir to the ISO output path
+                               # if it doesn't start with a /
+                               self.settings["iso"] = normpath(self.settings["storedir"] + \
+                                       "/builds/" + self.settings["rel_type"] + "/" + \
+                                       self.settings[self.settings["spec_prefix"]+"/iso"])
                        del self.settings[self.settings["spec_prefix"]+"/iso"]
 
        def set_fstype(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/cdfstype"):
-                       # TODO: remove this warning/code with the next major version
-                       print "\nWarning!!!  "
-                       print self.settings["spec_prefix"]+"/cdfstype"+\
-                               " is deprecated and will be removed."
-                       print "\tUse "+self.settings["spec_prefix"]+"/fstype"+" instead."
-                       print "\tConverting to "+self.settings["spec_prefix"]+"/fstype"+\
-                               " internally."
-                       print "\tContinuing ....\n"
-                       self.settings["fstype"]=\
-                               self.settings[self.settings["spec_prefix"]+"/cdfstype"]
-                       del self.settings[self.settings["spec_prefix"]+"/cdfstype"]
-
-               if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
+               if self.settings["spec_prefix"]+"/fstype" in self.settings:
                        self.settings["fstype"]=\
                                self.settings[self.settings["spec_prefix"]+"/fstype"]
                        del self.settings[self.settings["spec_prefix"]+"/fstype"]
 
-               if not self.settings.has_key("fstype"):
+               if "fstype" not in self.settings:
                        self.settings["fstype"]="normal"
                        for x in self.valid_values:
-                               if x ==  self.settings["spec_prefix"]+"/fstype"\
-                                       or x == self.settings["spec_prefix"]+"/cdfstype":
+                               if x ==  self.settings["spec_prefix"]+"/fstype":
                                        print "\n"+self.settings["spec_prefix"]+\
                                                "/fstype is being set to the default of \"normal\"\n"
 
        def set_fsops(self):
-               if self.settings.has_key("fstype"):
+               if "fstype" in self.settings:
                        self.valid_values.append("fsops")
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
+                       if self.settings["spec_prefix"]+"/fsops" in self.settings:
                                self.settings["fsops"]=\
                                        self.settings[self.settings["spec_prefix"]+"/fsops"]
                                del self.settings[self.settings["spec_prefix"]+"/fsops"]
 
        def set_source_path(self):
-               if self.settings.has_key("SEEDCACHE")\
+               if "SEEDCACHE" in self.settings\
                        and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
                                self.settings["source_subpath"]+"/")):
                        self.settings["source_path"]=normpath(self.settings["storedir"]+\
@@ -407,13 +391,14 @@ class generic_stage_target(generic_target):
                                                verbose=False)
                print "Source path set to "+self.settings["source_path"]
                if os.path.isdir(self.settings["source_path"]):
-                       print "\tIf this is not desired, remove this directory or turn off seedcache in the options of catalyst.conf"
-                       print "\tthe source path will then be "+\
+                       print "\tIf this is not desired, remove this directory or turn off"
+                       print "\tseedcache in the options of catalyst.conf the source path"
+                       print "\twill then be "+\
                                normpath(self.settings["storedir"]+"/builds/"+\
                                self.settings["source_subpath"]+".tar.bz2\n")
 
        def set_dest_path(self):
-               if self.settings.has_key("root_path"):
+               if "root_path" in self.settings:
                        self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
                                self.settings["root_path"])
                else:
@@ -425,15 +410,23 @@ class generic_stage_target(generic_target):
 
        def set_snapshot_path(self):
                self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-                       "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
+                       "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
 
                if os.path.exists(self.settings["snapshot_path"]):
                        self.settings["snapshot_path_hash"]=\
                                generate_hash(self.settings["snapshot_path"],\
                                hash_function=self.settings["hash_function"],verbose=False)
+               else:
+                       self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
+                               "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
+
+                       if os.path.exists(self.settings["snapshot_path"]):
+                               self.settings["snapshot_path_hash"]=\
+                                       generate_hash(self.settings["snapshot_path"],\
+                                       hash_function=self.settings["hash_function"],verbose=False)
 
        def set_snapcache_path(self):
-               if self.settings.has_key("SNAPCACHE"):
+               if "SNAPCACHE" in self.settings:
                        self.settings["snapshot_cache_path"]=\
                                normpath(self.settings["snapshot_cache"]+"/"+\
                                self.settings["snapshot"]+"/")
@@ -455,7 +448,7 @@ class generic_stage_target(generic_target):
                        "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
                        self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
                        self.settings["version_stamp"]+"/")
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        print "The autoresume path is " + self.settings["autoresume_path"]
                if not os.path.exists(self.settings["autoresume_path"]):
                        os.makedirs(self.settings["autoresume_path"],0755)
@@ -466,36 +459,40 @@ class generic_stage_target(generic_target):
                        "-controller.sh")
 
        def set_iso_volume_id(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
+               if self.settings["spec_prefix"]+"/volid" in self.settings:
                        self.settings["iso_volume_id"]=\
                                self.settings[self.settings["spec_prefix"]+"/volid"]
                        if len(self.settings["iso_volume_id"])>32:
                                raise CatalystError,\
                                        "ISO volume ID must not exceed 32 characters."
                else:
-                       self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"] 
+                       self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
 
        def set_action_sequence(self):
                """ Default action sequence for run method """
                self.settings["action_sequence"]=["unpack","unpack_snapshot",\
-                               "config_profile_link","setup_confdir","portage_overlay",\
+                               "setup_confdir","portage_overlay",\
                                "base_dirs","bind","chroot_setup","setup_environment",\
                                "run_local","preclean","unbind","clean"]
-#              if self.settings.has_key("TARBALL") or \
-#                      not self.settings.has_key("FETCH"):
-               if not self.settings.has_key("FETCH"):
+#              if "TARBALL" in self.settings or \
+#                      "FETCH" not in self.settings:
+               if "FETCH" not in self.settings:
                        self.settings["action_sequence"].append("capture")
                self.settings["action_sequence"].append("clear_autoresume")
 
        def set_use(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
+               if self.settings["spec_prefix"]+"/use" in self.settings:
                        self.settings["use"]=\
                                self.settings[self.settings["spec_prefix"]+"/use"]
                        del self.settings[self.settings["spec_prefix"]+"/use"]
-               if self.settings.has_key("use"):
-                       if type(self.settings["use"])==types.StringType:
-                               self.settings["use"]=self.settings["use"].split()
-                               self.settings["use"].append("bindist")
+               if "use" not in self.settings:
+                       self.settings["use"]=""
+               if type(self.settings["use"])==types.StringType:
+                       self.settings["use"]=self.settings["use"].split()
+
+               # Force bindist when options ask for it
+               if "BINDIST" in self.settings:
+                       self.settings["use"].append("bindist")
 
        def set_stage_path(self):
                self.settings["stage_path"]=normpath(self.settings["chroot_path"])
@@ -507,22 +504,30 @@ class generic_stage_target(generic_target):
                pass
 
        def set_rm(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
+               if self.settings["spec_prefix"]+"/rm" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/rm"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/rm"]=\
                                        self.settings[self.settings["spec_prefix"]+"/rm"].split()
 
        def set_linuxrc(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
+               if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/linuxrc"])==types.StringType:
                                self.settings["linuxrc"]=\
                                        self.settings[self.settings["spec_prefix"]+"/linuxrc"]
                                del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
 
+       def set_busybox_config(self):
+               if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
+                       if type(self.settings[self.settings["spec_prefix"]+\
+                               "/busybox_config"])==types.StringType:
+                               self.settings["busybox_config"]=\
+                                       self.settings[self.settings["spec_prefix"]+"/busybox_config"]
+                               del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
+
        def set_portage_overlay(self):
-               if self.settings.has_key("portage_overlay"):
+               if "portage_overlay" in self.settings:
                        if type(self.settings["portage_overlay"])==types.StringType:
                                self.settings["portage_overlay"]=\
                                        self.settings["portage_overlay"].split()
@@ -530,7 +535,7 @@ class generic_stage_target(generic_target):
                                string.join(self.settings["portage_overlay"])+"\""
 
        def set_overlay(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
+               if self.settings["spec_prefix"]+"/overlay" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/overlay"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/overlay"]=\
@@ -538,78 +543,45 @@ class generic_stage_target(generic_target):
                                        "/overlay"].split()
 
        def set_root_overlay(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
+               if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/root_overlay"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
                                        self.settings[self.settings["spec_prefix"]+\
                                        "/root_overlay"].split()
 
-
        def set_root_path(self):
                """ ROOT= variable for emerges """
                self.settings["root_path"]="/"
 
        def set_valid_build_kernel_vars(self,addlargs):
-               if addlargs.has_key("boot/kernel"):
+               if "boot/kernel" in addlargs:
                        if type(addlargs["boot/kernel"])==types.StringType:
                                loopy=[addlargs["boot/kernel"]]
                        else:
                                loopy=addlargs["boot/kernel"]
 
                        for x in loopy:
-                               self.required_values.append("boot/kernel/"+x+"/sources")
-                               self.required_values.append("boot/kernel/"+x+"/config")
                                self.valid_values.append("boot/kernel/"+x+"/aliases")
+                               self.valid_values.append("boot/kernel/"+x+"/config")
+                               self.valid_values.append("boot/kernel/"+x+"/console")
                                self.valid_values.append("boot/kernel/"+x+"/extraversion")
+                               self.valid_values.append("boot/kernel/"+x+"/gk_action")
+                               self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
+                               self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
+                               self.valid_values.append("boot/kernel/"+x+"/machine_type")
+                               self.valid_values.append("boot/kernel/"+x+"/sources")
+                               self.valid_values.append("boot/kernel/"+x+"/softlevel")
+                               self.valid_values.append("boot/kernel/"+x+"/use")
                                self.valid_values.append("boot/kernel/"+x+"/packages")
-                               if addlargs.has_key("boot/kernel/"+x+"/packages"):
+                               if "boot/kernel/"+x+"/packages" in addlargs:
                                        if type(addlargs["boot/kernel/"+x+\
                                                "/packages"])==types.StringType:
                                                addlargs["boot/kernel/"+x+"/packages"]=\
                                                        [addlargs["boot/kernel/"+x+"/packages"]]
-                               self.valid_values.append("boot/kernel/"+x+"/use")
-                               self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
-                               self.valid_values.append("boot/kernel/"+x+"/gk_action")
-                               self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
-                               self.valid_values.append("boot/kernel/"+x+"/softlevel")
-                               self.valid_values.append("boot/kernel/"+x+"/console")
-                               self.valid_values.append("boot/kernel/"+x+"/machine_type")
-                               # TODO: remove this warning/code with the next major version
-                               self.valid_values.append("boot/kernel/"+x+"/postconf")
-                               if addlargs.has_key("boot/kernel/"+x+"/postconf"):
-                                       print "boot/kernel/"+x+"/postconf is deprecated"
-                                       print "\tInternally moving these ebuilds to boot/kernel/"+\
-                                               x+"/packages"
-                                       print "\tPlease move them to boot/kernel/"+x+\
-                                               "/packages in your specfile"
-                                       if type(addlargs["boot/kernel/"+x+\
-                                               "/postconf"])==types.StringType:
-                                               loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
-                                       else:
-                                               loop2=addlargs["boot/kernel/"+x+"/postconf"]
-                               
-                                       for y in loop2:
-                                               if not addlargs.has_key("boot/kernel/"+x+"/packages"):
-                                                       addlargs["boot/kernel/"+x+"/packages"]=[y]
-                                               else:
-                                                       addlargs["boot/kernel/"+x+"/packages"].append(y)
 
        def set_build_kernel_vars(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
-                       # TODO: remove this warning/code with the next major version
-                       print self.settings["spec_prefix"]+\
-                               "/devmanager is deprecated and will be removed."
-                       self.settings["devmanager"]=\
-                               self.settings[self.settings["spec_prefix"]+"/devmanager"]
-                       del self.settings[self.settings["spec_prefix"]+"/devmanager"]
-
-               if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
-                       self.settings["splashtype"]=\
-                               self.settings[self.settings["spec_prefix"]+"/splashtype"]
-                       del self.settings[self.settings["spec_prefix"]+"/splashtype"]
-
-               if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
+               if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
                        self.settings["gk_mainargs"]=\
                                self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
                        del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
@@ -633,7 +605,7 @@ class generic_stage_target(generic_target):
 
                """
                Check and verify that none of our paths in mypath are mounted. We don't
-               want to clean up with things still mounted, and this allows us to check. 
+               want to clean up with things still mounted, and this allows us to check.
                Returns 1 on ok, 0 on "something is still mounted" case.
                """
 
@@ -663,8 +635,8 @@ class generic_stage_target(generic_target):
                clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
                        "unpack")
 
-               if self.settings.has_key("SEEDCACHE"):
-                       if os.path.isdir(self.settings["source_path"]): 
+               if "SEEDCACHE" in self.settings:
+                       if os.path.isdir(self.settings["source_path"]):
                                """ SEEDCACHE Is a directory, use rsync """
                                unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
                                        " "+self.settings["chroot_path"]
@@ -681,8 +653,12 @@ class generic_stage_target(generic_target):
                                        self.settings["source_path"]+"\nto "+\
                                        self.settings["chroot_path"]+\
                                                " (This may take some time) ...\n"
-                               unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
-                                       self.settings["chroot_path"]
+                               if "bz2" == self.settings["chroot_path"][-3:]:
+                                       unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                               self.settings["chroot_path"]
+                               else:
+                                       unpack_cmd="tar xpf "+self.settings["source_path"]+" -C "+\
+                                               self.settings["chroot_path"]
                                error_msg="Tarball extraction of "+\
                                        self.settings["source_path"]+" to "+\
                                        self.settings["chroot_path"]+" failed."
@@ -692,12 +668,16 @@ class generic_stage_target(generic_target):
                                self.settings["source_path"]+"\nto "+\
                                self.settings["chroot_path"]+\
                                " (This may take some time) ...\n"
-                       unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
-                               self.settings["chroot_path"]
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                       self.settings["chroot_path"]
+                       else:
+                               unpack_cmd="tar xpf "+self.settings["source_path"]+" -C "+\
+                                       self.settings["chroot_path"]
                        error_msg="Tarball extraction of "+self.settings["source_path"]+\
                                " to "+self.settings["chroot_path"]+" failed."
 
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        if os.path.isdir(self.settings["source_path"]) \
                                and os.path.exists(self.settings["autoresume_path"]+"unpack"):
                                """ Autoresume is valid, SEEDCACHE is valid """
@@ -709,7 +689,7 @@ class generic_stage_target(generic_target):
                                """ Autoresume is valid, tarball is valid """
                                unpack=False
                                invalid_snapshot=True
-                       
+
                        elif os.path.isdir(self.settings["source_path"]) \
                                and not os.path.exists(self.settings["autoresume_path"]+\
                                "unpack"):
@@ -724,7 +704,7 @@ class generic_stage_target(generic_target):
                                invalid_snapshot=True
                else:
                        """ No autoresume, SEEDCACHE """
-                       if self.settings.has_key("SEEDCACHE"):
+                       if "SEEDCACHE" in self.settings:
                                """ SEEDCACHE so let's run rsync and let it clean up """
                                if os.path.isdir(self.settings["source_path"]):
                                        unpack=True
@@ -748,7 +728,7 @@ class generic_stage_target(generic_target):
                        self.mount_safety_check()
 
                        if invalid_snapshot:
-                               if self.settings.has_key("AUTORESUME"):
+                               if "AUTORESUME" in self.settings:
                                        print "No Valid Resume point detected, cleaning up..."
 
                                self.clear_autoresume()
@@ -760,18 +740,18 @@ class generic_stage_target(generic_target):
                        if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
                                os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
 
-                       if self.settings.has_key("PKGCACHE"):
+                       if "PKGCACHE" in self.settings:
                                if not os.path.exists(self.settings["pkgcache_path"]):
                                        os.makedirs(self.settings["pkgcache_path"],0755)
 
-                       if self.settings.has_key("KERNCACHE"):
+                       if "KERNCACHE" in self.settings:
                                if not os.path.exists(self.settings["kerncache_path"]):
                                        os.makedirs(self.settings["kerncache_path"],0755)
 
                        print display_msg
                        cmd(unpack_cmd,error_msg,env=self.env)
 
-                       if self.settings.has_key("source_path_hash"):
+                       if "source_path_hash" in self.settings:
                                myf=open(self.settings["autoresume_path"]+"unpack","w")
                                myf.write(self.settings["source_path_hash"])
                                myf.close()
@@ -785,12 +765,15 @@ class generic_stage_target(generic_target):
                snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
                        "unpack_portage")
 
-               if self.settings.has_key("SNAPCACHE"): 
+               if "SNAPCACHE" in self.settings:
                        snapshot_cache_hash=\
                                read_from_clst(self.settings["snapshot_cache_path"]+\
                                "catalyst-hash")
                        destdir=self.settings["snapshot_cache_path"]
-                       unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
+                       else:
+                               unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
                        unpack_errmsg="Error unpacking snapshot"
                        cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
                                self.settings["snapshot_cache_path"]+\
@@ -806,11 +789,15 @@ class generic_stage_target(generic_target):
                        cleanup_errmsg="Error removing existing snapshot directory."
                        cleanup_msg=\
                                "Cleaning up existing portage tree (This can take a long time)..."
-                       unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
-                               self.settings["chroot_path"]+"/usr"
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
+                                       self.settings["chroot_path"]+"/usr"
+                       else:
+                               unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
+                                       self.settings["chroot_path"]+"/usr"
                        unpack_errmsg="Error unpacking snapshot"
 
-                       if self.settings.has_key("AUTORESUME") \
+                       if "AUTORESUME" in self.settings \
                                and os.path.exists(self.settings["chroot_path"]+\
                                        "/usr/portage/") \
                                and os.path.exists(self.settings["autoresume_path"]\
@@ -821,7 +808,7 @@ class generic_stage_target(generic_target):
                                        unpack=False
 
                if unpack:
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                self.snapshot_lock_object.write_lock()
                        if os.path.exists(destdir):
                                print cleanup_msg
@@ -833,7 +820,7 @@ class generic_stage_target(generic_target):
                        print "Unpacking portage tree (This can take a long time) ..."
                        cmd(unpack_cmd,unpack_errmsg,env=self.env)
 
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
@@ -843,11 +830,11 @@ class generic_stage_target(generic_target):
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
 
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                self.snapshot_lock_object.unlock()
 
        def config_profile_link(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "config_profile_link"):
                        print \
@@ -856,33 +843,32 @@ class generic_stage_target(generic_target):
                        # TODO: zmedico and I discussed making this a directory and pushing
                        # in a parent file, as well as other user-specified configuration.
                        print "Configuring profile link..."
-                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
+                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
                                        "Error zapping profile link",env=self.env)
-                       cmd("ln -sf ../usr/portage/profiles/"+\
+                       cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
+                       cmd("ln -sf ../../usr/portage/profiles/"+\
                                self.settings["target_profile"]+" "+\
-                               self.settings["chroot_path"]+"/etc/make.profile",\
+                               self.settings["chroot_path"]+"/etc/portage/make.profile",\
                                "Error creating profile link",env=self.env)
                        touch(self.settings["autoresume_path"]+"config_profile_link")
 
        def setup_confdir(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "setup_confdir"):
                        print "Resume point detected, skipping setup_confdir operation..."
                else:
-                       if self.settings.has_key("portage_confdir"):
+                       if "portage_confdir" in self.settings:
                                print "Configuring /etc/portage..."
-                               cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
-                                       "Error zapping /etc/portage",env=self.env)
-                               cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
-                                       self.settings["chroot_path"]+"/etc/portage",\
+                               cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
+                                       self.settings["chroot_path"]+"/etc/portage/",\
                                        "Error copying /etc/portage",env=self.env)
                                touch(self.settings["autoresume_path"]+"setup_confdir")
 
        def portage_overlay(self):
                """ We copy the contents of our overlays to /usr/local/portage """
-               if self.settings.has_key("portage_overlay"):
-                       for x in self.settings["portage_overlay"]: 
+               if "portage_overlay" in self.settings:
+                       for x in self.settings["portage_overlay"]:
                                if os.path.exists(x):
                                        print "Copying overlay dir " +x
                                        cmd("mkdir -p "+self.settings["chroot_path"]+\
@@ -894,9 +880,9 @@ class generic_stage_target(generic_target):
 
        def root_overlay(self):
                """ Copy over the root_overlay """
-               if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
+               if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
                        for x in self.settings[self.settings["spec_prefix"]+\
-                               "/root_overlay"]: 
+                               "/root_overlay"]:
                                if os.path.exists(x):
                                        print "Copying root_overlay: "+x
                                        cmd("rsync -a "+x+"/ "+\
@@ -908,15 +894,16 @@ class generic_stage_target(generic_target):
                pass
 
        def bind(self):
-               for x in self.mounts: 
+               for x in self.mounts:
                        if not os.path.exists(self.settings["chroot_path"]+x):
                                os.makedirs(self.settings["chroot_path"]+x,0755)
 
                        if not os.path.exists(self.mountmap[x]):
-                               os.makedirs(self.mountmap[x],0755)
+                               if not self.mountmap[x] == "tmpfs":
+                                       os.makedirs(self.mountmap[x],0755)
 
                        src=self.mountmap[x]
-                       if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
+                       if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                self.snapshot_lock_object.read_lock()
                        if os.uname()[0] == "FreeBSD":
                                if src == "/dev":
@@ -926,8 +913,14 @@ class generic_stage_target(generic_target):
                                        retval=os.system("mount_nullfs "+src+" "+\
                                                self.settings["chroot_path"]+x)
                        else:
-                               retval=os.system("mount --bind "+src+" "+\
-                                       self.settings["chroot_path"]+x)
+                               if src == "tmpfs":
+                                       if "var_tmpfs_portage" in self.settings:
+                                               retval=os.system("mount -t tmpfs -o size="+\
+                                                       self.settings["var_tmpfs_portage"]+"G "+src+" "+\
+                                                       self.settings["chroot_path"]+x)
+                               else:
+                                       retval=os.system("mount --bind "+src+" "+\
+                                               self.settings["chroot_path"]+x)
                        if retval!=0:
                                self.unbind()
                                raise CatalystError,"Couldn't bind mount "+src
@@ -959,7 +952,7 @@ class generic_stage_target(generic_target):
                                        ouch=1
                                        warn("Couldn't umount bind mount: "+mypath+x)
 
-                       if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
+                       if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                try:
                                        """
                                        It's possible the snapshot lock object isn't created yet.
@@ -980,25 +973,25 @@ class generic_stage_target(generic_target):
 
        def chroot_setup(self):
                self.makeconf=read_makeconf(self.settings["chroot_path"]+\
-                       "/etc/make.conf")
+                       "/etc/portage/make.conf")
                self.override_cbuild()
                self.override_chost()
                self.override_cflags()
-               self.override_cxxflags()        
-               self.override_ldflags() 
-               if self.settings.has_key("AUTORESUME") \
+               self.override_cxxflags()
+               self.override_ldflags()
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
                        print "Resume point detected, skipping chroot_setup operation..."
                else:
                        print "Setting up chroot..."
-                       
-                       #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
-                       
+
+                       #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
+
                        cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
                                "Could not copy resolv.conf into place.",env=self.env)
-               
+
                        """ Copy over the envscript, if applicable """
-                       if self.settings.has_key("ENVSCRIPT"):
+                       if "ENVSCRIPT" in self.settings:
                                if not os.path.exists(self.settings["ENVSCRIPT"]):
                                        raise CatalystError,\
                                                "Can't find envscript "+self.settings["ENVSCRIPT"]
@@ -1015,18 +1008,6 @@ class generic_stage_target(generic_target):
                                        self.settings["chroot_path"]+"/tmp/envscript",\
                                        "Could not copy envscript into place.",env=self.env)
 
-                       """ Setup metadata_overlay """
-                       if self.settings.has_key("METADATA_OVERLAY") \
-                               and not self.settings.has_key("portage_confdir"):
-                               if not os.path.exists(self.settings["chroot_path"]+\
-                                       "/etc/portage"):
-                                       cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
-                               myf=open(self.settings["chroot_path"]+\
-                                       "/etc/portage/modules","a")
-                               myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
-                               myf.close()
-
-
                        """
                        Copy over /etc/hosts from the host in case there are any
                        specialties in there
@@ -1039,23 +1020,26 @@ class generic_stage_target(generic_target):
                                        "Could not copy /etc/hosts",env=self.env)
 
                        """ Modify and write out make.conf (for the chroot) """
-                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
+                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
                                "Could not remove "+self.settings["chroot_path"]+\
-                               "/etc/make.conf",env=self.env)
-                       myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
+                               "/etc/portage/make.conf",env=self.env)
+                       myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
                        myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
-                       myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
-                       if self.settings.has_key("CFLAGS"):
+                       myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
+                       if "CFLAGS" in self.settings:
                                myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
-                       if self.settings.has_key("CXXFLAGS"):
-                               myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
+                       if "CXXFLAGS" in self.settings:
+                               if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
+                                       myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
+                               else:
+                                       myf.write('CXXFLAGS="${CFLAGS}"\n')
                        else:
                                myf.write('CXXFLAGS="${CFLAGS}"\n')
 
-                       if self.settings.has_key("LDFLAGS"):
-                               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")
+                       if "LDFLAGS" in self.settings:
+                               myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
                                myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
-                       if self.settings.has_key("CBUILD"):
+                       if "CBUILD" in self.settings:
                                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")
                                myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
 
@@ -1064,10 +1048,10 @@ class generic_stage_target(generic_target):
 
                        """ Figure out what our USE vars are for building """
                        myusevars=[]
-                       if self.settings.has_key("HOSTUSE"):
+                       if "HOSTUSE" in self.settings:
                                myusevars.extend(self.settings["HOSTUSE"])
 
-                       if self.settings.has_key("use"):
+                       if "use" in self.settings:
                                myusevars.extend(self.settings["use"])
 
                        if myusevars:
@@ -1076,32 +1060,33 @@ class generic_stage_target(generic_target):
                                myf.write('USE="'+string.join(myusevars)+'"\n')
                                if '-*' in myusevars:
                                        print "\nWarning!!!  "
-                                       print "\tThe use of -* in " + self.settings["spec_prefix"] + "/use will cause portage to ignore\n"
+                                       print "\tThe use of -* in "+self.settings["spec_prefix"]+\
+                                               "/use will cause portage to ignore"
                                        print "\tpackage.use in the profile and portage_confdir. You've been warned!"
 
                        """ Setup the portage overlay """
-                       if self.settings.has_key("portage_overlay"):
+                       if "portage_overlay" in self.settings:
                                myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
 
                        myf.close()
-                       cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
-                               self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
-                               "Could not backup /etc/make.conf",env=self.env)
+                       cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
+                               self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
+                               "Could not backup /etc/portage/make.conf",env=self.env)
                        touch(self.settings["autoresume_path"]+"chroot_setup")
 
        def fsscript(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
                        print "Resume point detected, skipping fsscript operation..."
                else:
-                       if self.settings.has_key("fsscript"):
+                       if "fsscript" in self.settings:
                                if os.path.exists(self.settings["controller_file"]):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " fsscript","fsscript script failed.",env=self.env)
                                        touch(self.settings["autoresume_path"]+"fsscript")
 
        def rcupdate(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
                        print "Resume point detected, skipping rcupdate operation..."
                else:
@@ -1111,11 +1096,11 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"rcupdate")
 
        def clean(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"clean"):
                        print "Resume point detected, skipping clean operation..."
                else:
-                       for x in self.settings["cleanables"]: 
+                       for x in self.settings["cleanables"]:
                                print "Cleaning chroot: "+x+"... "
                                cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
                                        x,env=self.env)
@@ -1131,7 +1116,7 @@ class generic_stage_target(generic_target):
                        cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
                                "Could not remove /usr/local/portage",env=self.env)
                        cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
-                               "/etc/make.conf",\
+                               "/etc/portage/make.conf",\
                                "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
 
                """ Clean up old and obsoleted files in /etc """
@@ -1146,39 +1131,39 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"clean")
 
        def empty(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"empty"):
                        print "Resume point detected, skipping empty operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
+                       if self.settings["spec_prefix"]+"/empty" in self.settings:
                                if type(self.settings[self.settings["spec_prefix"]+\
                                        "/empty"])==types.StringType:
                                        self.settings[self.settings["spec_prefix"]+"/empty"]=\
                                                self.settings[self.settings["spec_prefix"]+\
                                                "/empty"].split()
-                       for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
-                               myemp=self.settings["destpath"]+x
-                               if not os.path.isdir(myemp):
-                                       print x,"not a directory or does not exist, skipping 'empty' operation."
-                                       continue
-                               print "Emptying directory",x
-                               """ 
-                               stat the dir, delete the dir, recreate the dir and set
-                               the proper perms and ownership
-                               """
-                               mystat=os.stat(myemp)
-                               shutil.rmtree(myemp)
-                               os.makedirs(myemp,0755)
-                               os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-                               os.chmod(myemp,mystat[ST_MODE])
+                               for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
+                                       myemp=self.settings["destpath"]+x
+                                       if not os.path.isdir(myemp) or os.path.islink(myemp):
+                                               print x,"not a directory or does not exist, skipping 'empty' operation."
+                                               continue
+                                       print "Emptying directory",x
+                                       """
+                                       stat the dir, delete the dir, recreate the dir and set
+                                       the proper perms and ownership
+                                       """
+                                       mystat=os.stat(myemp)
+                                       shutil.rmtree(myemp)
+                                       os.makedirs(myemp,0755)
+                                       os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+                                       os.chmod(myemp,mystat[ST_MODE])
                        touch(self.settings["autoresume_path"]+"empty")
 
        def remove(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"remove"):
                        print "Resume point detected, skipping remove operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
+                       if self.settings["spec_prefix"]+"/rm" in self.settings:
                                for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
                                        """
                                        We're going to shell out for all these cleaning
@@ -1196,7 +1181,7 @@ class generic_stage_target(generic_target):
                                        raise
 
        def preclean(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"preclean"):
                        print "Resume point detected, skipping preclean operation..."
                else:
@@ -1205,13 +1190,13 @@ class generic_stage_target(generic_target):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " preclean","preclean script failed.",env=self.env)
                                        touch(self.settings["autoresume_path"]+"preclean")
-               
+
                        except:
                                self.unbind()
                                raise CatalystError, "Build failed, could not execute preclean"
 
        def capture(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"capture"):
                        print "Resume point detected, skipping capture operation..."
                else:
@@ -1226,7 +1211,7 @@ class generic_stage_target(generic_target):
 
                        print "Creating stage tarball..."
 
-                       cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
+                       cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
                                self.settings["stage_path"]+" .",\
                                "Couldn't create stage tarball",env=self.env)
 
@@ -1236,7 +1221,7 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"capture")
 
        def run_local(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"run_local"):
                        print "Resume point detected, skipping run_local operation..."
                else:
@@ -1273,7 +1258,7 @@ class generic_stage_target(generic_target):
                                        self.env[varname]="true"
                                else:
                                        self.env[varname]="false"
-               if self.settings.has_key("makeopts"):
+               if "makeopts" in self.settings:
                        self.env["MAKEOPTS"]=self.settings["makeopts"]
 
        def run(self):
@@ -1285,9 +1270,18 @@ class generic_stage_target(generic_target):
                """ Check for mounts right away and abort if we cannot unmount them """
                self.mount_safety_check()
 
-               if self.settings.has_key("CLEAR_AUTORESUME"):
+               if "CLEAR_AUTORESUME" in self.settings:
                        self.clear_autoresume()
-               if self.settings.has_key("PURGE"):
+
+               if "PURGETMPONLY" in self.settings:
+                       self.purge()
+                       return
+
+               if "PURGEONLY" in self.settings:
+                       self.purge()
+                       return
+
+               if "PURGE" in self.settings:
                        self.purge()
 
                for x in self.settings["action_sequence"]:
@@ -1298,15 +1292,15 @@ class generic_stage_target(generic_target):
                        except:
                                self.mount_safety_check()
                                raise
-               
+
                self.chroot_lock.unlock()
 
        def unmerge(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
                        print "Resume point detected, skipping unmerge operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
+                       if self.settings["spec_prefix"]+"/unmerge" in self.settings:
                                if type(self.settings[self.settings["spec_prefix"]+\
                                        "/unmerge"])==types.StringType:
                                        self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
@@ -1334,7 +1328,7 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"unmerge")
 
        def target_setup(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
                        print "Resume point detected, skipping target_setup operation..."
                else:
@@ -1345,12 +1339,12 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"target_setup")
 
        def setup_overlay(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
                        print "Resume point detected, skipping setup_overlay operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
-                               for x in self.settings[self.settings["spec_prefix"]+"/overlay"]: 
+                       if self.settings["spec_prefix"]+"/overlay" in self.settings:
+                               for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
                                        if os.path.exists(x):
                                                cmd("rsync -a "+x+"/ "+\
                                                        self.settings["target_path"],\
@@ -1359,12 +1353,12 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"setup_overlay")
 
        def create_iso(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
                        print "Resume point detected, skipping create_iso operation..."
                else:
                        """ Create the ISO """
-                       if self.settings.has_key("iso"):
+                       if "iso" in self.settings:
                                cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
                                        self.settings["iso"],"ISO creation script failed.",\
                                        env=self.env)
@@ -1376,13 +1370,13 @@ class generic_stage_target(generic_target):
                                print "An ISO Image will not be created."
 
        def build_packages(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "build_packages"):
                        print "Resume point detected, skipping build_packages operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
-                               if self.settings.has_key("AUTORESUME") \
+                       if self.settings["spec_prefix"]+"/packages" in self.settings:
+                               if "AUTORESUME" in self.settings \
                                        and os.path.exists(self.settings["autoresume_path"]+\
                                                "build_packages"):
                                        print "Resume point detected, skipping build_packages operation..."
@@ -1401,11 +1395,12 @@ class generic_stage_target(generic_target):
                                                        "build aborting due to error."
 
        def build_kernel(self):
-               if self.settings.has_key("AUTORESUME") \
+               "Build all configured kernels"
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
                        print "Resume point detected, skipping build_kernel operation..."
                else:
-                       if self.settings.has_key("boot/kernel"):
+                       if "boot/kernel" in self.settings:
                                try:
                                        mynames=self.settings["boot/kernel"]
                                        if type(mynames)==types.StringType:
@@ -1416,130 +1411,129 @@ class generic_stage_target(generic_target):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " pre-kmerge ","Runscript pre-kmerge failed",\
                                                env=self.env)
-
                                        for kname in mynames:
-                                               if self.settings.has_key("AUTORESUME") \
-                                                       and os.path.exists(self.settings["autoresume_path"]\
-                                                               +"build_kernel_"+kname):
-                                                       print "Resume point detected, skipping build_kernel for "+kname+" operation..."
-                                               else:
-                                                       try:
-                                                               if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
-                                                                       self.unbind()
-                                                                       raise CatalystError,\
-                                                                               "Can't find kernel config: "+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/config"]
-
-                                                       except TypeError:
-                                                               raise CatalystError,\
-                                                                       "Required value boot/kernel/config not specified"
-
-                                                       try:
-                                                               cmd("cp "+self.settings["boot/kernel/"+kname+\
-                                                                       "/config"]+" "+\
-                                                                       self.settings["chroot_path"]+"/var/tmp/"+\
-                                                                       kname+".config",\
-                                                                       "Couldn't copy kernel config: "+\
-                                                                       self.settings["boot/kernel/"+kname+\
-                                                                       "/config"],env=self.env)
-
-                                                       except CatalystError:
-                                                               self.unbind()
-
-                                                       """
-                                                       If we need to pass special options to the bootloader
-                                                       for this kernel put them into the environment
-                                                       """
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/kernelopts"):
-                                                               myopts=self.settings["boot/kernel/"+kname+\
-                                                                       "/kernelopts"]
-
-                                                               if type(myopts) != types.StringType:
-                                                                       myopts = string.join(myopts)
-                                                                       self.env[kname+"_kernelopts"]=myopts
-
-                                                               else:
-                                                                       self.env[kname+"_kernelopts"]=""
-
-                                                       if not self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/extraversion"):
-                                                               self.settings["boot/kernel/"+kname+\
-                                                                       "/extraversion"]=""
-
-                                                       self.env["clst_kextraversion"]=\
-                                                               self.settings["boot/kernel/"+kname+\
-                                                               "/extraversion"]
-
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/initramfs_overlay"):
-                                                               if os.path.exists(self.settings["boot/kernel/"+\
-                                                                       kname+"/initramfs_overlay"]):
-                                                                       print "Copying initramfs_overlay dir "+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"]
-
-                                                                       cmd("mkdir -p "+\
-                                                                               self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/"+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"],env=self.env)
-
-                                                                       cmd("cp -R "+self.settings["boot/kernel/"+\
-                                                                               kname+"/initramfs_overlay"]+"/* "+\
-                                                                               self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/"+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"],env=self.env)
-
-                                                       """ Execute the script that builds the kernel """
-                                                       cmd("/bin/bash "+self.settings["controller_file"]+\
-                                                               " kernel "+kname,\
-                                                               "Runscript kernel build failed",env=self.env)
-
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/initramfs_overlay"):
-                                                               if os.path.exists(self.settings["chroot_path"]+\
-                                                                       "/tmp/initramfs_overlay/"):
-                                                                       print "Cleaning up temporary overlay dir"
-                                                                       cmd("rm -R "+self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/",env=self.env)
-
-                                                       touch(self.settings["autoresume_path"]+\
-                                                               "build_kernel_"+kname)
-
-                                                       """
-                                                       Execute the script that cleans up the kernel build
-                                                       environment
-                                                       """
-                                                       cmd("/bin/bash "+self.settings["controller_file"]+\
-                                                               " post-kmerge ",
-                                                               "Runscript post-kmerge failed",env=self.env)
-
+                                               self._build_kernel(kname=kname)
                                        touch(self.settings["autoresume_path"]+"build_kernel")
-
                                except CatalystError:
                                        self.unbind()
                                        raise CatalystError,\
                                                "build aborting due to kernel build error."
 
+       def _build_kernel(self, kname):
+               "Build a single configured kernel by name"
+               if "AUTORESUME" in self.settings \
+                       and os.path.exists(self.settings["autoresume_path"]\
+                               +"build_kernel_"+kname):
+                       print "Resume point detected, skipping build_kernel for "+kname+" operation..."
+                       return
+               self._copy_kernel_config(kname=kname)
+
+               """
+               If we need to pass special options to the bootloader
+               for this kernel put them into the environment
+               """
+               if "boot/kernel/"+kname+"/kernelopts" in self.settings:
+                       myopts=self.settings["boot/kernel/"+kname+\
+                               "/kernelopts"]
+
+                       if type(myopts) != types.StringType:
+                               myopts = string.join(myopts)
+                               self.env[kname+"_kernelopts"]=myopts
+
+                       else:
+                               self.env[kname+"_kernelopts"]=""
+
+               if "boot/kernel/"+kname+"/extraversion" not in self.settings:
+                       self.settings["boot/kernel/"+kname+\
+                               "/extraversion"]=""
+
+               self.env["clst_kextraversion"]=\
+                       self.settings["boot/kernel/"+kname+\
+                       "/extraversion"]
+
+               self._copy_initramfs_overlay(kname=kname)
+
+               """ Execute the script that builds the kernel """
+               cmd("/bin/bash "+self.settings["controller_file"]+\
+                       " kernel "+kname,\
+                       "Runscript kernel build failed",env=self.env)
+
+               if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
+                       if os.path.exists(self.settings["chroot_path"]+\
+                               "/tmp/initramfs_overlay/"):
+                               print "Cleaning up temporary overlay dir"
+                               cmd("rm -R "+self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/",env=self.env)
+
+               touch(self.settings["autoresume_path"]+\
+                       "build_kernel_"+kname)
+
+               """
+               Execute the script that cleans up the kernel build
+               environment
+               """
+               cmd("/bin/bash "+self.settings["controller_file"]+\
+                       " post-kmerge ",
+                       "Runscript post-kmerge failed",env=self.env)
+
+       def _copy_kernel_config(self, kname):
+               if "boot/kernel/"+kname+"/config" in self.settings:
+                       if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
+                               self.unbind()
+                               raise CatalystError,\
+                                       "Can't find kernel config: "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/config"]
+
+                       try:
+                               cmd("cp "+self.settings["boot/kernel/"+kname+\
+                                       "/config"]+" "+\
+                                       self.settings["chroot_path"]+"/var/tmp/"+\
+                                       kname+".config",\
+                                       "Couldn't copy kernel config: "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/config"],env=self.env)
+
+                       except CatalystError:
+                               self.unbind()
+
+       def _copy_initramfs_overlay(self, kname):
+               if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
+                       if os.path.exists(self.settings["boot/kernel/"+\
+                               kname+"/initramfs_overlay"]):
+                               print "Copying initramfs_overlay dir "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"]
+
+                               cmd("mkdir -p "+\
+                                       self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/"+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"],env=self.env)
+
+                               cmd("cp -R "+self.settings["boot/kernel/"+\
+                                       kname+"/initramfs_overlay"]+"/* "+\
+                                       self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/"+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"],env=self.env)
+
        def bootloader(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
                        print "Resume point detected, skipping bootloader operation..."
                else:
                        try:
                                cmd("/bin/bash "+self.settings["controller_file"]+\
                                        " bootloader " + self.settings["target_path"],\
-                                       "Bootloader runscript failed.",env=self.env)
+                                       "Bootloader script failed.",env=self.env)
                                touch(self.settings["autoresume_path"]+"bootloader")
                        except CatalystError:
                                self.unbind()
-                               raise CatalystError,"Runscript aborting due to error."
+                               raise CatalystError,"Script aborting due to error."
 
        def livecd_update(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "livecd_update"):
                        print "Resume point detected, skipping build_packages operation..."
@@ -1572,7 +1566,7 @@ class generic_stage_target(generic_target):
                        os.chmod(myemp,mystat[ST_MODE])
 
        def clear_packages(self):
-               if self.settings.has_key("PKGCACHE"):
+               if "PKGCACHE" in self.settings:
                        print "purging the pkgcache ..."
 
                        myemp=self.settings["pkgcache_path"]
@@ -1590,7 +1584,7 @@ class generic_stage_target(generic_target):
                                os.chmod(myemp,mystat[ST_MODE])
 
        def clear_kerncache(self):
-               if self.settings.has_key("KERNCACHE"):
+               if "KERNCACHE" in self.settings:
                        print "purging the kerncache ..."
 
                        myemp=self.settings["kerncache_path"]
@@ -1609,11 +1603,11 @@ class generic_stage_target(generic_target):
 
        def clear_autoresume(self):
                """ Clean resume points since they are no longer needed """
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        print "Removing AutoResume Points: ..."
                myemp=self.settings["autoresume_path"]
                if os.path.isdir(myemp):
-                               if self.settings.has_key("AUTORESUME"):
+                               if "AUTORESUME" in self.settings:
                                        print "Emptying directory",myemp
                                """
                                stat the dir, delete the dir, recreate the dir and set
@@ -1633,7 +1627,7 @@ class generic_stage_target(generic_target):
        def gen_contents_file(self,file):
                if os.path.exists(file+".CONTENTS"):
                        os.remove(file+".CONTENTS")
-               if self.settings.has_key("contents"):
+               if "contents" in self.settings:
                        if os.path.exists(file):
                                myf=open(file+".CONTENTS","w")
                                keys={}
@@ -1643,14 +1637,15 @@ class generic_stage_target(generic_target):
                                        array.sort()
                                for j in array:
                                        contents=generate_contents(file,contents_function=j,\
-                                               verbose=self.settings.has_key("VERBOSE"))
-                                       myf.write(contents)
+                                               verbose="VERBOSE" in self.settings)
+                                       if contents:
+                                               myf.write(contents)
                                myf.close()
 
        def gen_digest_file(self,file):
                if os.path.exists(file+".DIGESTS"):
                        os.remove(file+".DIGESTS")
-               if self.settings.has_key("digests"):
+               if "digests" in self.settings:
                        if os.path.exists(file):
                                myf=open(file+".DIGESTS","w")
                                keys={}
@@ -1660,25 +1655,32 @@ class generic_stage_target(generic_target):
                                        array.sort()
                                for f in [file, file+'.CONTENTS']:
                                        if os.path.exists(f):
-                                               for j in array:
-                                                       hash=generate_hash(f,hash_function=j,verbose=\
-                                                               self.settings.has_key("VERBOSE"))
-                                                       myf.write(hash)
+                                               if "all" in array:
+                                                       for k in hash_map.keys():
+                                                               hash=generate_hash(f,hash_function=k,verbose=\
+                                                                       "VERBOSE" in self.settings)
+                                                               myf.write(hash)
+                                               else:
+                                                       for j in array:
+                                                               hash=generate_hash(f,hash_function=j,verbose=\
+                                                                       "VERBOSE" in self.settings)
+                                                               myf.write(hash)
                                myf.close()
 
        def purge(self):
                countdown(10,"Purging Caches ...")
-               if self.settings.has_key("PURGE"):
+               if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
                        print "clearing autoresume ..."
                        self.clear_autoresume()
 
                        print "clearing chroot ..."
                        self.clear_chroot()
 
-                       print "clearing package cache ..."
-                       self.clear_packages()
+                       if "PURGETMPONLY" not in self.settings:
+                               print "clearing package cache ..."
+                               self.clear_packages()
 
                        print "clearing kerncache ..."
                        self.clear_kerncache()
 
-# vim: ts=4 sw=4 sta et sts=4 ai 
+# vim: ts=4 sw=4 sta et sts=4 ai