From c7881d801745b4c156a8aa2afc17b95f97481e34 Mon Sep 17 00:00:00 2001 From: jbj Date: Thu, 15 Aug 2002 18:50:46 +0000 Subject: [PATCH] - python: explicit method to set transFlags. - python: stuff package name into a string for repackage callbacks. - rollback: re-create empty transaction set for multiple rollbacks. - fix: %%basename typo (Dmitry V. Levin). - fix: queryformat segfaults (Dmitry V. Levin). CVS patchset: 5639 CVS date: 2002/08/15 18:50:46 --- CHANGES | 5 +++++ lib/query.c | 4 ++-- lib/rpminstall.c | 36 ++++++++++++++++++++++--------- lib/rpmts.c | 45 ++++++++++++++++++++++++++++---------- lib/rpmts.h | 9 +++++++- lib/verify.c | 8 ++++--- python/rpmts-py.c | 64 +++++++++++++++++++++++++++++++++++++++++++------------ rpm.spec.in | 9 +++++++- rpmdb/header.c | 7 ++++-- rpmio/macro.c | 2 ++ tools/Makefile.am | 5 +---- 11 files changed, 146 insertions(+), 48 deletions(-) diff --git a/CHANGES b/CHANGES index 336fd5c..ca45ab2 100644 --- a/CHANGES +++ b/CHANGES @@ -238,6 +238,11 @@ - create /var/lib/rpm if non-existent in, say, a chroot. - erased packages are now repackaged into /var/spool/repackage. - fix: rebuilddb stat'ed target, not source, for rename sanity, take 2. + - python: explicit method to set transFlags. + - python: stuff package name into a string for repackage callbacks. + - rollback: re-create empty transaction set for multiple rollbacks. + - fix: %%basename typo (Dmitry V. Levin). + - fix: queryformat segfaults (Dmitry V. Levin). 4.0.3 -> 4.0.4: - solaris: translate i86pc to i386 (#57182). diff --git a/lib/query.c b/lib/query.c index e34c483..13799e8 100644 --- a/lib/query.c +++ b/lib/query.c @@ -589,7 +589,7 @@ restart: if (rpmrc == RPMRC_OK) { res = qva->qva_showPackage(qva, ts, h); h = headerFree(h); - rpmtsClean(ts); + rpmtsEmpty(ts); continue; } @@ -944,7 +944,7 @@ int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv) if (argv != NULL) while ((arg = *argv++) != NULL) { ec += rpmQueryVerify(qva, ts, arg); - rpmtsClean(ts); + rpmtsEmpty(ts); } /*@=boundsread@*/ } diff --git a/lib/rpminstall.c b/lib/rpminstall.c index b6df7d1..7bc2505 100644 --- a/lib/rpminstall.c +++ b/lib/rpminstall.c @@ -714,6 +714,8 @@ exit: eiu->pkgURL = _free(eiu->pkgURL); eiu->argv = _free(eiu->argv); + rpmtsEmpty(ts); + return eiu->numFailed; } /*@=bounds@*/ @@ -811,6 +813,8 @@ int rpmErase(rpmts ts, ps = rpmpsFree(ps); } + rpmtsEmpty(ts); + return numFailed; } @@ -1049,12 +1053,16 @@ int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv) 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; @@ -1065,7 +1073,7 @@ int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv) vsflags |= RPMVSF_NEEDPAYLOAD; /* XXX no legacy signatures */ ovsflags = rpmtsSetVSFlags(ts, vsflags); - (void) rpmtsSetFlags(ts, ia->transFlags); + (void) rpmtsSetFlags(ts, transFlags); itids = IDTXload(ts, RPMTAG_INSTALLTID); if (itids != NULL) { @@ -1119,12 +1127,14 @@ int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv) if (thistid == 0 || thistid < ia->rbtid) break; + rpmtsEmpty(ts); + (void) rpmtsSetFlags(ts, transFlags); + /* Install the previously erased packages for this transaction. */ while (rp != NULL && rp->val.u32 == thistid) { -/*@-nullpass@*/ /* FIX: rp->key may be NULL */ - rpmMessage(RPMMESS_DEBUG, "\t+++ %s\n", rp->key); -/*@=nullpass@*/ + rpmMessage(RPMMESS_DEBUG, "\t+++ install %s\n", + (rp->key ? rp->key : "???")); /*@-abstract@*/ rc = rpmtsAddInstallElement(ts, rp->h, (fnpyKey)rp->key, @@ -1152,18 +1162,21 @@ int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv) while (ip != NULL && ip->val.u32 == thistid) { rpmMessage(RPMMESS_DEBUG, - "\t--- rpmdb instance #%u\n", ip->instance); + "\t--- erase h#%u\n", ip->instance); rc = rpmtsAddEraseElement(ts, ip->h, ip->instance); if (rc != 0) goto exit; numRemoved++; -#ifdef NOTYET /* XXX don't count erasures yet */ - rpmcliPackagesTotal++; -#endif - if (!(ia->installInterfaceFlags & ifmask)) + + if (_unsafe_rollbacks) + rpmcliPackagesTotal++; + + if (!(ia->installInterfaceFlags & ifmask)) { ia->installInterfaceFlags |= INSTALL_ERASE; + (void) rpmtsSetFlags(ts, (transFlags | RPMTRANS_FLAG_REVERSE)); + } #ifdef NOTYET ip->instance = 0; @@ -1222,12 +1235,15 @@ int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv) } } + } while (1); exit: - rtids = IDTXfree(rtids); itids = IDTXfree(itids); + rpmtsEmpty(ts); + (void) rpmtsSetFlags(ts, transFlags); + return rc; } diff --git a/lib/rpmts.c b/lib/rpmts.c index da8a956..d06d658 100644 --- a/lib/rpmts.c +++ b/lib/rpmts.c @@ -546,6 +546,7 @@ void rpmtsCleanDig(rpmts ts) void rpmtsClean(rpmts ts) { rpmtsi pi; rpmte p; + if (ts == NULL) return; @@ -566,10 +567,35 @@ void rpmtsClean(rpmts ts) rpmtsCleanDig(ts); } +void rpmtsEmpty(rpmts ts) +{ + rpmtsi pi; rpmte p; + int oc; + + if (ts == NULL) + return; + +/*@-nullstate@*/ /* FIX: partial annotations */ + rpmtsClean(ts); +/*@=nullstate@*/ + + for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) { +/*@-type -unqualifiedtrans @*/ + ts->order[oc] = rpmteFree(ts->order[oc]); +/*@=type =unqualifiedtrans @*/ + } + pi = rpmtsiFree(pi); + + ts->orderCount = 0; + + ts->numRemovedPackages = 0; +} + rpmts rpmtsFree(rpmts ts) { rpmtsi pi; rpmte p; int oc; + if (ts == NULL) return NULL; @@ -579,15 +605,21 @@ rpmts rpmtsFree(rpmts ts) if (ts->nrefs > 0) return NULL; +/*@-nullstate@*/ /* FIX: partial annotations */ + rpmtsEmpty(ts); +/*@=nullstate@*/ + (void) rpmtsCloseDB(ts); (void) rpmtsCloseSDB(ts); + ts->removedPackages = _free(ts->removedPackages); + ts->availablePackages = rpmalFree(ts->availablePackages); ts->numAvailablePackages = 0; ts->dsi = _free(ts->dsi); - ts->removedPackages = _free(ts->removedPackages); + if (ts->scriptFd != NULL) { ts->scriptFd = fdFree(ts->scriptFd, "rpmtsFree"); ts->scriptFd = NULL; @@ -595,25 +627,16 @@ rpmts rpmtsFree(rpmts ts) ts->rootDir = _free(ts->rootDir); ts->currDir = _free(ts->currDir); - for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) { -/*@-type -unqualifiedtrans @*/ - ts->order[oc] = rpmteFree(ts->order[oc]); -/*@=type =unqualifiedtrans @*/ - } - pi = rpmtsiFree(pi); /*@-type +voidabstract @*/ /* FIX: double indirection */ ts->order = _free(ts->order); /*@=type =voidabstract @*/ + ts->orderAlloced = 0; if (ts->pkpkt != NULL) ts->pkpkt = _free(ts->pkpkt); ts->pkpktlen = 0; memset(ts->pksignid, 0, sizeof(ts->pksignid)); -/*@-nullstate@*/ /* FIX: partial annotations */ - rpmtsClean(ts); -/*@=nullstate@*/ - /*@-refcounttrans@*/ ts = _free(ts); /*@=refcounttrans@*/ /*@=usereleased@*/ diff --git a/lib/rpmts.h b/lib/rpmts.h index d729d7d..1aa882e 100644 --- a/lib/rpmts.h +++ b/lib/rpmts.h @@ -424,13 +424,20 @@ void rpmtsCleanDig(rpmts ts) /*@modifies ts @*/; /** \ingroup rpmts - * Re-create an empty transaction set. + * Free memory needed only for dependency checks and ordering. * @param ts transaction set */ void rpmtsClean(rpmts ts) /*@modifies ts @*/; /** \ingroup rpmts + * Re-create an empty transaction set. + * @param ts transaction set + */ +void rpmtsEmpty(rpmts ts) + /*@modifies ts @*/; + +/** \ingroup rpmts * Destroy transaction set, closing the database as well. * @param ts transaction set * @return NULL always diff --git a/lib/verify.c b/lib/verify.c index a586125..fcb7f3a 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -372,7 +372,7 @@ static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts, int xx; int i; - rpmtsClean(ts); + rpmtsEmpty(ts); (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL); xx = rpmtsCheck(ts); @@ -419,7 +419,7 @@ static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts, ps = rpmpsFree(ps); - rpmtsClean(ts); + rpmtsEmpty(ts); return rc; } @@ -493,7 +493,7 @@ int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv) if (argv != NULL) while ((arg = *argv++) != NULL) { ec += rpmQueryVerify(qva, ts, arg); - rpmtsClean(ts); + rpmtsEmpty(ts); } /*@=boundsread@*/ } @@ -502,5 +502,7 @@ int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv) if (qva->qva_showPackage == showVerifyPackage) qva->qva_showPackage = NULL; + rpmtsEmpty(ts); + return ec; } diff --git a/python/rpmts-py.c b/python/rpmts-py.c index 8deac8a..c413f3d 100644 --- a/python/rpmts-py.c +++ b/python/rpmts-py.c @@ -105,16 +105,12 @@ static int _rpmts_debug = 0; * rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a * requirement or a conflict. * - * - order() Do a topological sort of added element relations. + * - ts.order() Do a topological sort of added element relations. * @return None * - * - run(flags,problemSetFilter,callback,data) Attempt to execute a - * transaction set. After the transaction set has been populated - * with install and upgrade actions, it can be executed by invoking - * the run() method. - * @param flags - modifies the behavior of the transaction set as it is - * processed. The following values can be locical ORed - * together: + * - ts.setFlags(transFlags) Set transaction set flags. + * @param transFlags - bit(s) to controll transaction operations. The + * following values can be logically OR'ed together: * - rpm.RPMTRANS_FLAG_TEST - test mode, do not modify the RPM * database, change any files, or run any package scripts * - rpm.RPMTRANS_FLAG_BUILD_PROBS - only build a list of @@ -130,6 +126,12 @@ static int _rpmts_debug = 0; * being performed. * - rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted * packages. + * @return previous transFlags + * + * - run(problemSetFilter,callback,data) Attempt to execute a + * transaction set. After the transaction set has been populated + * with install and upgrade actions, it can be executed by invoking + * the run() method. * @param problemSetFilter - control bit(s) to ignore classes of problems, * any of * - rpm.RPMPROB_FILTER_IGNOREOS - @@ -929,20 +931,34 @@ rpmtsCallback(/*@unused@*/ const void * hd, const rpmCallbackType what, const void * pkgKey, rpmCallbackData data) /*@*/ { + Header h = (Header) hd; struct rpmtsCallbackType_s * cbInfo = data; + PyObject * pkgObj = (PyObject *) pkgKey; PyObject * args, * result; static FD_t fd; if (cbInfo->pythonError) return NULL; if (cbInfo->cb == Py_None) return NULL; - if (!pkgKey) pkgKey = Py_None; + /* Synthesize a python object for callback (if necessary). */ + if (pkgObj == NULL) { + if (h) { + const char * n = NULL; + (void) headerNVR(h, &n, NULL, NULL); + pkgObj = Py_BuildValue("s", n); + } else { + pkgObj = Py_None; + Py_INCREF(pkgObj); + } + } else + Py_INCREF(pkgObj); PyEval_RestoreThread(cbInfo->_save); - args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data); + args = Py_BuildValue("(illOO)", what, amount, total, pkgObj, cbInfo->data); result = PyEval_CallObject(cbInfo->cb, args); Py_DECREF(args); + Py_DECREF(pkgObj); if (!result) { cbInfo->pythonError = 1; @@ -984,17 +1000,34 @@ fprintf(stderr, "\t%ld:%ld key %p\n", amount, total, pkgKey); /** \ingroup python */ +static PyObject * rpmts_SetFlags(rpmtsObject * s, PyObject * args) + /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/ + /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/ +{ + rpmtransFlags transFlags = 0; + + if (!PyArg_ParseTuple(args, "i:SetFlags", &transFlags)) + return NULL; + +if (_rpmts_debug) +fprintf(stderr, "*** rpmts_SetFlags(%p) ts %p transFlags %x\n", s, s->ts, transFlags); + + return Py_BuildValue("i", rpmtsSetFlags(s->ts, transFlags)); +} + +/** \ingroup python + */ static PyObject * rpmts_Run(rpmtsObject * s, PyObject * args) /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/ /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/ { - int flags, ignoreSet; + int ignoreSet; int rc, i; PyObject * list; rpmps ps; struct rpmtsCallbackType_s cbInfo; - if (!PyArg_ParseTuple(args, "iiOO:Run", &flags, &ignoreSet, &cbInfo.cb, + if (!PyArg_ParseTuple(args, "iOO:Run", &ignoreSet, &cbInfo.cb, &cbInfo.data)) return NULL; @@ -1010,10 +1043,9 @@ static PyObject * rpmts_Run(rpmtsObject * s, PyObject * args) (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo); } - (void) rpmtsSetFlags(s->ts, flags); if (_rpmts_debug) -fprintf(stderr, "*** rpmts_Run(%p) ts %p flags %x ignore %x\n", s, s->ts, s->ts->transFlags, ignoreSet); +fprintf(stderr, "*** rpmts_Run(%p) ts %p ignore %x\n", s, s->ts, ignoreSet); rc = rpmtsRun(s->ts, NULL, ignoreSet); ps = rpmtsProblems(s->ts); @@ -1173,6 +1205,10 @@ static struct PyMethodDef rpmts_methods[] = { NULL }, {"order", (PyCFunction) rpmts_Order, METH_VARARGS, NULL }, + {"setFlags", (PyCFunction) rpmts_SetFlags, METH_VARARGS, +"ts.setFlags(transFlags) -> previous transFlags\n\ +- Set control bit(s) for processing a transaction set.\n\ + Note: This method sets bit(s) passed as the first argument to ts.run()\n" }, {"run", (PyCFunction) rpmts_Run, METH_VARARGS, NULL }, {"clean", (PyCFunction) rpmts_Clean, METH_VARARGS, diff --git a/rpm.spec.in b/rpm.spec.in index b166104..efb3308 100644 --- a/rpm.spec.in +++ b/rpm.spec.in @@ -17,7 +17,7 @@ Name: rpm %define version @VERSION@ Version: %{version} %{expand: %%define rpm_version %{version}} -Release: 0.80 +Release: 0.81 Group: System Environment/Base Source: ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.0.x/rpm-%{rpm_version}.tar.gz Copyright: GPL @@ -519,8 +519,15 @@ fi %{__prefix}/include/popt.h %changelog +* Thu Aug 15 2002 Jeff Johnson 4.1-0.81 +- rollback: re-create empty transaction set for multiple rollbacks. +- fix: %%basename typo (Dmitry V. Levin). +- fix: queryformat segfaults (Dmitry V. Levin). + * Wed Aug 14 2002 Jeff Johnson 4.1-0.80 - fix: rebuilddb stat'ed target, not source, for rename sanity, take 2. +- python: explicit method to set transFlags. +- python: stuff package name into a string for repackage/erase callbacks. * Tue Aug 13 2002 Jeff Johnson 4.1-0.79 - supply transitive closure for CLI packages from rpmdb-redhat database. diff --git a/rpmdb/header.c b/rpmdb/header.c index ea8aac5..e16782f 100644 --- a/rpmdb/header.c +++ b/rpmdb/header.c @@ -2507,7 +2507,8 @@ static int parseExpression(sprintfToken token, char * str, &token->u.cond.numIfTokens, &end, PARSER_IN_EXPR, errmsg)) return 1; - if (!*end) { + /* XXX fix segfault on "rpm -q rpm --qf='%|NAME?{%}:{NAME}|\n'"*/ + if (!(end && *end)) { /*@-observertrans -readonlytrans@*/ if (errmsg) *errmsg = _("} expected in expression"); /*@=observertrans =readonlytrans@*/ @@ -2552,7 +2553,9 @@ static int parseExpression(sprintfToken token, char * str, &token->u.cond.numElseTokens, &end, PARSER_IN_EXPR, errmsg)) return 1; - if (!*end) { + + /* XXX fix segfault on "rpm -q rpm --qf='%|NAME?{a}:{%}|{NAME}\n'" */ + if (!(end && *end)) { /*@-observertrans -readonlytrans@*/ if (errmsg) *errmsg = _("} expected in expression"); /*@=observertrans =readonlytrans@*/ diff --git a/rpmio/macro.c b/rpmio/macro.c index 4610555..1498f68 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -1061,6 +1061,8 @@ doFoo(MacroBuf mb, int negate, const char * f, size_t fn, if (STREQ("basename", f, fn)) { if ((b = strrchr(buf, '/')) == NULL) b = buf; + else + b++; #if NOTYET /* XXX watchout for conflict with %dir */ } else if (STREQ("dirname", f, fn)) { diff --git a/tools/Makefile.am b/tools/Makefile.am index 9c62bcf..61e75d4 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -15,7 +15,7 @@ INCLUDES = -I. \ EXTRA_DIST = rpminject.c rpmsort.c -EXTRA_PROGRAMS = rpminject rpmsort tblob +EXTRA_PROGRAMS = rpminject rpmsort LDADD = \ $(top_builddir)/build/librpmbuild.la \ @@ -48,7 +48,4 @@ rpminject_LDFLAGS = @LDFLAGS_STATIC@ rpmsort_SOURCES = rpmsort.c rpmsort_LDFLAGS = @LDFLAGS_STATIC@ -tblob_SOURCES = tblob.c -tblob_LDFLAGS = @LDFLAGS_STATIC@ - $(PROGRAMS): $(LDADD) -- 2.7.4