This change likely needs some explanation ...
The goal is to rewrite a "+bing" argument passed to -i/-U with a full
path
to a package file.
There's configuration that is needed to use (change "/X/time" to taste):
echo "%_rpmgi_prefix /X/time" >> /etc/rpm/macros
And (duh!) the directory needs *.rpm content:
$ ls -1 /X/time/*.rpm
/X/time/time-1.7-27.i386.rpm
/X/time/time-1.7-30.i386.rpm
/X/time/time-1.7-30.src.rpm
/X/time/time-1.7-31.i386.rpm
/X/time/time-1.7-31.src.rpm
With configuration/content in place, then an install looks like:
$ sudo rpm -Uvh +time
Preparing...
########################################### [100%]
1:time
########################################### [100%]
(aside) I spent a couple hours trying to write the glob equivalent
of the tail anchored RE pattern
static const char * pkgpat = "-[^-]*-[^-]*.[^.]*.rpm$";
If glob output is not filtered, then there are confusions between, say,
glibc-*.rpm and glibc-common-*.rpm returned from a glob.
I finally ended up applying the RE pattern to filter the glob output
so that
I could get an initial implementation in place.
Anyone got a better glob expression to use? The internal GNU glob in
rpm also supports ksh fnmatch extensions, if that matters.
Bleeping uglix hurts my head sometimes, sigh.
73 de Jeff
On Feb 2, 2008, at 4:45 PM, Jeff Johnson wrote:
> RPM Package Manager, CVS Repository
> http://rpm5.org/cvs/
>
> ______________________________________________________________________
> ______
>
> Server: rpm5.org Name: Jeff Johnson
> Root: /v/rpm/cvs Email: jbj@rpm5.org
> Module: rpm Date: 02-Feb-2008
> 22:45:18
> Branch: HEAD Handle: 2008020221451701
>
> Modified files:
> rpm CHANGES
> rpm/lib rpmgi.c rpmgi.h rpminstall.c tgi.c
>
> Log:
> - functional "+N-V-R.A" path-to-repository expansions with -i/-U.
>
> Summary:
> Revision Changes Path
> 1.2125 +1 -0 rpm/CHANGES
> 2.50 +1 -10 rpm/lib/rpmgi.c
> 2.25 +11 -0 rpm/lib/rpmgi.h
> 1.192 +51 -26 rpm/lib/rpminstall.c
> 2.17 +125 -14 rpm/lib/tgi.c
>
> ______________________________________________________________________
> ______
>
> patch -p0 <<'@@ .'
> Index: rpm/CHANGES
>
> ======================================================================
> ======
> $ cvs diff -u -r1.2124 -r1.2125 CHANGES
> --- rpm/CHANGES 2 Feb 2008 01:33:19 -0000 1.2124
> +++ rpm/CHANGES 2 Feb 2008 21:45:17 -0000 1.2125
> @@ -1,4 +1,5 @@
> 5.0.0 -> 5.1a1:
> + - jbj: functional "+N-V-R.A" path-to-repository expansions
> with -i/-U.
> - jbj: mire.c: add STANDALONE test exerciser.
> - jbj: use struct timeval timestamp for INSTALL{TID,TIME}
> and ORIGIN{TID,TIME}.
> Note: TID.usec field is always 0 atm.
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/lib/rpmgi.c
>
> ======================================================================
> ======
> $ cvs diff -u -r2.49 -r2.50 rpmgi.c
> --- rpm/lib/rpmgi.c 31 Jan 2008 15:35:09 -0000 2.49
> +++ rpm/lib/rpmgi.c 2 Feb 2008 21:45:18 -0000 2.50
> @@ -125,16 +125,7 @@
> return rpmrc;
> }
>
> -/**
> - * Return header from package.
> - * @param gi generalized iterator
> - * @param path file path
> - * @return header (NULL on failure)
> - */
> -/*@null@*/
> -static Header rpmgiReadHeader(rpmgi gi, const char * path)
> - /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
> - /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
> +Header rpmgiReadHeader(rpmgi gi, const char * path)
> {
> FD_t fd = rpmgiOpen(path, "r%{?_rpmgio}");
> Header h = NULL;
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/lib/rpmgi.h
>
> ======================================================================
> ======
> $ cvs diff -u -r2.24 -r2.25 rpmgi.h
> --- rpm/lib/rpmgi.h 8 Dec 2007 19:36:29 -0000 2.24
> +++ rpm/lib/rpmgi.h 2 Feb 2008 21:45:18 -0000 2.25
> @@ -217,6 +217,17 @@
> /*@globals internalState @*/
> /*@modifies gi, internalState @*/;
>
> +/**
> + * Return header from package.
> + * @param gi generalized iterator
> + * @param path file path
> + * @return header (NULL on failure)
> + */
> +/*@null@*/
> +Header rpmgiReadHeader(rpmgi gi, const char * path)
> + /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
> + /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/;
> +
> /*@}*/
>
> #ifdef __cplusplus
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/lib/rpminstall.c
>
> ======================================================================
> ======
> $ cvs diff -u -r1.191 -r1.192 rpminstall.c
> --- rpm/lib/rpminstall.c 31 Jan 2008 15:35:09 -0000 1.191
> +++ rpm/lib/rpminstall.c 2 Feb 2008 21:45:18 -0000 1.192
> @@ -17,6 +17,7 @@
> #include "rpmte.h" /* XXX rpmtsPrint() */
>
> #include "manifest.h"
> +#define _RPMGI_INTERNAL /* XXX "+bing" args need gi->h. */
> #include "rpmgi.h"
> #include "debug.h"
>
> @@ -331,6 +332,38 @@
> return 0;
> }
>
> +static const char * rpmcliInstallElementPath(rpmts ts, const
> char * arg)
> +{
> + static const char * pkgpat = "-[^-]*-[^-]*.[^.]*.rpm$";
> + const char * mirePattern = rpmExpand(&arg[1], pkgpat, NULL);
> + miRE mire = mireNew(RPMMIRE_REGEX, 0);
> + const char * fn = NULL;
> + ARGV_t av = NULL;
> + int ac = 0;
> + int xx = mireRegcomp(mire, mirePattern);
> + int i;
> +
> + /* Get list of candidate package paths. */
> + /* XXX note the added "-*.rpm" to force globbing on '-'
> boundaries. */
> + fn = rpmGetPath("%{?_rpmgi_prefix:%{?_rpmgi_prefix}/}", arg,
> "-*.rpm", NULL);
> + xx = rpmGlob(fn, &ac, &av);
> + fn = _free(fn);
> +
> + /* Filter out glibc <-> glibc-common confusions. */
> + for (i = 0; i < ac; i++) {
> + if (mireRegexec(mire, av[i]))
> + continue;
> + fn = xstrdup(av[0]);
> + break;
> + }
> +
> + av = argvFree(av);
> + mire = mireFree(mire);
> + mirePattern = _free(mirePattern);
> +
> + return fn;
> +}
> +
> /** @todo Generalize --freshen policies. */
> int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv)
> {
> @@ -400,35 +433,12 @@
> relocations = NULL;
> }
>
> -#if defined(REFERENCE_FORNOW)
> -if (fileURL[0] == '=') {
> - rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1,
> NULL, 0);
> -
> - xx = rpmtsSolve(ts, this, NULL);
> - if (ts->suggests && ts->nsuggests > 0) {
> - fileURL = _free(fileURL);
> - fileURL = ts->suggests[0];
> - ts->suggests[0] = NULL;
> - while (ts->nsuggests-- > 0) {
> - if (ts->suggests[ts->nsuggests] == NULL)
> - continue;
> - ts->suggests[ts->nsuggests] = _free(ts->suggests[ts-
> >nsuggests]);
> - }
> - ts->suggests = _free(ts->suggests);
> - rpmlog(RPMLOG_DEBUG, D_("Adding goal: %s\n"), fileURL);
> - pkgURL[pkgx] = fileURL;
> - fileURL = NULL;
> - pkgx++;
> - }
> - this = rpmdsFree(this);
> -} else
> -#endif
> -
> { /* start-of-transaction-build */
> int tag = (ia->qva_source == RPMQV_FTSWALK)
> ? RPMDBI_FTSWALK : RPMDBI_ARGLIST;
> rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
> rpmgiFlags _giFlags = RPMGI_NONE;
> + const char * fn = NULL;;
>
> /*@-mods@*/
> if (ftsOpts == 0)
> @@ -436,10 +446,24 @@
> /*@=mods@*/
> rc = rpmgiSetArgs(gi, argv, ftsOpts, _giFlags);
> while (rpmgiNext(gi) == RPMRC_OK) {
> - const char * fn = rpmgiHdrPath(gi);
> Header h;
>
> - /* === Check for erasures within install transaction. */
> + fn = _free(fn);
> + fn = xstrdup(rpmgiHdrPath(gi));
> +
> + /* === Check for "+bing" lookaside paths within install
> transaction. */
> + if (fn[0] == '+') {
> + const char * nfn = rpmcliInstallElementPath(ts, &fn[1]);
> + fn = _free(fn);
> + fn = nfn;
> + /* XXX hack into rpmgi innards for now ... */
> + h = rpmgiReadHeader(gi, fn);
> + if (h)
> + gi->h = headerLink(h);
> + h = headerFree(h);
> + }
> +
> + /* === Check for "-bang" erasures within install transaction. */
> if (fn[0] == '-') {
> switch (rpmcliEraseElement(ts, &fn[1])) {
> case RPMRC_OK:
> @@ -518,6 +542,7 @@
> numRPMS++;
> }
>
> + fn = _free(fn);
> gi = rpmgiFree(gi);
>
> } /* end-of-transaction-build */
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/lib/tgi.c
>
> ======================================================================
> ======
> $ cvs diff -u -r2.16 -r2.17 tgi.c
> --- rpm/lib/tgi.c 2 Feb 2008 17:53:28 -0000 2.16
> +++ rpm/lib/tgi.c 2 Feb 2008 21:45:18 -0000 2.17
> @@ -2,7 +2,12 @@
>
> #include <rpmio.h>
> #include <rpmmacro.h>
> +#include <argv.h>
> +#include <mire.h>
> #include <rpmcb.h>
> +
> +#include <rpmdb.h>
> +
> #include <rpmgi.h>
> #include <rpmcli.h>
>
> @@ -12,12 +17,10 @@
>
> #include "debug.h"
>
> -static const char * gitagstr = "packages";
> +static const char * gitagstr = NULL;
> static const char * gikeystr = NULL;
> static rpmtransFlags transFlags = 0;
> -#ifdef DYING
> -static rpmgiFlags giFlags = 0;
> -#endif
> +static rpmdepFlags depFlags = 0;
>
> static const char * queryFormat = NULL;
> static const char * defaultQueryFormat =
> @@ -42,6 +45,63 @@
> return val;
> }
>
> +static rpmRC rpmcliEraseElement(rpmts ts, const char * arg)
> +{
> + rpmdbMatchIterator mi;
> + Header h;
> + rpmRC rc = RPMRC_OK;
> + int xx;
> +
> + mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0);
> + if (mi == NULL)
> + return RPMRC_NOTFOUND;
> +
> + while ((h = rpmdbNextIterator(mi)) != NULL) {
> + unsigned int recOffset = rpmdbGetIteratorOffset(mi);
> +
> + if (recOffset == 0) { /* XXX can't happen. */
> + rc = RPMRC_FAIL;
> + break;
> + }
> + xx = rpmtsAddEraseElement(ts, h, recOffset);
> + }
> + mi = rpmdbFreeIterator(mi);
> +
> + return 0;
> +}
> +
> +static const char * rpmcliInstallElementPath(rpmts ts, const
> char * arg)
> +{
> + static const char * pkgpat = "-[^-]*-[^-]*.[^.]*.rpm$";
> + const char * mirePattern = rpmExpand(&arg[1], pkgpat, NULL);
> + miRE mire = mireNew(RPMMIRE_REGEX, 0);
> + const char * fn = NULL;
> + ARGV_t av = NULL;
> + int ac = 0;
> + int xx = mireRegcomp(mire, mirePattern);
> + int i;
> +
> + /* Get list of candidate package paths. */
> + /* XXX note the added "-*.rpm" to force globbing on '-'
> boundaries. */
> + fn = rpmGetPath("%{?_rpmgi_prefix:%{?_rpmgi_prefix}/}", arg,
> "-*.rpm", NULL);
> + xx = rpmGlob(fn, &ac, &av);
> + fn = _free(fn);
> +
> + /* Filter out glibc <-> glibc-common confusions. */
> + for (i = 0; i < ac; i++) {
> + if (mireRegexec(mire, av[i]))
> + continue;
> + fn = xstrdup(av[0]);
> + break;
> + }
> +
> + av = argvFree(av);
> + mire = mireFree(mire);
> + mirePattern = _free(mirePattern);
> +
> + return fn;
> +}
> +
> static struct poptOption optionsTable[] = {
> { "rpmgidebug", 'd', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN,
> &_rpmgi_debug, -1,
> N_("debug generalized iterator"), NULL},
> @@ -86,9 +146,12 @@
> poptContext optCon;
> rpmts ts = NULL;
> rpmVSFlags vsflags;
> + int numRPMS = 0;
> + int numFailed = 0;
> rpmgi gi = NULL;
> - int gitag = RPMDBI_PACKAGES;
> - const char ** av;
> + int gitag = RPMDBI_ARGLIST;
> + const char * fn = NULL;
> + ARGV_t av;
> int ac;
> int rc = 0;
>
> @@ -107,10 +170,13 @@
> }
> }
>
> + av = poptGetArgs(optCon);
> +
> /* XXX ftswalk segfault with no args. */
>
> ts = rpmtsCreate();
> (void) rpmtsSetFlags(ts, transFlags);
> + (void) rpmtsSetDFlags(ts, depFlags);
>
> vsflags = rpmExpandNumeric("%{?_vsflags_query}");
> if (rpmcliQueryFlags & VERIFY_DIGEST)
> @@ -121,25 +187,70 @@
> vsflags |= RPMVSF_NOHDRCHK;
> (void) rpmtsSetVSFlags(ts, vsflags);
>
> - { uint32_t tid = (uint32_t) time(NULL);
> - (void) rpmtsSetTid(ts, tid);
> - }
> -
> gi = rpmgiNew(ts, gitag, gikeystr, 0);
>
> - av = poptGetArgs(optCon);
> (void) rpmgiSetArgs(gi, av, ftsOpts, giFlags);
>
> +#if defined(REFERENCE_FORNOW)
> +if (fileURL[0] == '=') {
> + rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1,
> NULL, 0);
> +
> + xx = rpmtsSolve(ts, this, NULL);
> + if (ts->suggests && ts->nsuggests > 0) {
> + fileURL = _free(fileURL);
> + fileURL = ts->suggests[0];
> + ts->suggests[0] = NULL;
> + while (ts->nsuggests-- > 0) {
> + if (ts->suggests[ts->nsuggests] == NULL)
> + continue;
> + ts->suggests[ts->nsuggests] = _free(ts->suggests[ts-
> >nsuggests]);
> + }
> + ts->suggests = _free(ts->suggests);
> + rpmlog(RPMLOG_DEBUG, D_("Adding goal: %s\n"), fileURL);
> + pkgURL[pkgx] = fileURL;
> + fileURL = NULL;
> + pkgx++;
> + }
> + this = rpmdsFree(this);
> +} else
> +#endif
> +
> ac = 0;
> while (rpmgiNext(gi) == RPMRC_OK) {
> +
> + fn = _free(fn);
> + fn = xstrdup(rpmgiHdrPath(gi));
> +
> + /* === Check for "+bing" lookaside paths within install
> transaction. */
> + if (fn[0] == '+') {
> + const char * nfn = rpmcliInstallElementPath(ts, &fn[1]);
> + fn = _free(fn);
> + fn = nfn;
> + }
> +
> + /* === Check for "-bang" erasures within install transaction. */
> + if (fn[0] == '-') {
> + switch (rpmcliEraseElement(ts, &fn[1])) {
> + case RPMRC_OK:
> + numRPMS++; /* XXX multiple erasures? */
> + break;
> + case RPMRC_NOTFOUND:
> + default:
> + rpmlog(RPMLOG_ERR, _("package %s cannot be erased\n"), &fn[1]);
> + numFailed++; /* XXX multiple erasures? */
> + break;
> + }
> + continue;
> + }
> +
> if (!(giFlags & RPMGI_TSADD)) {
> const char * arg = rpmgiPathOrQF(gi);
> -
> - fprintf(stdout, "%5d %s\n", ac, arg);
> - arg = _free(arg);
> + fprintf(stdout, "%5d %s\n", ac, fn);
> + fn = _free(arg);
> }
> ac++;
> }
> + fn = _free(fn);
>
> if (giFlags & RPMGI_TSORDER) {
> rpmtsi tsi;
> @@ .
> ______________________________________________________________________
> RPM Package Manager http://rpm5.org
> CVS Sources Repository rpm-cvs@rpm5.org
Received on Sat Feb 2 23:06:04 2008