[Rpm-maint] [PATCH 1/2] Extending rpm plugin interface, part 1
Panu Matilainen
pmatilai at laiskiainen.org
Thu Oct 18 08:44:03 UTC 2012
On 10/17/2012 03:50 PM, Elena Reshetova wrote:
> This change adds a new type of the rpm plugin, called transaction plugin and a set of initial hooks for this plugin.
> The hooks are:
>
> PLUGINHOOK_TSM_PRE
> Pre-transaction hook that is called before an rpm transaction begins
> PLUGINHOOK_TSM_POST
> Post-transaction hook that is called after an rpm transaction ends
> PLUGINHOOK_PSM_PRE
> Pre-transaction-element hook that is called before an rpm transaction-element is processed
> PLUGINHOOK_PSM_POST
> Post-transaction-element hook that is called after an rpm transaction-element is processed
> PLUGINHOOK_SCRIPT_SETUP
> Per-script hook that is called once for each rpm mainainers script that is present in the package
>
> Each hook is called for every plugin that have this hook registered.
> The avaliable transaction plugins can be specified in macros.in via transaction_plugins element.
Okay, as this seems like more of an actual patch submission than
preliminary thing for sake of discussion, I'm switching into
nitpick-mode :) Overall this looks quite okay, most of the nits are on
cosmetic details that I previously either didn't notice or simply didn't
mention as it wasn't clear what parts you were going to further polish,
but there are a couple of "real" issues too.
> diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
> index 9098aa5..bb44f34 100644
> --- a/lib/rpmplugins.c
> +++ b/lib/rpmplugins.c
> @@ -110,6 +110,39 @@ rpmRC rpmpluginsAddCollectionPlugin(rpmPlugins plugins, const char *name)
> return rc;
> }
>
> +rpmRC rpmpluginsAddTransactionPlugin(rpmPlugins plugins, const char *name)
> +{
> + char *path;
> + char *options;
> + int rc = RPMRC_FAIL;
> +
> + path = rpmExpand("%{?__transaction_",name, "}", NULL);
> + if (!path || rstreq(path, "")) {
> + rpmlog(RPMLOG_INFO, _("Failed to expand %%__transaction_%s macro\n"), name);
> + goto exit;
> + }
> +
> + /* split the options from the path */
> +#define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
> +#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
> + options = path;
> + SKIPNONSPACE(options);
> + if (risspace(*options)) {
> + *options = '\0';
> + options++;
> + SKIPSPACE(options);
> + }
> + if (*options == '\0') {
> + options = NULL;
> + }
> +
> + rc = rpmpluginsAdd(plugins, name, path, options);
> +
> + exit:
> + _free(path);
> + return rc;
> +}
> +
AFAICS, with the exception of the actual macro names used, this is
identical to rpmpluginsAddCollectionPlugin(). While not a real
showstopper, I've grown very weary of mopping up the consequences of
copy-paste coding in rpm codebase over the course of the last five
years... Unless you foresee this significantly diverging from the
collection plugin setup, I'd prefer having these combined or at least
made to use a common internal helper from the start to avoid creeping
copy-pasteism :)
> +
> +rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts)
> +{
> + rpmRC (*hookFunc)(rpmts);
> + int i;
> + rpmRC rc = RPMRC_OK;
> + const char *name = NULL;
> +
> + for (i = 0; i < plugins->count; i++) {
> + name = plugins->names[i];
> + RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_PRE);
> + if ( hookFunc(ts) == RPMRC_FAIL )
> + rc = RPMRC_FAIL;
> + }
> +
> + return rc;
> +}
> +
> +rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts)
> +{
> + rpmRC (*hookFunc)(rpmts);
> + int i;
> + rpmRC rc = RPMRC_OK;
> + const char *name = NULL;
> +
> + for (i = 0; i < plugins->count; i++) {
> + name = plugins->names[i];
> + RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_POST);
> + if ( hookFunc(ts) == RPMRC_FAIL )
> + rc = RPMRC_FAIL;
Indentation is off for the entire for-block in this and all the other
rpmpluginsCall*() functions added (which seem to cry for a common helper
function but since macros are involved...) The rpm indentation style is
basically a combination of soft tabs (of width 4) and hard tabs with
minimal number of each to get to the desired indentation level, which is
four characters deeper than the previous indentation.
Also spaces dont belong before or after parenthesis (in the if).
'indent -kr' fixes these but makes "wrong" changes on some other aspects
as rpm isn't "pure" K&R style. One of these days I'll need to figure out
the magic incantation of indent switches to have it output rpm style.
Would make everybody's lives easier :)
> +/** \ingroup rpmplugins
> + * Call the post transaction element plugin hook
^^^^
> + * @param plugins plugins structure
> + * @param te processed transaction element
> + * @return RPMRC_OK on success, RPMRC_FAIL otherwise
> + */
> +rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te);
Probable copy-paste error, the description should be "pre", right? :)
> if (xx == 0) {
> - xx = execv(argv[0], argv);
> + /* Run script setup hook for all plugins */
> + if (rpmpluginsCallScriptSetup(plugins, argv[0]) != RPMRC_FAIL) {
> + xx = execv(argv[0], argv);
> + }
Cosmetics: indentation is off here.
> diff --git a/lib/rpmte.c b/lib/rpmte.c
> index 35b8e3e..5972505 100644
> --- a/lib/rpmte.c
> +++ b/lib/rpmte.c
> @@ -941,7 +941,7 @@ int rpmteProcess(rpmte te, pkgGoal goal)
> int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE);
> int test = (rpmtsFlags(te->ts) & RPMTRANS_FLAG_TEST);
> int reset_fi = (scriptstage == 0 && test == 0);
> - int failed = 1;
> + int failed = 0;
This isn't right, failure from rpmteOpen() would return success from
rpmteProcess() with this change.
>
> /* Dont bother opening for elements without pre/posttrans scripts */
> if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) {
> @@ -955,7 +955,17 @@ int rpmteProcess(rpmte te, pkgGoal goal)
> }
>
> if (rpmteOpen(te, reset_fi)) {
> - failed = rpmpsmRun(te->ts, te, goal);
> +
> + /* Run pre transaction element hook for all plugins */
> + if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS) {
> + failed = rpmpluginsCallPsmPre(rpmtsPlugins(te->ts), te);
> + }
> + if (!failed) {
> + failed = rpmpsmRun(te->ts, te, goal);
> + /* Run post transaction element hook for all plugins*/
> + if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS)
> + failed = rpmpluginsCallPsmPost(rpmtsPlugins(te->ts), te);
> + }
Hmm, this might be simpler to handle inside rpmpsmRun() where the
pre/posttrans/verify cruft is already weeded out to a separate case. If
left here, I'd think the condition should be on "scriptstage" instead of
PKG_PRETRANS/POSTTRANS to avoid calling these hooks on verification.
FWIW, the collection hooks kinda need to be here as they should be
called even if rpmteOpen() for the last collection elements failed (the
logic is a bit suspect but that's an unrelated issue), but these new
hooks are different.
> +static rpmRC rpmteSetupTransactionPlugins(rpmts ts)
Shouldn't this be rpmtsSetup... not, rpmte? :) Probably just a
copy-paste leftover from collection plugins which are on the transaction
elements.
> +{
> + rpmRC rc = 0;
> + char *plugins = NULL, *plugin = NULL;
> + char delims[] = ",";
> +
> + plugins = rpmExpand("%{?__transaction_plugins}", NULL);
> + if (!plugins || rstreq(plugins, "")) {
> + rpmlog(RPMLOG_INFO, _("Failed to expand %%__transaction_plugins macro\n"));
> + return -1;
> + }
Not having any plugins configured is not an error and should not
complain, in a "normal" setup. Obviously this has to do with wanting to
enforce security plugins being loaded but we need to find some other way
to deal with it. For now, "%{?__transaction_plugins}" evaluating to
empty should just quietly return with success. (I do see the return code
is ignored in the caller, but the output from here is ugly and causes
most of the test-suite to fail)
> +
> + plugin = strtok(plugins, delims);
> + while(plugin != NULL) {
> + rpmlog(RPMLOG_DEBUG, _("plugin is %s\n"), plugin);
> + if (!rpmpluginsPluginAdded(ts->plugins, (const char*)plugin)) {
> + rc = rpmpluginsAddTransactionPlugin(ts->plugins, (const char*)plugin);
> + }
> + plugin = strtok(NULL, delims);
> + }
> + free(plugins);
> + return rc;
> +}
...but any configured plugins failing should indeed abort the thing, so
the caller should take not of the return code.
Cosmetics: the indentation is off in this function, various mixtures of
spaces that should be a single tab + overly deep indentation for the
rpmpluginsAddTransactionPlugin() line.
> +
> int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
> {
> int rc = -1; /* assume failure */
> @@ -1441,11 +1467,19 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
> goto exit;
> }
>
> +
Cosmetics: Unnecessary empty line added.
> + rc = rpmteSetupTransactionPlugins(ts);
> +
> rpmtsSetupCollections(ts);
>
> /* Check package set for problems */
> tsprobs = checkProblems(ts);
>
> + /* Run pre transaction hook for all plugins */
> + if ( rpmpluginsCallTsmPre(ts->plugins, ts) == RPMRC_FAIL) {
^^
Cosmetics: extra space after parenthesis.
> + goto exit;
> + }
> +
> /* Run pre-transaction scripts, but only if there are no known
> * problems up to this point and not disabled otherwise. */
> if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_NOPRE))
> @@ -1489,6 +1523,11 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
> runTransScripts(ts, PKG_POSTTRANS);
> }
>
> + /* Run post transaction hook for all plugins */
> + if ( rpmpluginsCallTsmPost(ts->plugins, ts) == RPMRC_FAIL) {
^^
Cosmetics: extra space after parenthesis.
Once these mostly minor nits are fixed I think we're good to go. I'm
actually quite eager to have this in so I can start moving the selinux
stuff into a plugin :)
- Panu -
More information about the Rpm-maint
mailing list