RPM Community Forums

Mailing List Message of <rpm-devel>

Re: [CVS] RPM: rpm/ CHANGES rpm/lib/ rpmgi.c rpmgi.h rpminstall.c tgi.c

From: Jeff Johnson <n3npq@mac.com>
Date: Sat 02 Feb 2008 - 23:05:52 CET
Message-Id: <79C3C117-E5C1-4C3D-8916-0D6B7E0C86F9@mac.com>
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
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.