diff --git a/libraries/entropy/client/interfaces/package.py b/libraries/entropy/client/interfaces/package.py index 665f81435..4cd5bb27a 100644 --- a/libraries/entropy/client/interfaces/package.py +++ b/libraries/entropy/client/interfaces/package.py @@ -1417,7 +1417,8 @@ class Package: importance = 0, header = red(" ## ") ) - return Spm.execute_package_phase(self.pkgmeta, "configure") + return Spm.execute_package_phase(self.pkgmeta, self.pkgmeta, + self._action, "configure") def __remove_package(self): @@ -3111,8 +3112,10 @@ class Package: def _post_install_step(self): pkgdata = self.pkgmeta['triggers'].get('install') + action_data = self.pkgmeta['triggers'].get('install') if pkgdata: - trigger = self._entropy.Triggers('postinstall', pkgdata) + trigger = self._entropy.Triggers(self._action, 'postinstall', + pkgdata, action_data) do = trigger.prepare() if do: trigger.run() @@ -3122,8 +3125,10 @@ class Package: def _pre_install_step(self): pkgdata = self.pkgmeta['triggers'].get('install') + action_data = self.pkgmeta['triggers'].get('install') if pkgdata: - trigger = self._entropy.Triggers('preinstall', pkgdata) + trigger = self._entropy.Triggers(self._action, 'preinstall', + pkgdata, action_data) do = trigger.prepare() if do: trigger.run() @@ -3133,8 +3138,10 @@ class Package: def _pre_remove_step(self): remdata = self.pkgmeta['triggers'].get('remove') + action_data = self.pkgmeta['triggers'].get('install') if remdata: - trigger = self._entropy.Triggers('preremove', remdata) + trigger = self._entropy.Triggers(self._action, 'preremove', remdata, + action_data) do = trigger.prepare() if do: trigger.run() @@ -3206,8 +3213,10 @@ class Package: def _post_remove_step(self): remdata = self.pkgmeta['triggers'].get('remove') + action_data = self.pkgmeta['triggers'].get('install') if remdata: - trigger = self._entropy.Triggers('postremove', remdata) + trigger = self._entropy.Triggers(self._action, 'postremove', + remdata, action_data) do = trigger.prepare() if do: trigger.run() diff --git a/libraries/entropy/client/interfaces/trigger.py b/libraries/entropy/client/interfaces/trigger.py index 24b13833f..73cc26470 100644 --- a/libraries/entropy/client/interfaces/trigger.py +++ b/libraries/entropy/client/interfaces/trigger.py @@ -34,21 +34,30 @@ class Trigger: VALID_PHASES = ("preinstall", "postinstall", "preremove", "postremove",) - def __init__(self, entropy_client, phase, package_metadata): + def __init__(self, entropy_client, action, phase, package_metadata, + action_metadata): """ Trigger manager interface constructor. @param entropy_client: Entropy Client interface object @type entropy_client: entropy.client.interfaces.client.Client + @param action: package handling action, can be "install", "remove", + etc. see entropy.client.interfaces.package.Package + @type action: string @param phase: the package phase that is required to be run, can be either on of the Trigger.VALID_PHASES values. @type phase: string @param package_metadata: package metadata that can be used by this Trigger interface @type package_metadata: dict + @param action_metadata: trigger metadata bound to action (and not + to phase) + @type action_metadata: dict or None """ self._entropy = entropy_client self._pkgdata = package_metadata + self._action = action + self._action_metadata = action_metadata self._prepared = False self._triggers = [] self._trigger_data = {} @@ -463,7 +472,8 @@ class Trigger: importance = 0, header = red(" ## ") ) - return self._spm.execute_package_phase(self._pkgdata, 'postinstall') + return self._spm.execute_package_phase(self._action_metadata, + self._pkgdata, self._action, 'postinstall') def _trigger_spm_preinstall(self): if self._spm is not None: @@ -472,7 +482,8 @@ class Trigger: importance = 0, header = red(" ## ") ) - return self._spm.execute_package_phase(self._pkgdata, 'preinstall') + return self._spm.execute_package_phase(self._action_metadata, + self._pkgdata, self._action, 'preinstall') def _trigger_spm_setup(self): if self._spm is not None: @@ -481,7 +492,8 @@ class Trigger: importance = 0, header = red(" ## ") ) - return self._spm.execute_package_phase(self._pkgdata, 'setup') + return self._spm.execute_package_phase(self._action_metadata, + self._pkgdata, self._action, 'setup') def _trigger_spm_preremove(self): if self._spm is not None: @@ -490,7 +502,8 @@ class Trigger: importance = 0, header = red(" ## ") ) - return self._spm.execute_package_phase(self._pkgdata, 'preremove') + return self._spm.execute_package_phase(self._action_metadata, + self._pkgdata, self._action, 'preremove') def _trigger_spm_postremove(self): if self._spm is not None: @@ -499,4 +512,5 @@ class Trigger: importance = 0, header = red(" ## ") ) - return self._spm.execute_package_phase(self._pkgdata, 'postremove') + return self._spm.execute_package_phase(self._action_metadata, + self._pkgdata, self._action, 'postremove') diff --git a/libraries/entropy/spm/plugins/interfaces/portage_plugin/__init__.py b/libraries/entropy/spm/plugins/interfaces/portage_plugin/__init__.py index dce4b360a..e5c9b4d8b 100644 --- a/libraries/entropy/spm/plugins/interfaces/portage_plugin/__init__.py +++ b/libraries/entropy/spm/plugins/interfaces/portage_plugin/__init__.py @@ -1776,8 +1776,8 @@ class PortagePlugin(SpmPlugin): def xreadlines(self): return self._std.xreadlines() - def _portage_doebuild(self, myebuild, mydo, tree, cpv, - portage_tmpdir = None, licenses = None): + def _portage_doebuild(self, myebuild, action, action_metadata, mydo, + tree, cpv, portage_tmpdir = None, licenses = None): # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata # tree = "bintree" @@ -1824,6 +1824,13 @@ class PortagePlugin(SpmPlugin): if 'EAPI' in metadata: mysettings['EAPI'] = metadata['EAPI'] + # This is part of EAPI=4, but Portage doesn't set REPLACED_BY_VERSION + # if not inside dblink.treewalk(). So, we must set it here + if (action == "install") and (action_metadata is not None) and \ + (mydo in ("prerm", "postrm")): + mysettings["REPLACED_BY_VERSION"] = action_metadata['version'] + mysettings.backup_changes("REPLACED_BY_VERSION") + # workaround for scripts asking for user intervention mysettings['ROOT'] = root mysettings['CD_ROOT'] = "/tmp" @@ -2044,7 +2051,7 @@ class PortagePlugin(SpmPlugin): return myebuild, moved_ebuild - def _pkg_setup(self, package_metadata): + def _pkg_setup(self, action_name, action_metadata, package_metadata): package = PortagePlugin._pkg_compose_atom(package_metadata) env_file = os.path.join(package_metadata['unpackdir'], "portage", @@ -2056,8 +2063,8 @@ class PortagePlugin(SpmPlugin): ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) try: - rc = self._portage_doebuild(ebuild, "setup", - "bintree", package, + rc = self._portage_doebuild(ebuild, action_name, action_metadata, + "setup", "bintree", package, portage_tmpdir = package_metadata['unpackdir'], licenses = package_metadata.get('accept_license')) except Exception as e: @@ -2099,7 +2106,8 @@ class PortagePlugin(SpmPlugin): return rc - def _pkg_fooinst(self, package_metadata, phase): + def _pkg_fooinst(self, action_metadata, package_metadata, action_name, + phase): package = PortagePlugin._pkg_compose_atom(package_metadata) ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) @@ -2109,13 +2117,14 @@ class PortagePlugin(SpmPlugin): if not (os.path.isfile(ebuild) and os.access(ebuild, os.R_OK)): return rc - rc = self._pkg_setup(package_metadata) + rc = self._pkg_setup(action_name, action_metadata, package_metadata) if rc != 0: return rc try: - rc = self._portage_doebuild(ebuild, phase, "bintree", - package, portage_tmpdir = package_metadata['unpackdir'], + rc = self._portage_doebuild(ebuild, action_name, action_metadata, + phase, "bintree", package, + portage_tmpdir = package_metadata['unpackdir'], licenses = package_metadata.get('accept_license')) if rc != 0: @@ -2159,7 +2168,7 @@ class PortagePlugin(SpmPlugin): return rc - def _pkg_foorm(self, package_metadata, phase): + def _pkg_foorm(self, action_metadata, package_metadata, action_name, phase): rc = 0 moved_ebuild = None @@ -2200,8 +2209,8 @@ class PortagePlugin(SpmPlugin): try: self._reload_portage_if_required(phase, package_metadata) - rc = self._portage_doebuild(ebuild, phase, "bintree", - package, portage_tmpdir = work_dir, + rc = self._portage_doebuild(ebuild, action_name, action_metadata, + phase, "bintree", package, portage_tmpdir = work_dir, licenses = package_metadata.get('accept_license')) except Exception as e: @@ -2250,19 +2259,23 @@ class PortagePlugin(SpmPlugin): return rc - def _pkg_preinst(self, package_metadata): - return self._pkg_fooinst(package_metadata, "preinst") + def _pkg_preinst(self, action_name, action_metadata, package_metadata): + return self._pkg_fooinst(action_metadata, package_metadata, + action_name, "preinst") - def _pkg_postinst(self, package_metadata): - return self._pkg_fooinst(package_metadata, "postinst") + def _pkg_postinst(self, action_name, action_metadata, package_metadata): + return self._pkg_fooinst(action_metadata, package_metadata, + action_name, "postinst") - def _pkg_prerm(self, package_metadata): - return self._pkg_foorm(package_metadata, "prerm") + def _pkg_prerm(self, action_name, action_metadata, package_metadata): + return self._pkg_foorm(action_metadata, package_metadata, action_name, + "prerm") - def _pkg_postrm(self, package_metadata): - return self._pkg_foorm(package_metadata, "postrm") + def _pkg_postrm(self, action_name, action_metadata, package_metadata): + return self._pkg_foorm(action_metadata, package_metadata, action_name, + "postrm") - def _pkg_config(self, package_metadata): + def _pkg_config(self, action_name, action_metadata, package_metadata): package = PortagePlugin._pkg_compose_atom(package_metadata) ebuild = self.get_installed_package_build_script_path(package) @@ -2271,8 +2284,9 @@ class PortagePlugin(SpmPlugin): try: - rc = self._portage_doebuild(ebuild, "config", "bintree", - package, licenses = package_metadata.get('accept_license')) + rc = self._portage_doebuild(ebuild, action_name, action_metadata, + "config", "bintree", package, + licenses = package_metadata.get('accept_license')) if rc != 0: return 3 @@ -2591,7 +2605,8 @@ class PortagePlugin(SpmPlugin): """ return PortagePlugin._config_files_map.copy() - def execute_package_phase(self, package_metadata, phase_name): + def execute_package_phase(self, action_metadata, package_metadata, + action_name, phase_name): """ Reimplemented from SpmPlugin class. """ @@ -2604,7 +2619,8 @@ class PortagePlugin(SpmPlugin): 'postrm': self._pkg_postrm, 'config': self._pkg_config, } - return phase_calls[portage_phase](package_metadata) + return phase_calls[portage_phase](action_name, action_metadata, + package_metadata) def _bump_vartree_mtime(self, portage_cpv): root = etpConst['systemroot'] + os.path.sep diff --git a/libraries/entropy/spm/plugins/skel.py b/libraries/entropy/spm/plugins/skel.py index f29e35e1e..3778a9bf1 100644 --- a/libraries/entropy/spm/plugins/skel.py +++ b/libraries/entropy/spm/plugins/skel.py @@ -754,13 +754,22 @@ class SpmPlugin(Singleton): """ raise NotImplementedError() - def execute_package_phase(self, package_metadata, phase_name): + def execute_package_phase(self, action_metadata, package_metadata, + action_name, phase_name): """ Execute Source Package Manager package phase (postinstall, preinstall, preremove, postremove, etc). + @param action_metadata: metadata bound to the action and not to the + actual phase requested (for example, when updating a package, + during the removal phase, action_metadata contains the new + package -- being merged -- metadata) + @type action_metadata: dict or None @param package_metadata: Entropy package phase metadata @type package_metadata: dict + @param action_name: Entropy package action name, can be "install", + "remove" + @type action_name: string @param phase_name: name of the phase to call, must be a valid phase contained in package_phases() output. @type phase_name: string diff --git a/libraries/tests/client.py b/libraries/tests/client.py index 9ff1b9d62..c243fdbb4 100644 --- a/libraries/tests/client.py +++ b/libraries/tests/client.py @@ -225,7 +225,8 @@ class EntropyRepositoryTest(unittest.TestCase): echo $@ exit 42 """ % (etpConst['trigger_sh_interpreter'],) - trigger = self.Client.Triggers('postinstall', pkgdata) + trigger = self.Client.Triggers(self._action, 'postinstall', pkgdata, + pkgdata) trigger.prepare() exit_st = trigger._do_trigger_call_ext_generic() trigger.kill() @@ -243,7 +244,8 @@ import os os.system("echo hello") my_ext_status = 42 """ - trigger = self.Client.Triggers('postinstall', pkgdata) + trigger = self.Client.Triggers(self._action, 'postinstall', pkgdata, + pkgdata) trigger.prepare() exit_st = trigger._do_trigger_call_ext_generic() trigger.kill() @@ -282,7 +284,8 @@ if stage == "postinstall": else: my_ext_status = 0 """ - trigger = self.Client.Triggers('postinstall', pkgdata) + trigger = self.Client.Triggers(self._action, 'postinstall', pkgdata, + pkgdata) trigger.prepare() exit_st = trigger._do_trigger_call_ext_generic() trigger.kill()