From 71b0f8dff8ce6aa1127f6676244cc3283f5078f9 Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Sat, 26 Sep 2009 14:52:40 +0200 Subject: [PATCH] [entropy.spm] Plugin interface refactoring, move Portage stuff away from Entropy Client Trigger interface --- docs/TODO | 2 +- .../entropy/client/interfaces/package.py | 6 +- .../entropy/client/interfaces/trigger.py | 439 ++-------------- libraries/entropy/const.py | 6 +- .../spm/plugins/interfaces/portage_plugin.py | 471 ++++++++++++++---- libraries/entropy/spm/plugins/skel.py | 35 +- 6 files changed, 437 insertions(+), 522 deletions(-) diff --git a/docs/TODO b/docs/TODO index ff3f4f585..f646b681c 100644 --- a/docs/TODO +++ b/docs/TODO @@ -5,7 +5,7 @@ Proposed for Entropy 1.0 (before and after) (requires API changes, perhaps): 1.0_beta1: - move sensible pkgs to alt dir - - entropy.client.interfaces.trigger, move Portage code to entropy.spm + - move etpConst['spm'] to entropy.spm - entropy.db hookable plugins support (atom/dep validation, db taint, pkg add, pkg rm) - Transform Sulfur into Entropy Store: diff --git a/libraries/entropy/client/interfaces/package.py b/libraries/entropy/client/interfaces/package.py index 8b48696a6..406f4f724 100644 --- a/libraries/entropy/client/interfaces/package.py +++ b/libraries/entropy/client/interfaces/package.py @@ -352,7 +352,7 @@ class Package: importance = 0, header = red(" ## ") ) - return Spm.configure_installed_package(self.pkgmeta) + return Spm.execute_package_phase(self.pkgmeta, "configure") def __remove_package(self): @@ -2338,6 +2338,10 @@ class Package: self.pkgmeta['key'], self.pkgmeta['slot'] = key, slot self.pkgmeta['version'] = \ self.Entropy.clientDbconn.retrieveVersion(idpackage) + self.pkgmeta['category'] = \ + self.Entropy.clientDbconn.retrieveCategory(idpackage) + self.pkgmeta['name'] = \ + self.Entropy.clientDbconn.retrieveName(idpackage) self.pkgmeta['accept_license'] = \ self.Entropy.clientDbconn.retrieveLicensedataKeys(idpackage) self.pkgmeta['steps'] = [] diff --git a/libraries/entropy/client/interfaces/trigger.py b/libraries/entropy/client/interfaces/trigger.py index 9e800f6d0..81c9b4c49 100644 --- a/libraries/entropy/client/interfaces/trigger.py +++ b/libraries/entropy/client/interfaces/trigger.py @@ -22,8 +22,14 @@ from entropy.i18n import _ class Trigger: VALID_PHASES = ("preinstall", "postinstall", "preremove", "postremove",) - ENV_VARS_DIR = "/etc/env.d" - ENV_UPDATE_HOOK = "env-update" + ENV_VARS_DIR = etpConst['spm']['env_dir_reference'] + ENV_UPDATE_HOOK = etpConst['spm']['env_update_cmd'] + PHASES = { + 'preinstall': "preinstall", + 'postinstall': "postinstall", + 'preremove': "preremove", + 'postremove': "postremove", + } import entropy.tools as entropyTools def __init__(self, entropy_client, phase, pkgdata, package_action = None): @@ -199,7 +205,8 @@ class Trigger: self.Entropy.clientLog.log( ETP_LOGPRI_INFO, ETP_LOGLEVEL_NORMAL, - "[POST] ATTENTION Cannot run External trigger for "+mykey+"!! "+str(Exception)+": "+str(e) + "[POST] ATTENTION Cannot run External trigger for " + \ + mykey + "!! " + str(Exception) + ": " + str(e) ) mytxt = "%s: %s %s. %s." % ( bold(_("QA")), @@ -425,410 +432,40 @@ class Trigger: def trigger_spm_postinstall(self): - stdfile = open("/dev/null", "w") - oldstderr = sys.stderr - oldstdout = sys.stdout - sys.stderr = stdfile - - myebuild = None - if os.path.isdir(self.pkgdata['xpakdir']) and \ - os.access(self.pkgdata['xpakdir'], os.R_OK): - - myebuild = [self.pkgdata['xpakdir']+"/"+x for x \ - in os.listdir(self.pkgdata['xpakdir']) if \ - x.endswith(etpConst['spm']['source_build_ext'])] - - if myebuild: - myebuild = myebuild[0] - portage_atom = self.pkgdata['category'] + "/" + \ - self.pkgdata['name'] + "-" + self.pkgdata['version'] - self.Entropy.updateProgress( - "SPM: %s" % (brown(_("post-install phase")),), - importance = 0, - header = red(" ## ") - ) - try: - - if not etpUi['debug']: - sys.stdout = stdfile - self.__ebuild_setup_phase(myebuild, portage_atom) - if not etpUi['debug']: - sys.stdout = oldstdout - - rc = self.Spm.execute_package_phase(portage_atom, myebuild, - "postinstall", - work_dir = self.pkgdata['unpackdir'], - licenses_accepted = self.pkgdata['accept_license'] - ) - if rc == 1: - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[POST] ATTENTION Cannot properly run Source Package Manager post-install (pkg_postinst()) trigger for " + \ - str(portage_atom) + ". Something bad happened." - ) - - except Exception, e: - sys.stdout = oldstdout - self.entropyTools.print_traceback() - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[POST] ATTENTION Cannot run Source Package Manager trigger for "+portage_atom+"!! "+str(Exception)+": "+str(e) - ) - mytxt = "%s: %s %s. %s. %s: %s" % ( - bold(_("QA")), - brown(_("Cannot run Source Package Manager trigger for")), - bold(str(portage_atom)), - brown(_("Please report it")), - bold(_("Attach this")), - darkred(etpConst['spmlogfile']), - ) - self.Entropy.updateProgress( - mytxt, - importance = 0, - header = red(" ## ") - ) - sys.stderr = oldstderr - sys.stdout = oldstdout - stdfile.close() - return 0 - - def __ebuild_setup_phase(self, ebuild, portage_atom): - - rc = 0 - env_file = os.path.join(self.pkgdata['unpackdir'], "portage", - portage_atom, "temp/environment") - if not os.path.isfile(env_file): - - # FIXME: please remove as soon as upstream fixes it - # FIXME: workaround for buggy linux-info.eclass not being - # ported to EAPI=2 yet. - # It is required to make depmod running properly for the - # kernel modules inside this ebuild - # fix KV_OUT_DIR= inside environment - bz2envfile = os.path.join(self.pkgdata['xpakdir'], - "environment.bz2") - if "linux-info" in self.pkgdata['eclasses'] and \ - os.path.isfile(bz2envfile) and self.pkgdata['versiontag']: - - import bz2 - envfile = self.Entropy.entropyTools.unpack_bzip2(bz2envfile) - bzf = bz2.BZ2File(bz2envfile,"w") - f = open(envfile,"r") - line = f.readline() - while line: - if line == "KV_OUT_DIR=/usr/src/linux\n": - line = "KV_OUT_DIR=/lib/modules/%s/build\n" % ( - self.pkgdata['versiontag'],) - bzf.write(line) - line = f.readline() - f.close() - bzf.close() - os.remove(envfile) - - rc = self.Spm.execute_package_phase(portage_atom, ebuild, - "setup", - work_dir = self.pkgdata['unpackdir'], - licenses_accepted = self.pkgdata['accept_license'] - ) - if rc == 1: - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[POST] ATTENTION Cannot properly run Source Package Manager setup" - " phase for "+str(portage_atom)+". Something bad happened." - ) - return rc - + self.Entropy.updateProgress( + "SPM: %s" % (brown(_("post-install phase")),), + importance = 0, + header = red(" ## ") + ) + return self.Spm.execute_package_phase(self.pkgdata, + Trigger.PHASES['postinstall']) def trigger_spm_preinstall(self): - stdfile = open("/dev/null", "w") - oldstderr = sys.stderr - oldstdout = sys.stdout - sys.stderr = stdfile - - myebuild = None - if os.path.isdir(self.pkgdata['xpakdir']) and \ - os.access(self.pkgdata['xpakdir'], os.R_OK): - - myebuild = [self.pkgdata['xpakdir']+"/"+x for x in \ - os.listdir(self.pkgdata['xpakdir']) if \ - x.endswith(etpConst['spm']['source_build_ext'])] - - if myebuild: - myebuild = myebuild[0] - portage_atom = self.pkgdata['category'] + "/" + \ - self.pkgdata['name'] + "-" + self.pkgdata['version'] - self.Entropy.updateProgress( - "SPM: %s" % (brown(_("pre-install phase")),), - importance = 0, - header = red(" ## ") - ) - try: - - if not etpUi['debug']: - sys.stdout = stdfile - self.__ebuild_setup_phase(myebuild, portage_atom) - if not etpUi['debug']: - sys.stdout = oldstdout - - rc = self.Spm.execute_package_phase(portage_atom, myebuild, - "preinstall", - work_dir = self.pkgdata['unpackdir'], - licenses_accepted = self.pkgdata['accept_license'] - ) - if rc == 1: - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot properly run Source Package Manager pre-install (pkg_preinst()) trigger for " + \ - str(portage_atom)+". Something bad happened." - ) - except Exception, e: - sys.stdout = oldstdout - self.entropyTools.print_traceback() - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot run Source Package Manager preinst trigger for "+portage_atom+"!! "+str(Exception)+": "+str(e) - ) - mytxt = "%s: %s %s. %s. %s: %s" % ( - bold(_("QA")), - brown(_("Cannot run Source Package Manager trigger for")), - bold(str(portage_atom)), - brown(_("Please report it")), - bold(_("Attach this")), - darkred(etpConst['spmlogfile']), - ) - self.Entropy.updateProgress( - mytxt, - importance = 0, - header = red(" ## ") - ) - sys.stderr = oldstderr - sys.stdout = oldstdout - stdfile.close() - return 0 + self.Entropy.updateProgress( + "SPM: %s" % (brown(_("pre-install phase")),), + importance = 0, + header = red(" ## ") + ) + return self.Spm.execute_package_phase(self.pkgdata, + Trigger.PHASES['preinstall']) def trigger_spm_preremove(self): - stdfile = open("/dev/null", "w") - oldstderr = sys.stderr - sys.stderr = stdfile - - portage_atom = self.pkgdata['category'] + "/" + self.pkgdata['name'] + \ - "-" + self.pkgdata['version'] - - myebuild = self.Spm.get_installed_package_build_script_path( - portage_atom) - - self.myebuild_moved = None - if os.path.isfile(myebuild): - try: - myebuild = self._setup_remove_ebuild_environment(myebuild, portage_atom) - except EOFError, e: - sys.stderr = oldstderr - stdfile.close() - # stuff on system is broken, ignore it - self.Entropy.updateProgress( - darkred("!!! Ebuild: pkg_prerm() failed, EOFError: ")+str(e)+darkred(" - ignoring"), - importance = 1, - type = "warning", - header = red(" ## ") - ) - return 0 - except ImportError, e: - sys.stderr = oldstderr - stdfile.close() - # stuff on system is broken, ignore it - self.Entropy.updateProgress( - darkred("!!! Ebuild: pkg_prerm() failed, ImportError: ")+str(e)+darkred(" - ignoring"), - importance = 1, - type = "warning", - header = red(" ## ") - ) - return 0 - - if os.path.isfile(myebuild): - - self.Entropy.updateProgress( - "SPM: %s" % (brown(_("pre-remove phase")),), - importance = 0, - header = red(" ## ") - ) - try: - rc = self.Spm.execute_package_phase(portage_atom, myebuild, - "preremove", - work_dir = etpConst['entropyunpackdir']+"/"+portage_atom, - licenses_accepted = self.pkgdata['accept_license'] - ) - if rc == 1: - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot properly run Source Package Manager trigger for " + \ - str(portage_atom)+". Something bad happened." - ) - except Exception, e: - sys.stderr = oldstderr - stdfile.close() - self.entropyTools.print_traceback() - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot run Source Package Manager " + \ - "pre-remove trigger for " + portage_atom + "!! " + \ - str(Exception)+": "+str(e) - ) - mytxt = "%s: %s %s. %s. %s: %s" % ( - bold(_("QA")), - brown(_("Cannot run Source Package Manager trigger for")), - bold(str(portage_atom)), - brown(_("Please report it")), - bold(_("Attach this")), - darkred(etpConst['spmlogfile']), - ) - self.Entropy.updateProgress( - mytxt, - importance = 0, - header = red(" ## ") - ) - return 0 - - sys.stderr = oldstderr - stdfile.close() - self._remove_overlayed_ebuild() - return 0 + self.Entropy.updateProgress( + "SPM: %s" % (brown(_("pre-remove phase")),), + importance = 0, + header = red(" ## ") + ) + return self.Spm.execute_package_phase(self.pkgdata, + Trigger.PHASES['preremove']) def trigger_spm_postremove(self): - stdfile = open("/dev/null", "w") - oldstderr = sys.stderr - sys.stderr = stdfile - - portage_atom = self.pkgdata['category'] + "/" + self.pkgdata['name'] + \ - "-" + self.pkgdata['version'] - - myebuild = self.Spm.get_installed_package_build_script_path( - portage_atom) - - self.myebuild_moved = None - if os.path.isfile(myebuild): - try: - myebuild = self._setup_remove_ebuild_environment(myebuild, portage_atom) - except EOFError, e: - sys.stderr = oldstderr - stdfile.close() - # stuff on system is broken, ignore it - self.Entropy.updateProgress( - darkred("!!! Ebuild: pkg_postrm() failed, EOFError: ")+str(e)+darkred(" - ignoring"), - importance = 1, - type = "warning", - header = red(" ## ") - ) - return 0 - except ImportError, e: - sys.stderr = oldstderr - stdfile.close() - # stuff on system is broken, ignore it - self.Entropy.updateProgress( - darkred("!!! Ebuild: pkg_postrm() failed, ImportError: ")+str(e)+darkred(" - ignoring"), - importance = 1, - type = "warning", - header = red(" ## ") - ) - return 0 - - if os.path.isfile(myebuild): - self.Entropy.updateProgress( - "SPM: %s" % (brown(_("post-remove phase")),), - importance = 0, - header = red(" ## ") - ) - try: - rc = self.Spm.execute_package_phase(portage_atom, myebuild, - "postremove", - work_dir = etpConst['entropyunpackdir']+"/"+portage_atom, - licenses_accepted = self.pkgdata['accept_license'] - ) - if rc == 1: - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot properly run Source Package Manager postremove trigger for " + \ - str(portage_atom)+". Something bad happened." - ) - except Exception, e: - sys.stderr = oldstderr - stdfile.close() - self.entropyTools.print_traceback() - self.Entropy.clientLog.log( - ETP_LOGPRI_INFO, - ETP_LOGLEVEL_NORMAL, - "[PRE] ATTENTION Cannot run Source Package Manager postremove trigger for " + \ - portage_atom+"!! "+str(Exception)+": "+str(e) - ) - mytxt = "%s: %s %s. %s. %s: %s" % ( - bold(_("QA")), - brown(_("Cannot run Source Package Manager trigger for")), - bold(str(portage_atom)), - brown(_("Please report it")), - bold(_("Attach this")), - darkred(etpConst['spmlogfile']), - ) - self.Entropy.updateProgress( - mytxt, - importance = 0, - header = red(" ## ") - ) - return 0 - - sys.stderr = oldstderr - stdfile.close() - self._remove_overlayed_ebuild() - return 0 - - def _setup_remove_ebuild_environment(self, myebuild, portage_atom): - - ebuild_dir = os.path.dirname(myebuild) - ebuild_file = os.path.basename(myebuild) - - # copy the whole directory in a safe place - dest_dir = os.path.join(etpConst['entropyunpackdir'],"vardb/"+portage_atom) - if os.path.exists(dest_dir): - if os.path.isdir(dest_dir): - shutil.rmtree(dest_dir,True) - elif os.path.isfile(dest_dir) or os.path.islink(dest_dir): - os.remove(dest_dir) - os.makedirs(dest_dir) - items = os.listdir(ebuild_dir) - for item in items: - myfrom = os.path.join(ebuild_dir,item) - myto = os.path.join(dest_dir,item) - shutil.copy2(myfrom,myto) - - newmyebuild = os.path.join(dest_dir,ebuild_file) - if os.path.isfile(newmyebuild): - myebuild = newmyebuild - self.myebuild_moved = myebuild - self.Spm._ebuild_env_setup_hook(myebuild) - - return myebuild - - def _remove_overlayed_ebuild(self): - - if not self.myebuild_moved: - return - if not os.path.isfile(self.myebuild_moved): - return - - mydir = os.path.dirname(self.myebuild_moved) - shutil.rmtree(mydir, True) - mydir = os.path.dirname(mydir) - content = os.listdir(mydir) - while not content: - os.rmdir(mydir) - mydir = os.path.dirname(mydir) - content = os.listdir(mydir) + self.Entropy.updateProgress( + "SPM: %s" % (brown(_("post-remove phase")),), + importance = 0, + header = red(" ## ") + ) + return self.Spm.execute_package_phase(self.pkgdata, + Trigger.PHASES['postremove']) diff --git a/libraries/entropy/const.py b/libraries/entropy/const.py index 378beb48e..77dd033f3 100644 --- a/libraries/entropy/const.py +++ b/libraries/entropy/const.py @@ -526,9 +526,9 @@ def const_default_settings(rootdir): 'global_make_profile_link_name' : "profile.link", # source package manager executable 'exec': rootdir+"/usr/bin/emerge", - 'env_update_cmd': rootdir+"/usr/sbin/env-update", - 'source_profile': ["source", rootdir+"/etc/profile"], - 'source_build_ext': ".ebuild", + 'env_dir_reference': "/etc/env.d", + 'env_update_cmd': "/usr/sbin/env-update", + 'source_profile': ["source", "/etc/profile"], 'ask_cmd': "--ask", 'info_cmd': "--info", 'remove_cmd': "-C", diff --git a/libraries/entropy/spm/plugins/interfaces/portage_plugin.py b/libraries/entropy/spm/plugins/interfaces/portage_plugin.py index 9ce08276d..9847bba72 100644 --- a/libraries/entropy/spm/plugins/interfaces/portage_plugin.py +++ b/libraries/entropy/spm/plugins/interfaces/portage_plugin.py @@ -11,10 +11,10 @@ """ from __future__ import with_statement import os +import bz2 import sys import shutil import tempfile -import bz2 from entropy.const import etpConst, etpUi from entropy.exceptions import FileNotFound, SPMError, InvalidDependString, \ InvalidData @@ -139,6 +139,7 @@ class PortagePlugin(SpmPlugin): } ENV_FILE_COMP = "environment.bz2" + EBUILD_EXT = ".ebuild" class paren_normalize(list): """Take a dependency structure as returned by paren_reduce or use_reduce @@ -289,7 +290,7 @@ class PortagePlugin(SpmPlugin): Reimplemented from SpmPlugin class. """ return os.path.join(self._get_vdb_path(root = root), package, - package.split("/")[-1] + etpConst['spm']['source_build_ext']) + package.split("/")[-1] + PortagePlugin.EBUILD_EXT) def get_installed_package_metadata(self, package, key, root = None): """ @@ -1222,6 +1223,7 @@ class PortagePlugin(SpmPlugin): def _portage_doebuild(self, myebuild, mydo, tree, cpv, portage_tmpdir = None, licenses = None): + # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata # tree = "bintree" # cpv = atom @@ -1381,26 +1383,396 @@ class PortagePlugin(SpmPlugin): del keys return rc - def execute_package_phase(self, package, build_script_path, phase_name, - work_dir = None, licenses_accepted = None): + @staticmethod + def _pkg_compose_atom(package_metadata): + return package_metadata['category'] + "/" + \ + package_metadata['name'] + "-" + package_metadata['version'] + + @staticmethod + def _pkg_compose_xpak_ebuild(package_metadata): + package = PortagePlugin._pkg_compose_atom(package_metadata) + return os.path.join(package_metadata['xpakdir'], + os.path.basename(package) + PortagePlugin.EBUILD_EXT) + + def _pkg_remove_overlayed_ebuild(self, moved_ebuild): + + mydir = os.path.dirname(moved_ebuild) + shutil.rmtree(mydir, True) + mydir = os.path.dirname(mydir) + content = os.listdir(mydir) + while not content: + os.rmdir(mydir) + mydir = os.path.dirname(mydir) + content = os.listdir(mydir) + + def _pkg_remove_ebuild_env_setup_hook(self, ebuild): + + ebuild_path = os.path.dirname(ebuild) + + myroot = os.path.sep + if etpConst['systemroot']: + myroot = etpConst['systemroot'] + os.path.sep + + # we need to fix ROOT= if it's set inside environment + bz2envfile = os.path.join(ebuild_path, PortagePlugin.ENV_FILE_COMP) + if os.path.isfile(bz2envfile) and os.path.isdir(myroot): + envfile = entropy.tools.unpack_bzip2(bz2envfile) + bzf = bz2.BZ2File(bz2envfile, "w") + f = open(envfile, "r") + line = f.readline() + while line: + if line.startswith("ROOT="): + line = "ROOT=%s\n" % (myroot,) + bzf.write(line) + line = f.readline() + + f.close() + bzf.close() + os.remove(envfile) + + def _pkg_remove_setup_ebuild_env(self, myebuild, portage_atom): + + ebuild_dir = os.path.dirname(myebuild) + ebuild_file = os.path.basename(myebuild) + moved_ebuild = None + + # copy the whole directory in a safe place + dest_dir = os.path.join(etpConst['entropyunpackdir'], + "vardb/" + portage_atom) + if os.path.exists(dest_dir): + if os.path.isdir(dest_dir): + shutil.rmtree(dest_dir, True) + elif os.path.isfile(dest_dir) or os.path.islink(dest_dir): + os.remove(dest_dir) + + os.makedirs(dest_dir) + items = os.listdir(ebuild_dir) + for item in items: + myfrom = os.path.join(ebuild_dir, item) + myto = os.path.join(dest_dir, item) + shutil.copy2(myfrom, myto) + + newmyebuild = os.path.join(dest_dir, ebuild_file) + if os.path.isfile(newmyebuild): + myebuild = newmyebuild + moved_ebuild = myebuild + self._pkg_remove_ebuild_env_setup_hook(myebuild) + + return myebuild, moved_ebuild + + def _pkg_setup(self, package_metadata, skip_if_found = False): + + package = PortagePlugin._pkg_compose_atom(package_metadata) + env_file = os.path.join(package_metadata['unpackdir'], "portage", + package, "temp/environment") + + if os.path.isfile(env_file) and skip_if_found: + return 0 + + # FIXME: please remove as soon as upstream fixes it + # FIXME: workaround for buggy linux-info.eclass not being + # ported to EAPI=2 yet. + # It is required to make depmod running properly for the + # kernel modules inside this ebuild + # fix KV_OUT_DIR= inside environment + bz2envfile = os.path.join(package_metadata['xpakdir'], + PortagePlugin.ENV_FILE_COMP) + + if "linux-info" in package_metadata['eclasses'] and \ + os.path.isfile(bz2envfile) and package_metadata['versiontag']: + + envfile = entropy.tools.unpack_bzip2(bz2envfile) + bzf = bz2.BZ2File(bz2envfile,"w") + f = open(envfile,"r") + line = f.readline() + while line: + if line == "KV_OUT_DIR=/usr/src/linux\n": + line = "KV_OUT_DIR=/lib/modules/%s/build\n" % ( + package_metadata['versiontag'],) + bzf.write(line) + line = f.readline() + f.close() + bzf.close() + os.remove(envfile) + + ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) + rc = self._portage_doebuild(ebuild, "setup", + "bintree", package, portage_tmpdir = package_metadata['unpackdir'], + licenses = package_metadata.get('accept_license')) + + if rc == 1: + self.log_message( + "[POST] ATTENTION Cannot properly run Source Package Manager" + " setup phase for %s Something bad happened." % (package,) + ) + + return rc + + def _pkg_fooinst(self, package_metadata, phase): + + tmp_file = tempfile.mktemp() + stdfile = open(tmp_file, "w") + oldstderr = sys.stderr + oldstdout = sys.stdout + sys.stderr = stdfile + + package = PortagePlugin._pkg_compose_atom(package_metadata) + ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) + rc = 0 + remove_tmp = True + + try: + # is ebuild available + if not (os.path.isfile(ebuild) and os.access(ebuild, os.R_OK)): + return rc + + try: + + if not etpUi['debug']: + sys.stdout = stdfile + self._pkg_setup(package_metadata, skip_if_found = True) + if not etpUi['debug']: + sys.stdout = oldstdout + + rc = self._portage_doebuild(ebuild, phase, "bintree", + package, portage_tmpdir = package_metadata['unpackdir'], + licenses = package_metadata.get('accept_license')) + + if rc != 0: + self.log_message( + "[PRE] ATTENTION Cannot properly run SPM %s" + " phase for %s. Something bad happened." % ( + phase, package,) + ) + + except Exception, e: + + stdfile.flush() + sys.stdout = oldstdout + entropy.tools.print_traceback() + + self.log_message( + "[PRE] ATTENTION Cannot properly run SPM %s" + " phase for %s. Something bad happened." + " Exception %s [%s]" % ( + phase, package, Exception, e,) + ) + + mytxt = "%s: %s %s. %s. %s: %s + %s [%s]" % ( + bold(_("QA")), + brown(_("Cannot run Source Package Manager trigger for")), + bold(str(package)), + brown(_("Please report it")), + bold(_("Attach this")), + darkred(etpConst['spmlogfile']), + darkred(tmp_file), + brown(phase), + ) + self.updateProgress( + mytxt, + importance = 0, + header = red(" ## ") + ) + remove_tmp = False + + return rc + + finally: + + sys.stderr = oldstderr + sys.stdout = oldstdout + stdfile.flush() + stdfile.close() + + if (rc == 0) and remove_tmp: + try: + os.remove(tmp_file) + except OSError: + pass + + def _pkg_foorm(self, package_metadata, phase): + + tmp_file = tempfile.mktemp() + stdfile = open(tmp_file, "w") + oldstderr = sys.stderr + oldstdout = sys.stdout + sys.stderr = stdfile + + rc = 0 + remove_tmp = True + moved_ebuild = None + package = PortagePlugin._pkg_compose_atom(package_metadata) + ebuild = self.get_installed_package_build_script_path(package) + + try: + + if not os.path.isfile(ebuild): + return 0 + + try: + ebuild, moved_ebuild = self._pkg_remove_setup_ebuild_env( + ebuild, package) + + except EOFError, e: + sys.stderr = oldstderr + # stuff on system is broken, ignore it + self.updateProgress( + darkred("!!! Ebuild: pkg_" + phase + "() failed, EOFError: ") + \ + str(e) + darkred(" - ignoring"), + importance = 1, + type = "warning", + header = red(" ## ") + ) + return 0 + + except ImportError, e: + sys.stderr = oldstderr + # stuff on system is broken, ignore it + self.updateProgress( + darkred("!!! Ebuild: pkg_" + phase + "() failed, ImportError: ") + \ + str(e) + darkred(" - ignoring"), + importance = 1, + type = "warning", + header = red(" ## ") + ) + return 0 + + try: + + work_dir = os.path.join(etpConst['entropyunpackdir'], package) + + rc = self._portage_doebuild(ebuild, phase, "bintree", + package, portage_tmpdir = work_dir, + licenses = package_metadata.get('accept_license')) + + if rc != 1: + self.log_message( + "[PRE] ATTENTION Cannot properly run SPM %s trigger " + "for %s. Something bad happened." % (phase, package,) + ) + + except Exception, e: + + stdfile.flush() + sys.stdout = oldstdout + entropy.tools.print_traceback() + + self.log_message( + "[PRE] ATTENTION Cannot properly run SPM %s" + " phase for %s. Something bad happened." + " Exception %s [%s]" % (phase, package, Exception, e,) + ) + + mytxt = "%s: %s %s. %s. %s: %s + %s [%s]" % ( + bold(_("QA")), + brown(_("Cannot run Source Package Manager trigger for")), + bold(str(package)), + brown(_("Please report it")), + bold(_("Attach this")), + darkred(etpConst['spmlogfile']), + darkred(tmp_file), + brown(phase), + ) + self.updateProgress( + mytxt, + importance = 0, + header = red(" ## ") + ) + remove_tmp = False + + if moved_ebuild is not None: + if os.path.isfile(moved_ebuild): + self._pkg_remove_overlayed_ebuild(moved_ebuild) + + return rc + + finally: + + sys.stderr = oldstderr + sys.stdout = oldstdout + stdfile.flush() + stdfile.close() + + if (rc == 0) and remove_tmp: + try: + os.remove(tmp_file) + except OSError: + pass + + + def _pkg_preinst(self, package_metadata): + return self._pkg_fooinst(package_metadata, "preinst") + + def _pkg_postinst(self, package_metadata): + return self._pkg_fooinst(package_metadata, "postinst") + + def _pkg_prerm(self, package_metadata): + return self._pkg_foorm(package_metadata, "prerm") + + def _pkg_postrm(self, package_metadata): + return self._pkg_foorm(package_metadata, "postrm") + + def _pkg_config(self, package_metadata): + + package = PortagePlugin._pkg_compose_atom(package_metadata) + ebuild = self.get_installed_package_build_script_path(package) + if not os.path.isfile(ebuild): + return 2 + + try: + + rc = self._portage_doebuild(ebuild, "config", "bintree", + package, licenses = package_metadata.get('accept_license')) + + if rc != 0: + return 3 + + except Exception, err: + + entropy.tools.print_traceback() + mytxt = "%s: %s %s." % ( + bold(_("QA")), + brown(_("Cannot run SPM configure phase for")), + bold(str(package)), + ) + mytxt2 = "%s: %s, %s" % ( + bold(_("Error")), + type(Exception), + err, + ) + for txt in (mytxt, mytxt2,): + self.updateProgress( + txt, + importance = 0, + header = red(" ## ") + ) + return 1 + + return 0 + + def execute_package_phase(self, package_metadata, phase_name): """ Reimplemented from SpmPlugin class. """ - if licenses_accepted is None: - licenses_accepted = [] - portage_phase = PortagePlugin.package_phases_map[phase_name] - return self._portage_doebuild(build_script_path, portage_phase, - "bintree", package, work_dir, licenses_accepted) + phase_calls = { + 'setup': self._pkg_setup, + 'preinst': self._pkg_preinst, + 'postinst': self._pkg_postinst, + 'prerm': self._pkg_prerm, + 'postrm': self._pkg_postrm, + 'config': self._pkg_config, + } + return phase_calls[portage_phase](package_metadata) def add_installed_package(self, package_metadata): """ Reimplemented from SpmPlugin class. """ atomsfound = set() - category = package_metadata['category'] - key = category + "/" + package_metadata['name'] - spm_package = key + "-" + package_metadata['version'] + spm_package = PortagePlugin._pkg_compose_atom(package_metadata) + key = entropy.tools.dep_getkey(spm_package) + category = key.split("/")[0] build = self.get_installed_package_build_script_path(spm_package) pkg_dir = os.path.dirname(build) @@ -1615,48 +1987,6 @@ class PortagePlugin(SpmPlugin): return 0 - def configure_installed_package(self, package_metadata): - """ - Reimplemented from SpmPlugin class. - """ - atom = package_metadata['key'] + "-" + package_metadata['version'] - myebuild = self.get_installed_package_build_script_path(atom) - - if not (os.access(myebuild, os.R_OK) and os.path.isfile(myebuild)): - # cannot find ebuild ! ouch! - return 2 - - try: - rc = self.execute_package_phase(atom, myebuild, - "configure", - licenses_accepted = package_metadata['accept_license'] - ) - if rc == 1: - return 3 - - except Exception, err: - - entropy.tools.print_traceback() - mytxt = "%s: %s %s." % ( - bold(_("QA")), - brown(_("Cannot run SPM configure phase for")), - bold(str(atom)), - ) - mytxt2 = "%s: %s, %s" % ( - bold(_("Error")), - type(Exception), - err, - ) - for txt in (mytxt, mytxt2,): - self.updateProgress( - txt, - importance = 0, - header = red(" ## ") - ) - return 1 - - return 0 - @staticmethod def entropy_install_setup_hook(entropy_client, package_metadata): """ @@ -1686,9 +2016,8 @@ class PortagePlugin(SpmPlugin): portdbdir = 'var/db/pkg' portdbdir = os.path.join(package_metadata['merge_from'], portdbdir) - portdbdir = os.path.join(portdbdir, package_metadata['category']) - portdbdir = os.path.join(portdbdir, package_metadata['name'] + \ - "-" + package_metadata['version']) + portdbdir = os.path.join(portdbdir, + PortagePlugin._pkg_compose_atom(package_metadata)) package_metadata['xpakdir'] = portdbdir @@ -1753,8 +2082,7 @@ class PortagePlugin(SpmPlugin): os.symlink(package_metadata['xpakdir'], tolink_dir) # create fake portage ${D} linking it to imagedir - portage_cpv = package_metadata['category'] + "/" + \ - package_metadata['name'] + "-" + package_metadata['version'] + portage_cpv = PortagePlugin._pkg_compose_atom(package_metadata) portage_db_fakedir = os.path.join( package_metadata['unpackdir'], @@ -1768,31 +2096,6 @@ class PortagePlugin(SpmPlugin): return 0 - def _ebuild_env_setup_hook(self, ebuild): - - ebuild_path = os.path.dirname(ebuild) - - myroot = os.path.sep - if etpConst['systemroot']: - myroot = etpConst['systemroot'] + os.path.sep - - # we need to fix ROOT= if it's set inside environment - bz2envfile = os.path.join(ebuild_path, PortagePlugin.ENV_FILE_COMP) - if os.path.isfile(bz2envfile) and os.path.isdir(myroot): - envfile = entropy.tools.unpack_bzip2(bz2envfile) - bzf = bz2.BZ2File(bz2envfile, "w") - f = open(envfile, "r") - line = f.readline() - while line: - if line.startswith("ROOT="): - line = "ROOT=%s\n" % (myroot,) - bzf.write(line) - line = f.readline() - - f.close() - bzf.close() - os.remove(envfile) - def _get_portage_vartree(self, root = None): if root is None: diff --git a/libraries/entropy/spm/plugins/skel.py b/libraries/entropy/spm/plugins/skel.py index f276a4320..027e37b6d 100644 --- a/libraries/entropy/spm/plugins/skel.py +++ b/libraries/entropy/spm/plugins/skel.py @@ -514,26 +514,16 @@ class SpmPlugin(Singleton): """ raise NotImplementedError() - def execute_package_phase(self, package, build_script_path, phase_name, - work_dir = None, licenses_accepted = None): + def execute_package_phase(self, package_metadata, phase_name): """ Execute Source Package Manager package phase (postinstall, preinstall, preremove, postremove, etc). - @param package: package name - @type package: string - @param build_script_path: path to Source Package Manager build script - to call - @type build_script_path: string + @param package_metadata: Entropy package phase metadata + @type package_metadata: dict @param phase_name: name of the phase to call, must be a valid phase contained in package_phases() output. @type phase_name: string - @keyword work_dir: specify a work directory if required by your SPM - @type work_dir: string - @keyword licenses_accepted: list of license names already accepted - that can be given to Source Package Manager (to skip its license - acceptance verification stuff, for example) - @type licenses_accepted: list @return: phase script exit status @rtype: int @raise KeyError: if phase is not available @@ -575,25 +565,6 @@ class SpmPlugin(Singleton): """ raise NotImplementedError() - def configure_installed_package(self, package_metadata): - """ - Configure installed package. Some SPM require users to do manual - stuff on packages. - "package_metadata" is a dictionary featuring the following (relevant) - keys: - ['accept_license', 'imagedir', 'xpakpath', 'slot', 'pkgdbpath', - 'versiontag', 'version', 'xpakstatus', 'unpackdir', 'revision', - 'category', 'repository', 'xpakdir', 'name', 'install_source', - 'removeatom' - ] - - @param package_metadata: Entropy package metadata - @type package_metadata: dict - @return: execution status - @rtype: int - """ - raise NotImplementedError() - @staticmethod def entropy_install_setup_hook(entropy_client, package_metadata): """