Merged from trunk 10833:10843
authorFabian Groffen <grobian@gentoo.org>
Tue, 1 Jul 2008 16:59:40 +0000 (16:59 -0000)
committerFabian Groffen <grobian@gentoo.org>
Tue, 1 Jul 2008 16:59:40 +0000 (16:59 -0000)
   | 10834   | Use the EbuildMerge class instead of portage.merge().        |
   | zmedico |                                                              |

   | 10835   | Bug #229859 - Make portageq check atom validity when         |
   | zmedico | has_version() and best_version() are called from inside the  |
   |         | ebuild environment.                                          |

   | 10836   | Copy portageq exit code validation from has_version() to     |
   | zmedico | best_version().                                              |

   | 10837   | Bug #229859 - Also add atom validation to match().           |
   | zmedico |                                                              |

   | 10838   | * Remove unused EbuildBuild.pretend attribute. * Add TODO    |
   | zmedico | not about asynchronous execution.                            |

   | 10839   | Make EbuildBinpkg delegate everything up to src_install() to |
   | zmedico | the EbuildBuild class.                                       |

   | 10840   | Handle re.error exceptions raised from re.compile() when     |
   | zmedico | ACCEPT_CHOSTS is invalid. Thanks to solar for reporting.     |

   | 10841   | Split out an EbuildBuildDir class to handle locking of the   |
   | zmedico | build dir.                                                   |

   | 10842   | Instead of calling the ebuild "clean" phase in               |
   | zmedico | MergeTask.merge(), move it inside doebuild() where it can be |
   |         | tied into the actionmap_deps framework.                      |

   | 10843   | Move clean code, from the previous commit, from doebuild()   |
   | zmedico | to EbuildBuild.execute() where it fits better.               |

svn path=/main/branches/prefix/; revision=10878

bin/ebuild.sh
bin/portageq
pym/_emerge/__init__.py
pym/portage/__init__.py

index 1e9ff29df2c66cfde50bf1170607738f8071595b..46060a9e01a5d0488706bc5e5b015095ae75491b 100755 (executable)
@@ -204,6 +204,18 @@ best_version() {
        # Takes single depend-type atoms.
        PYTHONPATH="${PORTAGE_PYM_PATH}:${PYTHONPATH}" \
        "${PORTAGE_BIN_PATH}/portageq" 'best_version' "${ROOT}" "$1"
+       local retval=$?
+       case "${retval}" in
+               0)
+                       return 0
+                       ;;
+               1)
+                       return 1
+                       ;;
+               *)
+                       die "unexpected portageq exit code: ${retval}"
+                       ;;
+       esac
 }
 
 use_with() {
index b4ba70fde446d878743ba844d36a12c2508570da..e5b36bbbc2f5dcaab420d96384791a9a6a1b6b3b 100755 (executable)
@@ -51,6 +51,10 @@ def has_version(argv):
        if (len(argv) < 2):
                print "ERROR: insufficient parameters!"
                sys.exit(2)
+       if atom_validate_strict and not portage.isvalidatom(argv[1]):
+               portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
+                       noiselevel=-1)
+               return 2
        try:
                mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
                if mylist:
@@ -69,6 +73,10 @@ def best_version(argv):
        if (len(argv) < 2):
                print "ERROR: insufficient parameters!"
                sys.exit(2)
+       if atom_validate_strict and not portage.isvalidatom(argv[1]):
+               portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1],
+                       noiselevel=-1)
+               return 2
        try:
                mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
                print portage.best(mylist)
@@ -268,6 +276,10 @@ def match(argv):
                sys.exit(2)
        root, atom = argv
        if atom:
+               if atom_validate_strict and not portage.isvalidatom(atom):
+                       portage.writemsg("ERROR: Invalid atom: '%s'\n" % atom,
+                               noiselevel=-1)
+                       return 2
                results = portage.db[root]["vartree"].dbapi.match(atom)
        else:
                results = portage.db[root]["vartree"].dbapi.cpv_all()
@@ -437,6 +449,8 @@ def usage(argv):
        if (len(sys.argv) == 1):
                print "\nRun portageq with --help for info"
 
+atom_validate_strict = "EBUILD_PHASE" in os.environ
+
 def main():
        if "-h" in sys.argv or "--help" in sys.argv:
                usage(sys.argv)
index 94f1832af00a6fe2cfd1f4f086cc39243ee8ef5b..59c0c6d8b917d46f5139d0efdac83f46489bfd9c 100644 (file)
@@ -1478,9 +1478,83 @@ class EbuildFetcher(Task):
                        mydbapi=portdb, tree="porttree")
                return retval
 
-class EbuildBuild(Task):
+class EbuildBuildDir(SlotObject):
+
+       __slots__ = ("pkg", "settings",
+               "locked", "_catdir", "_lock_obj")
+
+       def __init__(self, **kwargs):
+               SlotObject.__init__(self, **kwargs)
+               self.locked = False
+
+       def lock(self):
+               """
+               This raises an AlreadyLocked exception if lock() is called
+               while a lock is already held. In order to avoid this, call
+               unlock() or check whether the "locked" attribute is True
+               or False before calling lock().
+               """
+               if self._lock_obj is not None:
+                       raise self.AlreadyLocked((self._lock_obj,))
+
+               root_config = self.pkg.root_config
+               portdb = root_config.trees["porttree"].dbapi
+               ebuild_path = portdb.findname(self.pkg.cpv)
+               settings = self.settings
+               debug = settings.get("PORTAGE_DEBUG") == "1"
+               use_cache = 1 # always true
+
+               portage.doebuild_environment(ebuild_path, "setup", root_config.root,
+                       self.settings, debug, use_cache, portdb)
+               catdir = os.path.dirname(settings["PORTAGE_BUILDDIR"])
+               self._catdir = catdir
+               portage.util.ensure_dirs(os.path.dirname(catdir),
+                       uid=portage.portage_uid, gid=portage.portage_gid,
+                       mode=070, mask=0)
+               catdir_lock = None
+               try:
+                       catdir_lock = portage.locks.lockdir(catdir)
+                       portage.util.ensure_dirs(catdir,
+                               gid=portage.portage_gid,
+                               mode=070, mask=0)
+                       self._lock_obj = portage.locks.lockdir(
+                               self.settings["PORTAGE_BUILDDIR"])
+               finally:
+                       self.locked = self._lock_obj is not None
+                       if catdir_lock is not None:
+                               portage.locks.unlockdir(catdir_lock)
+
+       def unlock(self):
+               if self._lock_obj is None:
+                       return
+
+               portage.locks.unlockdir(self._lock_obj)
+               self._lock_obj = None
+               self.locked = False
+
+               catdir = self._catdir
+               catdir_lock = None
+               try:
+                       catdir_lock = portage.locks.lockdir(catdir)
+               finally:
+                       if catdir_lock:
+                               try:
+                                       os.rmdir(catdir)
+                               except OSError, e:
+                                       if e.errno not in (errno.ENOENT,
+                                               errno.ENOTEMPTY, errno.EEXIST):
+                                               raise
+                                       del e
+                               portage.locks.unlockdir(catdir_lock)
+
+       class AlreadyLocked(portage.exception.PortageException):
+               pass
 
-       __slots__ = ("pkg", "pretend", "settings")
+class EbuildBuild(Task):
+       """
+       TODO: Support asynchronous execution, to implement parallel builds.
+       """
+       __slots__ = ("pkg", "settings")
 
        def _get_hash_key(self):
                hash_key = getattr(self, "_hash_key", None)
@@ -1491,18 +1565,25 @@ class EbuildBuild(Task):
        def execute(self):
                root_config = self.pkg.root_config
                portdb = root_config.trees["porttree"].dbapi
-               vartree = root_config.trees["vartree"]
                ebuild_path = portdb.findname(self.pkg.cpv)
                debug = self.settings.get("PORTAGE_DEBUG") == "1"
 
+               retval = portage.doebuild(ebuild_path, "clean",
+                       root_config.root, self.settings, debug, cleanup=1,
+                       mydbapi=portdb, tree="porttree")
+               if retval != os.EX_OK:
+                       return retval
+
                retval = portage.doebuild(ebuild_path, "install",
-                       root_config.root, self.settings, debug, vartree=vartree,
+                       root_config.root, self.settings, debug,
                        mydbapi=portdb, tree="porttree")
                return retval
 
 class EbuildBinpkg(Task):
-
-       __slots__ = ("pkg", "pretend", "settings")
+       """
+       This assumes that src_install() has successfully completed.
+       """
+       __slots__ = ("pkg", "settings")
 
        def _get_hash_key(self):
                hash_key = getattr(self, "_hash_key", None)
@@ -1525,13 +1606,21 @@ class EbuildBinpkg(Task):
                settings["PORTAGE_BINPKG_TMPFILE"] = binpkg_tmpfile
                settings.backup_changes("PORTAGE_BINPKG_TMPFILE")
 
+               # Earlier phases should already be done, so
+               # use "noauto" to quietly skip them.
+               settings.features.append("noauto")
+
                try:
                        retval = portage.doebuild(ebuild_path,
                                "package", root_config.root,
                                settings, debug, mydbapi=portdb,
                                tree="porttree")
                finally:
-                       self.settings.pop("PORTAGE_BINPKG_TMPFILE", None)
+                       settings.pop("PORTAGE_BINPKG_TMPFILE", None)
+                       try:
+                               settings.features.remove("noauto")
+                       except ValueError:
+                               pass
 
                if retval == os.EX_OK:
                        bintree.inject(pkg.cpv, filename=binpkg_tmpfile)
@@ -6516,35 +6605,16 @@ class MergeTask(object):
                                        self.curval += 1
                                        return
 
-                               portage.doebuild_environment(y, "setup", myroot,
-                                       pkgsettings, self.edebug, 1, portdb)
-                               catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
-                               portage.util.ensure_dirs(os.path.dirname(catdir),
-                                       uid=portage.portage_uid, gid=portage.portage_gid,
-                                       mode=070, mask=0)
-                               builddir_lock = None
-                               catdir_lock = None
+                               build_dir = EbuildBuildDir(pkg=pkg, settings=pkgsettings)
                                try:
-                                       catdir_lock = portage.locks.lockdir(catdir)
-                                       portage.util.ensure_dirs(catdir,
-                                               gid=portage.portage_gid,
-                                               mode=070, mask=0)
-                                       builddir_lock = portage.locks.lockdir(
-                                               pkgsettings["PORTAGE_BUILDDIR"])
-                                       try:
-                                               portage.locks.unlockdir(catdir_lock)
-                                       finally:
-                                               catdir_lock = None
+                                       build_dir.lock()
+                                       # Cleaning is triggered before the setup
+                                       # phase, in portage.doebuild().
                                        msg = " === (%s of %s) Cleaning (%s::%s)" % \
                                                (mergecount, len(mymergelist), pkg_key, y)
                                        short_msg = "emerge: (%s of %s) %s Clean" % \
                                                (mergecount, len(mymergelist), pkg_key)
                                        emergelog(xterm_titles, msg, short_msg=short_msg)
-                                       retval = portage.doebuild(y, "clean", myroot,
-                                               pkgsettings, self.edebug, cleanup=1,
-                                               mydbapi=portdb, tree="porttree")
-                                       if retval != os.EX_OK:
-                                               raise self._pkg_failure(retval)
 
                                        if "--buildpkg" in self.myopts or issyspkg:
                                                if issyspkg:
@@ -6556,8 +6626,12 @@ class MergeTask(object):
                                                        (mergecount, len(mymergelist), pkg_key)
                                                emergelog(xterm_titles, msg, short_msg=short_msg)
 
-                                               build = EbuildBinpkg(pkg=pkg, pretend=pretend,
-                                                       settings=pkgsettings)
+                                               build = EbuildBuild(pkg=pkg, settings=pkgsettings)
+                                               retval = build.execute()
+                                               if retval != os.EX_OK:
+                                                       raise self._pkg_failure(retval)
+
+                                               build = EbuildBinpkg(pkg=pkg, settings=pkgsettings)
                                                retval = build.execute()
                                                if retval != os.EX_OK:
                                                        raise self._pkg_failure(retval)
@@ -6569,14 +6643,11 @@ class MergeTask(object):
                                                                (mergecount, len(mymergelist), pkg_key)
                                                        emergelog(xterm_titles, msg, short_msg=short_msg)
 
-                                                       retval = portage.merge(pkgsettings["CATEGORY"],
-                                                               pkgsettings["PF"], pkgsettings["D"],
-                                                               os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
-                                                               "build-info"), myroot, pkgsettings,
-                                                               myebuild=pkgsettings["EBUILD"],
-                                                               mytree="porttree", mydbapi=portdb,
-                                                               vartree=vartree, prev_mtimes=ldpath_mtimes,
-                                                               blockers=self._find_blockers(pkg))
+                                                       merge = EbuildMerge(
+                                                               find_blockers=self._find_blockers(pkg),
+                                                               ldpath_mtimes=ldpath_mtimes,
+                                                               pkg=pkg, pretend=pretend, settings=pkgsettings)
+                                                       retval = merge.execute()
                                                        if retval != os.EX_OK:
                                                                raise self._pkg_failure(retval)
                                                elif "noclean" not in pkgsettings.features:
@@ -6590,8 +6661,7 @@ class MergeTask(object):
                                                        (mergecount, len(mymergelist), pkg_key)
                                                emergelog(xterm_titles, msg, short_msg=short_msg)
 
-                                               build = EbuildBuild(ldpath_mtimes=ldpath_mtimes,
-                                                       pkg=pkg, pretend=pretend, settings=pkgsettings)
+                                               build = EbuildBuild(pkg=pkg, settings=pkgsettings)
                                                retval = build.execute()
                                                if retval != os.EX_OK:
                                                        raise self._pkg_failure(retval)
@@ -6605,24 +6675,10 @@ class MergeTask(object):
                                                if retval != os.EX_OK:
                                                        raise self._pkg_failure(retval)
                                finally:
-                                       if builddir_lock:
+                                       if build_dir.locked:
                                                elog_process(pkg.cpv, pkgsettings,
                                                        phasefilter=filter_mergephases)
-                                               portage.locks.unlockdir(builddir_lock)
-                                       try:
-                                               if not catdir_lock:
-                                                       # Lock catdir for removal if empty.
-                                                       catdir_lock = portage.locks.lockdir(catdir)
-                                       finally:
-                                               if catdir_lock:
-                                                       try:
-                                                               os.rmdir(catdir)
-                                                       except OSError, e:
-                                                               if e.errno not in (errno.ENOENT,
-                                                                       errno.ENOTEMPTY, errno.EEXIST):
-                                                                       raise
-                                                               del e
-                                                       portage.locks.unlockdir(catdir_lock)
+                                               build_dir.unlock()
 
                        elif x[0]=="binary":
                                #merge the tbz2
index a8c120e2bff89af9f5f2c193d8a5da98e1fc87c2..feb3d1332d66e472ef7715cb0baaa66120b34de3 100644 (file)
@@ -2415,10 +2415,21 @@ class config(object):
                        if not accept_chost:
                                self._accept_chost_re = re.compile(".*")
                        elif len(accept_chost) == 1:
-                               self._accept_chost_re = re.compile(r'^%s$' % accept_chost[0])
+                               try:
+                                       self._accept_chost_re = re.compile(r'^%s$' % accept_chost[0])
+                               except re.error, e:
+                                       writemsg("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n" % \
+                                               (accept_chost[0], e), noiselevel=-1)
+                                       self._accept_chost_re = re.compile("^$")
                        else:
-                               self._accept_chost_re = re.compile(
-                                       r'^(%s)$' % "|".join(accept_chost))
+                               try:
+                                       self._accept_chost_re = re.compile(
+                                               r'^(%s)$' % "|".join(accept_chost))
+                               except re.error, e:
+                                       writemsg("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n" % \
+                                               (" ".join(accept_chost), e), noiselevel=-1)
+                                       self._accept_chost_re = re.compile("^$")
+
                return self._accept_chost_re.match(
                        pkg.metadata.get("CHOST", "")) is not None
 
@@ -4855,6 +4866,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                vartree = db[myroot]["vartree"]
 
        features = mysettings.features
+       noauto = "noauto" in features
        from portage.data import secpass
 
        validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst",
@@ -4970,6 +4982,12 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                doebuild_environment(myebuild, mydo, myroot, mysettings, debug,
                        use_cache, mydbapi)
 
+               clean_phases = ("clean", "cleanrm")
+               if mydo in clean_phases:
+                       retval = spawn(_shell_quote(ebuild_sh_binary) + " clean",
+                               mysettings, debug=debug, free=1, logfile=None)
+                       return retval
+
                # get possible slot information from the deps file
                if mydo == "depend":
                        writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
@@ -5182,10 +5200,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
 
                # if any of these are being called, handle them -- running them out of
                # the sandbox -- and stop now.
-               if mydo in ["clean","cleanrm"]:
-                       return spawn(_shell_quote(ebuild_sh_binary) + " clean", mysettings,
-                               debug=debug, free=1, logfile=None)
-               elif mydo == "help":
+               if mydo == "help":
                        return spawn(_shell_quote(ebuild_sh_binary) + " " + mydo,
                                mysettings, debug=debug, free=1, logfile=logfile)
                elif mydo == "setup":