}
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;
+}
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
#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;
};
RPM_GNUC_INTERNAL
int rpmteClose(rpmte te, rpmts ts);
+RPM_GNUC_INTERNAL
+int rpmteMarkFailed(rpmte te, rpmts ts);
#endif /* _RPMTE_INTERNAL_H */
*/
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);
(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
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:
* 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));