Re: [Rpm-maint] RFC: experiments with rich dependencies
Hi, I tested this feature a little and I find the following problem. I have package testA that requires (testB | testC). I tried to installed it. # rpm -i testA-1-1.x86_64.rpm error: Failed dependencies: (testB | testC) is needed by testA-1-1.x86_64 # rpm -i testA-1-1.x86_64.rpm testB-1-1.x86_64.rpm # rpm -q testA testA-1-1.x86_64 #rpm -q testB testB-1-1.x86_64 That's ok. Now I have successfully installed packages testA and testB. But then I tried to uninstall package testB. # rpm -e testB # rpm -q testB package testB is not installed And this is problem I shouldn't be able to unistall package testB because it is required by testA. This problem was created in commit 8674de47 on line 2108 in lib/rpmdb.c. The last char of string name is cut off no matter if that char is white char or not. Try this: # rpm -q --whatrequires testB no package requires testB # rpm -q --whatrequries test # Now without the last char testA-1-1.x86_64 testA-1-1.x86_64 Lubos - Original Message - From: Michael Schroeder m...@suse.de To: Panu Matilainen pmati...@redhat.com Cc: rpm-maint@lists.rpm.org Sent: Friday, September 12, 2014 6:06:15 PM Subject: Re: [Rpm-maint] RFC: experiments with rich dependencies On Thu, Sep 11, 2014 at 03:18:19PM +0300, Panu Matilainen wrote: With rpm 4.12 branched out and new development cycle just starting, this would be the prime time to land in such big new features and AFAICS this would make for a fine starting point for further refining. I'd say go ahead and push this pretty much as-is [**], unless others have objections. Florian? Ok, pushed. Happy hacking, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On Thu, Sep 11, 2014 at 03:18:19PM +0300, Panu Matilainen wrote: With rpm 4.12 branched out and new development cycle just starting, this would be the prime time to land in such big new features and AFAICS this would make for a fine starting point for further refining. I'd say go ahead and push this pretty much as-is [**], unless others have objections. Florian? Ok, pushed. Happy hacking, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On 09/09/2014 06:33 PM, Michael Schroeder wrote: On Mon, Sep 08, 2014 at 04:51:12PM +0200, Michael Schroeder wrote: Hi Panu et al, Hi, attached is an updated version of my rich dependencies patch. I cleanup up the code a bit, now we have only one generic parser instead of three specialized ones, and we use a callback function to do the needed work. New version attached: some bugs fixed plus the ordering code now also understands rich deps. I still haven't had a chance to look at this in any greater detail, but overall it is looking quite nice really, and the basics seem to be working fine. I did find one unexpected complication [*] in the concept in my brief testing, and in all likelihood there are more cases nobody thought of etc... Just like we're still finding uncovered cases with the plain old provide/requires/conflicts/obsoletes handling. With rpm 4.12 branched out and new development cycle just starting, this would be the prime time to land in such big new features and AFAICS this would make for a fine starting point for further refining. I'd say go ahead and push this pretty much as-is [**], unless others have objections. Florian? Thanks, - Panu - [*] IF-dependencies have similar issues as reverse dependencies: one can break somebody elses dependencies by installing some seemingly unrelated package. Perhaps they should be limited to weak dependencies. [**] Minor nits from assigning pointers to 0 instead of NULL here and there. Other non-showstopper notes: haveRichDep() could use the new rpmds array (similar to commit 622e0661532ac65e4094f4f7046f01fcd35e0a76) and duplication of struct ReqComp (probably belongs to rpmds.c with some kind of api though) ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On 09/11/2014 02:18 PM, Panu Matilainen wrote: [*] IF-dependencies have similar issues as reverse dependencies: one can break somebody elses dependencies by installing some seemingly unrelated package. Perhaps they should be limited to weak dependencies. That's not exactly the same situation. Reverse Requires can make your installation broken by adding a package to the repository. While I agree tha most use case should and will probably use weak dependencies I do not see anything intrinsicly wrong about forcing in an intermediate package (or act as a conflict in case this package is not available) Florian -- Red Hat GmbH, http://www.de.redhat.com/ Registered seat: Grasbrunn, Commercial register: Amtsgericht Muenchen, HRB 153243, Managing Directors: Charles Cachera, Michael Cunningham, Michael O'Neill, Charles Peters ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On Thu, Sep 11, 2014 at 03:18:19PM +0300, Panu Matilainen wrote: I did find one unexpected complication [*] in the concept in my brief testing, and in all likelihood there are more cases nobody thought of etc... Just like we're still finding uncovered cases with the plain old provide/requires/conflicts/obsoletes handling. But you can't break an installed package by installing an unrelated package, you should get a conflict. (If that doesn't happen you have found a bug.) The problem with reverse requires is that you can add a dependency problem by just adding a repository. This can't happen with IF. With rpm 4.12 branched out and new development cycle just starting, this would be the prime time to land in such big new features and AFAICS this would make for a fine starting point for further refining. I'd say go ahead and push this pretty much as-is [**], unless others have objections. Florian? Ah, but I was hoping for a discussion of the syntax. Are you ok with the enclosing the rich deps with ()? What about the op names, I'd love to use as 'and' and | as 'or' (which also makes it more like Debian), but I can't think of any good charater for 'if'. Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On 09/11/2014 02:51 PM, Michael Schroeder wrote: Ah, but I was hoping for a discussion of the syntax. Are you ok with the enclosing the rich deps with ()? What about the op names, I'd love to use as 'and' and | as 'or' (which also makes it more like Debian), but I can't think of any good charater for 'if'. Formally the sign would be - (reverse implication). But I kinda doubt that most people would get that. Florian -- Red Hat GmbH, http://www.de.redhat.com/ Registered seat: Grasbrunn, Commercial register: Amtsgericht Muenchen, HRB 153243, Managing Directors: Charles Cachera, Michael Cunningham, Michael O'Neill, Charles Peters ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On 09/11/2014 03:51 PM, Michael Schroeder wrote: On Thu, Sep 11, 2014 at 03:18:19PM +0300, Panu Matilainen wrote: I did find one unexpected complication [*] in the concept in my brief testing, and in all likelihood there are more cases nobody thought of etc... Just like we're still finding uncovered cases with the plain old provide/requires/conflicts/obsoletes handling. But you can't break an installed package by installing an unrelated package, you should get a conflict. (If that doesn't happen you have found a bug.) Mm, must've accidentally installed the unrelated package with system rpm instead of the one aware of rich deps, at least I cant reproduce it anymore. Apologies for the false alarm. The problem with reverse requires is that you can add a dependency problem by just adding a repository. This can't happen with IF. With rpm 4.12 branched out and new development cycle just starting, this would be the prime time to land in such big new features and AFAICS this would make for a fine starting point for further refining. I'd say go ahead and push this pretty much as-is [**], unless others have objections. Florian? Ah, but I was hoping for a discussion of the syntax. Are you ok with the enclosing the rich deps with ()? What about the op names, I'd love to use as 'and' and | as 'or' (which also makes it more like Debian), but I can't think of any good charater for 'if'. Enclosing with () seems fine to me. I dunno about the average packager but I too would much rather have | and (or better yet, make that || and ) for 'or' and 'and' ops. For 'if', perhaps a loosely C-like ? operator would work. For example, A or B would become B ? A which could also be extended to Requires: B ? A : C, as in if B is installed require A, otherwise require C. - Panu - ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On Thu, Sep 11, 2014 at 03:02:15PM +0200, Florian Festi wrote: On 09/11/2014 02:51 PM, Michael Schroeder wrote: Ah, but I was hoping for a discussion of the syntax. Are you ok with the enclosing the rich deps with ()? What about the op names, I'd love to use as 'and' and | as 'or' (which also makes it more like Debian), but I can't think of any good charater for 'if'. Formally the sign would be - (reverse implication). But I kinda doubt that most people would get that. Formally we can also use |~ i.e. OR_NOT ;) Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} ___ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint
Re: [Rpm-maint] RFC: experiments with rich dependencies
On Mon, Sep 08, 2014 at 04:51:12PM +0200, Michael Schroeder wrote: Hi Panu et al, attached is an updated version of my rich dependencies patch. I cleanup up the code a bit, now we have only one generic parser instead of three specialized ones, and we use a callback function to do the needed work. New version attached: some bugs fixed plus the ordering code now also understands rich deps. Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} diff --git a/build/pack.c b/build/pack.c index 74471d9..fee89b5 100644 --- a/build/pack.c +++ b/build/pack.c @@ -265,6 +265,29 @@ static int haveTildeDep(Header h) return 0; } +static int depContainsRich(Header h, rpmTagVal tagFlags) +{ +struct rpmtd_s flags; +rpm_flag_t *flag = NULL; + +if (headerGet(h, tagFlags, flags, HEADERGET_MINMEM)) { +while ((flag = rpmtdNextUint32(flags)) != NULL) +if (*flag RPMSENSE_RICH) +break; +rpmtdFreeData(flags); +} +return flag != NULL; +} + +static int haveRichDep(Header h) +{ +if (depContainsRich(h, RPMTAG_REQUIREFLAGS)) + return 1; +if (depContainsRich(h, RPMTAG_CONFLICTFLAGS)) + return 1; +return 0; +} + static rpm_loff_t estimateCpioSize(Package pkg) { rpmfi fi; @@ -438,6 +461,10 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, if (haveTildeDep(pkg-header)) (void) rpmlibNeedsFeature(pkg, TildeInVersions, 4.10.0-1); +/* check if the package has a rich dependency */ +if (haveRichDep(pkg-header)) + (void) rpmlibNeedsFeature(pkg, RichDependencies, 4.12.0-1); + /* All dependencies added finally, write them into the header */ for (int i = 0; i PACKAGE_NUM_DEPS; i++) { /* Nuke any previously added dependencies from the header */ diff --git a/build/parseReqs.c b/build/parseReqs.c index 37ee1fc..eaf10fb 100644 --- a/build/parseReqs.c +++ b/build/parseReqs.c @@ -68,6 +68,70 @@ static rpmRC checkDep(rpmSpec spec, char *N, char *EVR, char **emsg) return RPMRC_OK; } +struct parseRCPOTRichData { +rpmSpec spec; +StringBuf sb; +int no_if; +int stacked_if; +}; + +/* Callback for the rich dependency parser. We use this to do check for invalid + * characters and to build a normailzed version of the dependency */ +static rpmRC parseRCPOTRichCB(void *cbdata, int type, + const char *n, int nl, const char *e, int el, rpmsenseFlags sense, + rpmrichOp op, char **emsg) { +struct parseRCPOTRichData *data = cbdata; +StringBuf sb = data-sb; +rpmRC rc = RPMRC_OK; + +if (type == RPMRICH_PARSE_ENTER) { + appendStringBuf(sb, (); +} else if (type == RPMRICH_PARSE_LEAVE) { + appendStringBuf(sb, )); + if (op == RPMRICHOP_IF) + data-stacked_if--; +} else if (type == RPMRICH_PARSE_SIMPLE) { + char *N = xmalloc(nl + 1); + char *EVR = NULL; + rstrlcpy(N, n, nl + 1); + appendStringBuf(sb, N); + if (el) { + char rel[6], *rp = rel; + EVR = xmalloc(el + 1); + rstrlcpy(EVR, e, el + 1); + *rp++ = ' '; + if (sense RPMSENSE_LESS) + *rp++ = ''; + if (sense RPMSENSE_GREATER) + *rp++ = ''; + if (sense RPMSENSE_EQUAL) + *rp++ = '='; + *rp++ = ' '; + *rp = 0; + appendStringBuf(sb, rel); + appendStringBuf(sb, EVR); + } + rc = checkDep(data-spec, N, EVR, emsg); + _free(N); + _free(EVR); +} else if (type == RPMRICH_PARSE_OP) { + if (op == RPMRICHOP_IF) { + if (data-no_if) { + rasprintf(emsg, IF not allowed in conflicts dependencies); + rc = RPMRC_FAIL; + } else if (data-stacked_if) { + rasprintf(emsg, Stacked IF is not supported ); + rc = RPMRC_FAIL; + } + data-stacked_if++; + } + appendStringBuf(sb, ); + appendStringBuf(sb, rpmrichOpStr(op)); + appendStringBuf(sb, ); +} +return rc; +} + rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { @@ -146,6 +210,32 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, Flags = (tagflags ~RPMSENSE_SENSEMASK); + if (r[0] == '(') { + struct parseRCPOTRichData data; + if (nametag != RPMTAG_REQUIRENAME nametag != RPMTAG_CONFLICTNAME + nametag != RPMTAG_RECOMMENDNAME nametag != RPMTAG_SUPPLEMENTNAME + nametag != RPMTAG_SUGGESTNAME nametag != RPMTAG_ENHANCENAME) { + rasprintf(emsg, _(No rich dependencies allowed for this type)); + goto exit; + } + data.spec = spec; + data.sb = newStringBuf(); + data.no_if = (nametag == RPMTAG_CONFLICTNAME); + data.stacked_if = 0; + if (rpmrichParse(r, emsg, parseRCPOTRichCB, data) != RPMRC_OK) { + freeStringBuf(data.sb); + goto exit; + } + if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags | RPMSENSE_RICH, index)) { + rasprintf(emsg, _(invalid dependency)); + freeStringBuf(data.sb); + goto exit; +
[Rpm-maint] RFC: experiments with rich dependencies
Hi Panu et al, attached is an updated version of my rich dependencies patch. I cleanup up the code a bit, now we have only one generic parser instead of three specialized ones, and we use a callback function to do the needed work. Supported are AND, OR, and IF, but IF is not allowd in Conflicts, and it also must not be chained or stacked. Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);} diff --git a/build/pack.c b/build/pack.c index 4aa4a66..afa23dc 100644 --- a/build/pack.c +++ b/build/pack.c @@ -265,6 +265,29 @@ static int haveTildeDep(Header h) return 0; } +static int depContainsRich(Header h, rpmTagVal tagFlags) +{ +struct rpmtd_s flags; +rpm_flag_t *flag = NULL; + +if (headerGet(h, tagFlags, flags, HEADERGET_MINMEM)) { +while ((flag = rpmtdNextUint32(flags)) != NULL) +if (*flag RPMSENSE_RICH) +break; +rpmtdFreeData(flags); +} +return flag != NULL; +} + +static int haveRichDep(Header h) +{ +if (depContainsRich(h, RPMTAG_REQUIREFLAGS)) + return 1; +if (depContainsRich(h, RPMTAG_CONFLICTFLAGS)) + return 1; +return 0; +} + static rpm_loff_t estimateCpioSize(Package pkg) { rpmfi fi; @@ -438,6 +461,10 @@ static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, if (haveTildeDep(pkg-header)) (void) rpmlibNeedsFeature(pkg, TildeInVersions, 4.10.0-1); +/* check if the package has a rich dependency */ +if (haveRichDep(pkg-header)) + (void) rpmlibNeedsFeature(pkg, RichDependencies, 4.12.0-1); + /* Create and add the cookie */ if (cookie) { rasprintf(cookie, %s %d, buildHost(), (int) (*getBuildTime())); diff --git a/build/parseReqs.c b/build/parseReqs.c index 1427111..6bce361 100644 --- a/build/parseReqs.c +++ b/build/parseReqs.c @@ -45,6 +45,76 @@ static int checkSep(const char *s, char c, char **emsg) return 0; } +struct parseRCPOTRichData { +rpmSpec spec; +StringBuf sb; +int no_if; +int stacked_if; +}; + +/* Callback for the rich dependency parser. We use this to do check for invalid + * characters and to build a normailzed version of the dependency */ +static rpmRC parseRCPOTRichCB(void *cbdata, int type, + const char *n, int nl, const char *e, int el, rpmsenseFlags sense, + rpmrichOp op, char **emsg) { +struct parseRCPOTRichData *data = cbdata; +StringBuf sb = data-sb; +rpmRC rc = RPMRC_OK; + +if (type == RPMRICH_PARSE_ENTER) { + appendStringBuf(sb, (); +} else if (type == RPMRICH_PARSE_LEAVE) { + appendStringBuf(sb, )); + if (op == RPMRICHOP_IF) + data-stacked_if--; +} else if (type == RPMRICH_PARSE_SIMPLE) { + char *N = xmalloc(nl + 1); + char *EVR = 0; + rstrlcpy(N, n, nl + 1); + appendStringBuf(sb, N); + if (isascii(N[0]) !(risalnum(N[0]) || N[0] == '_' || N[0] == '/')) { + rasprintf(emsg, _(Dependency tokens must begin with alpha-numeric, '_' or '/')); + rc = RPMRC_FAIL; + } else if (el) { + char rel[6], *rp = rel; + char *EVR = xmalloc(el + 1); + rstrlcpy(EVR, e, el + 1); + if (rpmCharCheck(data-spec, EVR, el, .-_+:%{}~)) + rc = RPMRC_FAIL; + else if (checkSep(EVR, '-', emsg) || checkSep(EVR, ':', emsg)) + rc = RPMRC_FAIL; + *rp++ = ' '; + if (sense RPMSENSE_LESS) + *rp++ = ''; + if (sense RPMSENSE_GREATER) + *rp++ = ''; + if (sense RPMSENSE_EQUAL) + *rp++ = ''; + *rp++ = ' '; + *rp = 0; + appendStringBuf(sb, rel); + appendStringBuf(sb, EVR); + } + _free(N); + _free(EVR); +} else if (type == RPMRICH_PARSE_OP) { + if (op == RPMRICHOP_IF) { + if (data-no_if) { + rasprintf(emsg, IF not allowed in conflicts dependencies); + rc = RPMRC_FAIL; + } else if (data-stacked_if) { + rasprintf(emsg, Stacked IF is not supported ); + rc = RPMRC_FAIL; + } + data-stacked_if++; + } + appendStringBuf(sb, ); + appendStringBuf(sb, rpmrichOpStr(op)); + appendStringBuf(sb, ); +} +return rc; +} + rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { @@ -123,6 +193,31 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, Flags = (tagflags ~RPMSENSE_SENSEMASK); + if (r[0] == '(') { + struct parseRCPOTRichData data; + if (nametag == RPMTAG_PROVIDENAME || nametag == RPMTAG_OBSOLETENAME || nametag == RPMTAG_ORDERNAME + || nametag == RPMTAG_TRIGGERNAME) { + rasprintf(emsg, _(No rich dependencies allowed for this type)); + goto exit; + } + data.spec = spec; + data.sb = newStringBuf(); + data.no_if = nametag == RPMTAG_CONFLICTNAME; + data.stacked_if = 0; + if (rpmrichParse(r, emsg, parseRCPOTRichCB, data) != RPMRC_OK) { + freeStringBuf(data.sb); + goto exit; + } + if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags |