From: Fabian Groffen Date: Tue, 1 Jul 2008 16:59:40 +0000 (-0000) Subject: Merged from trunk 10833:10843 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=7d10257a814a4ddeb1ee734f56651aa83b9b5f67;p=portage.git Merged from trunk 10833:10843 | 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 --- diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 1e9ff29df..46060a9e0 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -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() { diff --git a/bin/portageq b/bin/portageq index b4ba70fde..e5b36bbbc 100755 --- a/bin/portageq +++ b/bin/portageq @@ -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) diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 94f1832af..59c0c6d8b 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -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 diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index a8c120e2b..feb3d1332 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -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":