Add support for weak dependencies: A) use RPMTAG_SUGGESTS and RPMTAG_ENHANCES to store them. This is different to upstream, which uses RPMSENSE_MISSINGOK and RPMTAG_REQUIRES/RPMTAG_PROVIDES instead. I chose different tags because I wanted to be compatible. The point is that applications that don't know about the new MISSINGOK semantics will mis-interpret the provides/requires otherwise, which I deemed to risky. B) use RPMSENSE_STRONG to support a "strong" version, "Recommends" instead of "Suggests" and "Supplements" instead of "Enhances". Needs extcond.diff for query operations. Index: build/parsePreamble.c =================================================================== --- build/parsePreamble.c.orig +++ build/parsePreamble.c @@ -129,6 +129,8 @@ static struct tokenBits_s installScriptB { "post", RPMSENSE_SCRIPT_POST }, { "rpmlib", RPMSENSE_RPMLIB }, { "verify", RPMSENSE_SCRIPT_VERIFY }, + { "hint", RPMSENSE_MISSINGOK }, + { "strong", RPMSENSE_STRONG }, { NULL, 0 } }; @@ -140,6 +142,8 @@ static struct tokenBits_s buildScriptBit { "build", RPMSENSE_SCRIPT_BUILD }, { "install", RPMSENSE_SCRIPT_INSTALL }, { "clean", RPMSENSE_SCRIPT_CLEAN }, + { "hint", RPMSENSE_MISSINGOK }, + { "strong", RPMSENSE_STRONG }, { NULL, 0 } }; @@ -692,6 +696,18 @@ static int handlePreambleTag(Spec spec, if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; + case RPMTAG_SUGGESTSFLAGS: + case RPMTAG_ENHANCESFLAGS: + case RPMTAG_BUILDSUGGESTS: + case RPMTAG_BUILDENHANCES: + tagflags = RPMSENSE_MISSINGOK; + if (macro && (!strcmp(macro, "recommends") || !strcmp(macro, "buildrecommends"))) + tagflags |= RPMSENSE_STRONG; + if (macro && (!strcmp(macro, "supplements") || !strcmp(macro, "buildsupplements"))) + tagflags |= RPMSENSE_STRONG; + if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) + return rc; + break; case RPMTAG_EXCLUDEARCH: case RPMTAG_EXCLUSIVEARCH: case RPMTAG_EXCLUDEOS: @@ -783,6 +799,14 @@ static struct PreambleRec_s preambleList {RPMTAG_DISTTAG, 0, 0, 0, "disttag"}, {RPMTAG_CVSID, 0, 0, 0, "cvsid"}, {RPMTAG_SVNID, 0, 0, 0, "svnid"}, + {RPMTAG_SUGGESTSFLAGS, 0, 0, 0, "recommends"}, + {RPMTAG_SUGGESTSFLAGS, 0, 0, 0, "suggests"}, + {RPMTAG_ENHANCESFLAGS, 0, 0, 0, "supplements"}, + {RPMTAG_ENHANCESFLAGS, 0, 0, 0, "enhances"}, + {RPMTAG_BUILDSUGGESTS, 0, 0, 0, "buildrecommends"}, + {RPMTAG_BUILDSUGGESTS, 0, 0, 0, "buildsuggests"}, + {RPMTAG_BUILDENHANCES, 0, 0, 0, "buildsupplements"}, + {RPMTAG_BUILDENHANCES, 0, 0, 0, "buildenhances"}, /*@-nullassign@*/ /* LCL: can't add null annotation */ {0, 0, 0, 0, 0} /*@=nullassign@*/ Index: build/parseReqs.c =================================================================== --- build/parseReqs.c.orig +++ build/parseReqs.c @@ -81,6 +81,14 @@ int parseRCPOT(Spec spec, Package pkg, c tagflags |= RPMSENSE_ANY; h = spec->buildRestrictions; break; + case RPMTAG_SUGGESTSFLAGS: + case RPMTAG_ENHANCESFLAGS: + h = pkg->header; + break; + case RPMTAG_BUILDSUGGESTS: + case RPMTAG_BUILDENHANCES: + h = spec->buildRestrictions; + break; default: case RPMTAG_REQUIREFLAGS: tagflags |= RPMSENSE_ANY; Index: build/reqprov.c =================================================================== --- build/reqprov.c.orig +++ build/reqprov.c @@ -48,6 +48,16 @@ int addReqProv(/*@unused@*/ Spec spec, H flagtag = RPMTAG_TRIGGERFLAGS; indextag = RPMTAG_TRIGGERINDEX; extra = Flags & RPMSENSE_TRIGGER; + } else if (tagN == RPMTAG_SUGGESTSFLAGS || tagN == RPMTAG_BUILDSUGGESTS) { + nametag = RPMTAG_SUGGESTSNAME; + versiontag = RPMTAG_SUGGESTSVERSION; + flagtag = RPMTAG_SUGGESTSFLAGS; + extra = Flags & _ALL_REQUIRES_MASK; + } else if (tagN == RPMTAG_ENHANCESFLAGS || tagN == RPMTAG_BUILDENHANCES) { + nametag = RPMTAG_ENHANCESNAME; + versiontag = RPMTAG_ENHANCESVERSION; + flagtag = RPMTAG_ENHANCESFLAGS; + extra = Flags & _ALL_REQUIRES_MASK; } else { nametag = RPMTAG_REQUIRENAME; versiontag = RPMTAG_REQUIREVERSION; Index: build/rpmfc.c =================================================================== --- build/rpmfc.c.orig +++ build/rpmfc.c @@ -1350,6 +1350,12 @@ static struct DepMsg_s depMsgs[] = { { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL }, RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS, 0, -1 }, + { "Enhances", { "%{?__find_enhances}", NULL, NULL, NULL }, + RPMTAG_ENHANCESNAME, RPMTAG_ENHANCESVERSION, RPMTAG_ENHANCESFLAGS, + RPMSENSE_STRONG, RPMSENSE_STRONG }, + { "Supplements", { "%{?__find_supplements}", NULL, NULL, NULL }, + RPMTAG_ENHANCESNAME, RPMTAG_ENHANCESVERSION, RPMTAG_ENHANCESFLAGS, + RPMSENSE_STRONG, 0 }, { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 } }; @@ -1445,6 +1451,14 @@ static int rpmfcGenerateDependsHelper(co failnonzero = 0; tagflags = RPMSENSE_FIND_REQUIRES; /*@switchbreak@*/ break; + case RPMTAG_ENHANCESFLAGS: + if (!pkg->autoProv) + continue; + failnonzero = 0; + tagflags = RPMSENSE_FIND_REQUIRES | RPMSENSE_MISSINGOK; + if (strcmp(dm->msg, "Supplements") == 0) + tagflags |= RPMSENSE_STRONG; + /*@switchbreak@*/ break; default: continue; /*@notreached@*/ /*@switchbreak@*/ break; Index: lib/rpmlib.h =================================================================== --- lib/rpmlib.h.orig +++ lib/rpmlib.h @@ -541,7 +541,7 @@ typedef enum rpmsenseFlags_e { RPMSENSE_TRIGGERPREIN = (1 << 25), /*!< @todo Implement %triggerprein. */ /*@=enummemuse@*/ RPMSENSE_KEYRING = (1 << 26), - RPMSENSE_PATCHES = (1 << 27), + RPMSENSE_STRONG = (1 << 27), RPMSENSE_CONFIG = (1 << 28), RPMSENSE_PROBE = (1 << 29), RPMSENSE_PACKAGE = (1 << 30) @@ -562,6 +562,7 @@ typedef enum rpmsenseFlags_e { RPMSENSE_SCRIPT_VERIFY | \ RPMSENSE_FIND_REQUIRES | \ RPMSENSE_MISSINGOK | \ + RPMSENSE_STRONG | \ RPMSENSE_SCRIPT_PREP | \ RPMSENSE_SCRIPT_BUILD | \ RPMSENSE_SCRIPT_INSTALL | \ Index: python/rpmmodule.c =================================================================== --- python/rpmmodule.c.orig +++ python/rpmmodule.c @@ -354,7 +354,7 @@ void init_rpm(void) REGISTER_ENUM(RPMSENSE_RPMLIB); REGISTER_ENUM(RPMSENSE_TRIGGERPREIN); REGISTER_ENUM(RPMSENSE_KEYRING); - REGISTER_ENUM(RPMSENSE_PATCHES); + REGISTER_ENUM(RPMSENSE_STRONG); REGISTER_ENUM(RPMSENSE_CONFIG); REGISTER_ENUM(RPMTRANS_FLAG_TEST); Index: lib/rpmds.c =================================================================== --- lib/rpmds.c.orig +++ lib/rpmds.c @@ -320,6 +320,11 @@ rpmds rpmdsNew(Header h, rpmTag tagN, in tagEVR = RPMTAG_TRIGGERVERSION; tagF = RPMTAG_TRIGGERFLAGS; } else + if (tagN == RPMTAG_ENHANCESNAME) { + Type = "Enhances"; + tagEVR = RPMTAG_ENHANCESVERSION; + tagF = RPMTAG_ENHANCESFLAGS; + } else goto exit; /*@-branchstate@*/ Index: rpmpopt.in =================================================================== --- rpmpopt.in.orig +++ rpmpopt.in @@ -60,6 +60,22 @@ rpm alias --requires --qf \ --POPTdesc=$"list capabilities required by package(s)" rpm alias -R --requires +rpm alias --suggests --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{}:{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package suggests" + +rpm alias --recommends --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package recommends" + +rpm alias --enhances --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{}:{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package enhances" + +rpm alias --supplements --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package supplements" + rpm alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\ Version : %-27{VERSION} Vendor: %{VENDOR}\n\ Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\ @@ -340,6 +356,22 @@ rpmq alias --requires --qf \ --POPTdesc=$"list capabilities required by package(s)" rpmq alias -R --requires +rpmq alias --suggests --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{}:{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package suggests" + +rpmq alias --recommends --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package recommends" + +rpmq alias --enhances --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{}:{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package enhances" + +rpmq alias --supplements --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package supplements" + rpmq alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\ Version : %-27{VERSION} Vendor: %{VENDOR}\n\ Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\ @@ -438,6 +470,22 @@ rpmquery alias --requires --qf \ --POPTdesc=$"list capabilities required by package(s)" rpmquery alias -R --requires +rpmquery alias --suggests --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{}:{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package suggests" + +rpmquery alias --recommends --qf \ + "[%|SUGGESTSFLAGS:depflag_strong?{%{SUGGESTSNAME} %{SUGGESTSFLAGS:depflags} %{SUGGESTSVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package recommends" + +rpmquery alias --enhances --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{}:{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package enhances" + +rpmquery alias --supplements --qf \ + "[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \ + --POPTdesc=$"list capabilities this package supplements" + rpmquery alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\ Version : %-27{VERSION} Vendor: %{VENDOR}\n\ Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\ Index: lib/formats.c =================================================================== --- lib/formats.c.orig +++ lib/formats.c @@ -652,6 +652,38 @@ static /*@only@*/ char * depflagsFormat( return val; } +static /*@only@*/ char * depflag_strongFormat(int_32 type, const void * data, + char * formatPrefix, int padding, /*@unused@*/ int element) + /*@modifies formatPrefix @*/ + /*@requires maxRead(data) >= 0 @*/ +{ + char * val; + char buf[10]; + int anint; + + if (type != RPM_INT32_TYPE) { + val = xstrdup(_("(not a number)")); + } else { + anint = *((int_32 *) data); + buf[0] = '\0'; + +/*@-boundswrite@*/ + if (anint & RPMSENSE_STRONG) + strcat(buf, "strong"); +/*@=boundswrite@*/ + + val = xmalloc(7 + padding); +/*@-boundswrite@*/ + strcat(formatPrefix, "s"); +/*@=boundswrite@*/ + /*@-formatconst@*/ + sprintf(val, formatPrefix, buf); + /*@=formatconst@*/ + } + + return val; +} + /** * Retrieve mounted file system paths. * @param h header @@ -1344,6 +1376,7 @@ const struct headerSprintfExtension_s rp { HEADER_EXT_FORMAT, "base64", { base64Format } }, { HEADER_EXT_FORMAT, "pgpsig", { pgpsigFormat } }, { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } }, + { HEADER_EXT_FORMAT, "depflag_strong", { depflag_strongFormat } }, { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } }, { HEADER_EXT_FORMAT, "perms", { permsFormat } }, { HEADER_EXT_FORMAT, "permissions", { permsFormat } },