-/** @todo Transaction handling, more, needs work. */
-int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv)
-{
- int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
- unsigned thistid = 0xffffffff;
- unsigned prevtid;
- time_t tid;
- IDTX itids = NULL;
- IDTX rtids = NULL;
- IDT rp;
- int nrids = 0;
- IDT ip;
- int niids = 0;
- int rc = 0;
- int vsflags, ovsflags;
- int numAdded;
- int numRemoved;
- rpmps ps;
- int _unsafe_rollbacks = 0;
- rpmtransFlags transFlags = ia->transFlags;
-
- if (argv != NULL && *argv != NULL) {
- rc = -1;
- goto exit;
- }
-
- _unsafe_rollbacks = rpmExpandNumeric("%{?_unsafe_rollbacks}");
-
- vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
- if (ia->qva_flags & VERIFY_DIGEST)
- vsflags |= _RPMVSF_NODIGESTS;
- if (ia->qva_flags & VERIFY_SIGNATURE)
- vsflags |= _RPMVSF_NOSIGNATURES;
- if (ia->qva_flags & VERIFY_HDRCHK)
- vsflags |= RPMVSF_NOHDRCHK;
- vsflags |= RPMVSF_NEEDPAYLOAD; /* XXX no legacy signatures */
- ovsflags = rpmtsSetVSFlags(ts, vsflags);
-
- (void) rpmtsSetFlags(ts, transFlags);
-
- /* Make the transaction a rollback transaction. In a rollback
- * a best effort is what we want
- */
- rpmtsSetType(ts, RPMTRANS_TYPE_ROLLBACK);
-
- itids = IDTXload(ts, RPMTAG_INSTALLTID);
- if (itids != NULL) {
- ip = itids->idt;
- niids = itids->nidt;
- } else {
- ip = NULL;
- niids = 0;
- }
-
- { const char * globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
- if (globstr == NULL || *globstr == '%') {
- globstr = _free(globstr);
- rc = -1;
- goto exit;
- }
- rtids = IDTXglob(ts, globstr, RPMTAG_REMOVETID);
-
- if (rtids != NULL) {
- rp = rtids->idt;
- nrids = rtids->nidt;
- } else {
- rp = NULL;
- nrids = 0;
- }
- globstr = _free(globstr);
- }
-
- { int notifyFlags, xx;
- notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
- xx = rpmtsSetNotifyCallback(ts,
- rpmShowProgress, (void *) ((long)notifyFlags));
- }
-
- /* Run transactions until rollback goal is achieved. */
- do {
- prevtid = thistid;
- rc = 0;
- rpmcliPackagesTotal = 0;
- numAdded = 0;
- numRemoved = 0;
- ia->installInterfaceFlags &= ~ifmask;
-
- /* Find larger of the remaining install/erase transaction id's. */
- thistid = 0;
- if (ip != NULL && ip->val.u32 > thistid)
- thistid = ip->val.u32;
- if (rp != NULL && rp->val.u32 > thistid)
- thistid = rp->val.u32;
-
- /* If we've achieved the rollback goal, then we're done. */
- if (thistid == 0 || thistid < ia->rbtid)
- break;
-
- /* If we've reached the (configured) rollback goal, then we're done. */
- if (_unsafe_rollbacks && thistid <= _unsafe_rollbacks)
- break;
-
- rpmtsEmpty(ts);
- (void) rpmtsSetFlags(ts, transFlags);
-
- /* Install the previously erased packages for this transaction. */
- while (rp != NULL && rp->val.u32 == thistid) {
-
- rpmlog(RPMLOG_DEBUG, "\t+++ install %s\n",
- (rp->key ? rp->key : "???"));
-
- rc = rpmtsAddInstallElement(ts, rp->h, (fnpyKey)rp->key,
- 0, ia->relocations);
- if (rc != 0)
- goto exit;
-
- numAdded++;
- rpmcliPackagesTotal++;
- if (!(ia->installInterfaceFlags & ifmask))
- ia->installInterfaceFlags |= INSTALL_UPGRADE;
-
-#ifdef NOTYET
- rp->h = headerFree(rp->h);
-#endif
- nrids--;
- if (nrids > 0)
- rp++;
- else
- rp = NULL;
- }
-
- /* Erase the previously installed packages for this transaction. */
- while (ip != NULL && ip->val.u32 == thistid) {
-
- rpmlog(RPMLOG_DEBUG,
- "\t--- erase h#%u\n", ip->instance);
-
- rc = rpmtsAddEraseElement(ts, ip->h, ip->instance);
- if (rc != 0)
- goto exit;
-
- numRemoved++;
-
- if (_unsafe_rollbacks)
- rpmcliPackagesTotal++;
-
- if (!(ia->installInterfaceFlags & ifmask)) {
- ia->installInterfaceFlags |= INSTALL_ERASE;
- (void) rpmtsSetFlags(ts, (transFlags | RPMTRANS_FLAG_REVERSE));
- }
-
-#ifdef NOTYET
- ip->instance = 0;
-#endif
- niids--;
- if (niids > 0)
- ip++;
- else
- ip = NULL;
- }
-
- /* Anything to do? */
- if (rpmcliPackagesTotal <= 0)
- break;
-
- tid = (time_t)thistid;
- rpmlog(RPMLOG_NOTICE,
- _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
- numAdded, numRemoved, ctime(&tid), tid);
-
- rc = rpmtsCheck(ts);
- ps = rpmtsProblems(ts);
- if (rc != 0 && rpmpsNumProblems(ps) > 0) {
- rpmlog(RPMLOG_ERR, _("Failed dependencies:\n"));
- rpmpsPrint(NULL, ps);
- ps = rpmpsFree(ps);
- goto exit;
- }
- ps = rpmpsFree(ps);
-
- rc = rpmtsOrder(ts);
- if (rc != 0)
- goto exit;
-
- /* Drop added/available package indices and dependency sets. */
- rpmtsClean(ts);
-
- rc = rpmtsRun(ts, NULL, (ia->probFilter|RPMPROB_FILTER_OLDPACKAGE));
- ps = rpmtsProblems(ts);
- if (rc > 0 && rpmpsNumProblems(ps) > 0)
- rpmpsPrint(stderr, ps);
- ps = rpmpsFree(ps);
- if (rc)
- goto exit;
-
- /* Clean up after successful rollback. */
- if (rtids && !rpmIsDebug()) {
- int i;
- rpmlog(RPMLOG_NOTICE, _("Cleaning up repackaged packages:\n"));
- if (rtids->idt)
- for (i = 0; i < rtids->nidt; i++) {
- IDT rrp = rtids->idt + i;
- if (rrp->val.u32 != thistid)
- continue;
- if (rrp->key) { /* XXX can't happen */
- rpmlog(RPMLOG_NOTICE, _("\tRemoving %s:\n"), rrp->key);
- (void) unlink(rrp->key); /* XXX: Should check rc??? */
- }
- }
- }
-
-
- } while (1);
-
-exit:
- rtids = IDTXfree(rtids);
- itids = IDTXfree(itids);
-
- rpmtsEmpty(ts);
- (void) rpmtsSetFlags(ts, transFlags);
-
- return rc;
-}