From 1cbb50c7b99803613b3dea967bc51b3e2687ffe5 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Tue, 25 Nov 2008 11:46:20 +0200 Subject: [PATCH] Record failure of install/erase into transaction elements - add rpmteMarkFailed() (internal) and rpmteFailed() methods to rpmte - skip any elements marked as failed in rpmtsProcess() - this is fairly close to the previous "now mostly broken" hack, except we remember more than one failure so it's slightly better and it's possible to do much better by making rpmteMarkFailed() smarter --- lib/rpmte.c | 23 +++++++++++++++++++++++ lib/rpmte.h | 7 +++++++ lib/rpmte_internal.h | 3 +++ lib/transaction.c | 30 +++++++++++++++++------------- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/lib/rpmte.c b/lib/rpmte.c index ef1a4be..154c01b 100644 --- a/lib/rpmte.c +++ b/lib/rpmte.c @@ -659,3 +659,26 @@ int rpmteClose(rpmte te, rpmts ts) } return rc; } + +int rpmteMarkFailed(rpmte te, rpmts ts) +{ + rpmtsi pi = rpmtsiInit(ts); + int rc = 0; + rpmte p; + rpmalKey key = rpmteAddedKey(te); + + te->failed = 1; + /* XXX we can do a much better here than this... */ + while ((p = rpmtsiNext(pi, TR_REMOVED))) { + if (rpmteDependsOnKey(p) == key) { + p->failed = 1; + } + } + rpmtsiFree(pi); + return rc; +} + +int rpmteFailed(rpmte te) +{ + return (te != NULL) ? te->failed : -1; +} diff --git a/lib/rpmte.h b/lib/rpmte.h index c1136b4..32ece3b 100644 --- a/lib/rpmte.h +++ b/lib/rpmte.h @@ -348,6 +348,13 @@ FD_t rpmteFd(rpmte te); fnpyKey rpmteKey(rpmte te); /** \ingroup rpmte + * Return failed status of transaction element. + * @param te transaction element + * @return 1 if transaction element (or its parents) failed + */ +int rpmteFailed(rpmte te); + +/** \ingroup rpmte * Retrieve dependency tag set from transaction element. * @param te transaction element * @param tag dependency tag diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h index 3d8903e..5b7c5c2 100644 --- a/lib/rpmte_internal.h +++ b/lib/rpmte_internal.h @@ -65,6 +65,7 @@ struct rpmte_s { #define RPMTE_HAVE_PRETRANS (1 << 0) #define RPMTE_HAVE_POSTTRANS (1 << 1) int transscripts; /*!< pre/posttrans script existence */ + int failed; /*!< (parent) install/erase failed */ rpmalKey pkgKey; }; @@ -85,5 +86,7 @@ int rpmteOpen(rpmte te, rpmts ts); RPM_GNUC_INTERNAL int rpmteClose(rpmte te, rpmts ts); +RPM_GNUC_INTERNAL +int rpmteMarkFailed(rpmte te, rpmts ts); #endif /* _RPMTE_INTERNAL_H */ diff --git a/lib/transaction.c b/lib/transaction.c index 30f4660..88e8257 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -893,24 +893,28 @@ static int runTransScripts(rpmts ts, rpmTag stag) */ static int rpmtsProcess(rpmts ts) { - rpmalKey lastFailKey = (rpmalKey)-2; /* erased packages have -1 */ rpmtsi pi; rpmte p; int rc = 0; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { - rpmalKey pkgKey; rpmpsm psm; rpmfi fi; int async; + int failed = 0; rpmElementType tetype = rpmteType(p); rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE; rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); - if ((fi = rpmtsiFi(pi)) == NULL) - continue; /* XXX can't happen */ + if (rpmteFailed(p) || (fi = rpmtsiFi(pi)) == NULL) { + /* XXX this should be a warning, need a better message though */ + rpmlog(RPMLOG_DEBUG, "element %s marked as failed, skipping\n", + rpmteNEVRA(p)); + rc++; + continue; + } psm = rpmpsmNew(ts, p, fi); async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0); @@ -919,7 +923,6 @@ static int rpmtsProcess(rpmts ts) (void) rpmswEnter(rpmtsOp(ts, op), 0); switch (tetype) { case TR_ADDED: - pkgKey = rpmteAddedKey(p); if (rpmteOpen(p, ts)) { /* * XXX Sludge necessary to tranfer existing fstates/actions @@ -930,14 +933,12 @@ static int rpmtsProcess(rpmts ts) rpmpsmSetFI(psm, p->fi); if (rpmpsmStage(psm, PSM_PKGINSTALL)) { - rc++; - lastFailKey = pkgKey; + failed = 1; } rpmteClose(p, ts); } else { - rc++; - lastFailKey = pkgKey; + failed = 1; } break; case TR_REMOVED: @@ -945,13 +946,16 @@ static int rpmtsProcess(rpmts ts) * XXX This has always been a hack, now mostly broken. * If install failed, then we shouldn't erase. */ - if (rpmteDependsOnKey(p) != lastFailKey) { - if (rpmpsmStage(psm, PSM_PKGERASE)) { - rc++; - } + if (rpmpsmStage(psm, PSM_PKGERASE)) { + failed = 1; } break; } + if (failed) { + rpmteMarkFailed(p, ts); + rc++; + } + (void) rpmswExit(rpmtsOp(ts, op), 0); (void) rpmdbSync(rpmtsGetRdb(ts)); -- 2.7.4