Added a pair of new things to the query format:
the '>'-test, ':nothing' format variant and implemented '-q --changes-since=<e:v-r>' upon them.
This commit is contained in:
parent
3e8d542527
commit
de25d1f6d1
@ -133,6 +133,17 @@ name after the tag name. Here are some examples:
|
||||
The :shescape may be used on plain strings to get a string which can pass
|
||||
through a single level of shell and give the original string.
|
||||
|
||||
On ALT's systems, rpm accepts a special format for printing nothing instead
|
||||
of the value of the tag. This can be particularly useful in combination with
|
||||
iterating over arrays:
|
||||
|
||||
\begin{verbatim}
|
||||
[%{filenames:nothing}i]
|
||||
\end{verbatim}
|
||||
|
||||
will print an i for each file your package contains (so, you'll get the number
|
||||
of files in the package in unary form).
|
||||
|
||||
\subsection queryformat_expressions Query Expressions
|
||||
|
||||
Simple conditionals may be evaluated through query expressions. Expressions
|
||||
@ -148,6 +159,34 @@ the SOMETAG tag is present, and "missing" otherwise:
|
||||
Notice that the subformats "present" and "missing" must be inside of curly
|
||||
braces.
|
||||
|
||||
In rpm used on an ALT's system, there is also one more (non-trivial) test
|
||||
expression which is accepted as the first operand of \verb!%| ?{}:{} |!. Here's an example:
|
||||
|
||||
\begin{verbatim}
|
||||
%|%{SOME}expression>epoch:version-release?{ultra-fresh}:{pre-historic}|
|
||||
\end{verbatim}
|
||||
|
||||
It's idea is to test whether an expression evaluates to a value which is
|
||||
more fresh than a specified epoch:versiobn-release triple (in the sense
|
||||
rpm compares E:V-Rs). Things get more complicated because of the special
|
||||
use of this hack: it should be used to filter changelog entries, that
|
||||
contain \verb!%{CHANGELOGNAME}! of the form:
|
||||
|
||||
\begin{verbatim}
|
||||
John Smith <js@my-distro.com> 5.0.1-my6
|
||||
\end{verbatim}
|
||||
|
||||
so the test extracts the part of the value that follows the email address,
|
||||
and compares it to the specified epoch:version-release. (If there is no
|
||||
email address, it takes the whole value, so you could use a query like this
|
||||
|
||||
\begin{verbatim}
|
||||
%|2-1mdk>2-alt1?{mdk}:{alt}|
|
||||
\end{verbatim}
|
||||
|
||||
to determine which of the releases is considered by rpm to be more fresh.)
|
||||
|
||||
|
||||
\subsection queryformat_example Example: Viewing the Verify Flags
|
||||
|
||||
The follwing example query is run against dev becuase I know %verify
|
||||
|
@ -479,48 +479,7 @@ static void alMakeIndex(availableList al)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split EVR into epoch, version, and release components.
|
||||
* @param evr [epoch:]version[-release] string
|
||||
* @retval *ep pointer to epoch
|
||||
* @retval *vp pointer to version
|
||||
* @retval *rp pointer to release
|
||||
*/
|
||||
static void parseEVR(char * evr,
|
||||
/*@exposed@*/ /*@out@*/ const char ** ep,
|
||||
/*@exposed@*/ /*@out@*/ const char ** vp,
|
||||
/*@exposed@*/ /*@out@*/ const char ** rp)
|
||||
/*@modifies *ep, *vp, *rp @*/
|
||||
{
|
||||
const char *epoch;
|
||||
const char *version; /* assume only version is present */
|
||||
const char *release;
|
||||
char *s, *se;
|
||||
|
||||
s = evr;
|
||||
while (*s && xisdigit(*s)) s++; /* s points to epoch terminator */
|
||||
se = strrchr(s, '-'); /* se points to version terminator */
|
||||
|
||||
if (*s == ':') {
|
||||
epoch = evr;
|
||||
*s++ = '\0';
|
||||
version = s;
|
||||
if (*epoch == '\0') epoch = "0";
|
||||
} else {
|
||||
epoch = NULL; /* XXX disable epoch compare if missing */
|
||||
version = evr;
|
||||
}
|
||||
if (se) {
|
||||
*se++ = '\0';
|
||||
release = se;
|
||||
} else {
|
||||
release = NULL;
|
||||
}
|
||||
|
||||
if (ep) *ep = epoch;
|
||||
if (vp) *vp = version;
|
||||
if (rp) *rp = release;
|
||||
}
|
||||
/* parseEVR() moved to rpmvercmp.c */
|
||||
|
||||
const char *rpmNAME = PACKAGE;
|
||||
const char *rpmEVR = VERSION;
|
||||
@ -559,25 +518,8 @@ int rpmRangesOverlap(const char * AName, const char * AEVR, int AFlags,
|
||||
parseEVR(aEVR, &aE, &aV, &aR);
|
||||
bEVR = xstrdup(BEVR);
|
||||
parseEVR(bEVR, &bE, &bV, &bR);
|
||||
|
||||
/* Compare {A,B} [epoch:]version[-release] */
|
||||
sense = 0;
|
||||
if (aE && *aE && bE && *bE)
|
||||
sense = rpmvercmp(aE, bE);
|
||||
else if (aE && *aE && atol(aE) > 0) {
|
||||
/* XXX legacy epoch-less requires/conflicts compatibility */
|
||||
rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency needs an epoch (assuming same as \"A\")\n\tA %s\tB %s\n"),
|
||||
aDepend, bDepend);
|
||||
sense = 0;
|
||||
} else if (bE && *bE && atol(bE) > 0)
|
||||
sense = -1;
|
||||
|
||||
if (sense == 0) {
|
||||
sense = rpmvercmp(aV, bV);
|
||||
if (sense == 0 && aR && *aR && bR && *bR) {
|
||||
sense = rpmvercmp(aR, bR);
|
||||
}
|
||||
}
|
||||
/* rpmEVRcmp() is also shared; the code moved to rpmvercmp.c */
|
||||
sense = rpmEVRcmp(aE, aV, aR, aDepend, bE, bV, bR, bDepend);
|
||||
aEVR = _free(aEVR);
|
||||
bEVR = _free(bEVR);
|
||||
|
||||
|
@ -299,6 +299,28 @@ static /*@only@*/ char * depflagsFormat(int_32 type, const void * data,
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type tag type
|
||||
* @param data tag value
|
||||
* @param formatPrefix
|
||||
* @param padding
|
||||
* @param element (unused)
|
||||
* @return formatted string
|
||||
*/
|
||||
static /*@only@*/ char * nothingFormat(int_32 type, const void * data,
|
||||
char * formatPrefix, int padding, /*@unused@*/ int element)
|
||||
/*@modifies formatPrefix @*/
|
||||
{ /* based on depflagsFormat() code. */
|
||||
char * val;
|
||||
val = xmalloc(2 + padding);
|
||||
strcat(formatPrefix, "s");
|
||||
/*@-formatconst@*/
|
||||
sprintf(val, formatPrefix, "");
|
||||
/*@=formatconst@*/
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param h header
|
||||
* @retval type address of tag type
|
||||
@ -736,6 +758,7 @@ const struct headerSprintfExtension_s rpmHeaderFormats[] = {
|
||||
{ HEADER_EXT_FORMAT, "perms", { permsFormat } },
|
||||
{ HEADER_EXT_FORMAT, "permissions", { permsFormat } },
|
||||
{ HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } },
|
||||
{ HEADER_EXT_FORMAT, "nothing", { nothingFormat } },
|
||||
{ HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } }
|
||||
} ;
|
||||
/*@=type@*/
|
||||
|
129
lib/header.c
129
lib/header.c
@ -16,6 +16,9 @@
|
||||
|
||||
#include <header_internal.h>
|
||||
|
||||
/* We get parseEVR() from there used in parsing the >-test in conditionals: */
|
||||
#include <rpmlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/*@-redecl@*/ /* FIX: avoid rpmlib.h, need for debugging. */
|
||||
@ -79,6 +82,8 @@ static int typeSizes[] = {
|
||||
/*@observer@*/ /*@unchecked@*/
|
||||
HV_t hdrVec; /* forward reference */
|
||||
|
||||
/* Already defined in <rpmlib.h> */
|
||||
#if 0
|
||||
/**
|
||||
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
|
||||
* @param p memory to free
|
||||
@ -90,6 +95,7 @@ _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies *p @*/
|
||||
if (p != NULL) free((void *)p);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \ingroup header
|
||||
* Reference a header instance.
|
||||
@ -2065,6 +2071,23 @@ freeFormat( /*@only@*/ /*@null@*/ sprintfToken format, int num)
|
||||
format[i].u.cond.elseFormat =
|
||||
freeFormat(format[i].u.cond.elseFormat,
|
||||
format[i].u.cond.numElseTokens);
|
||||
switch (format[i].u.cond.test.type) {
|
||||
case TRIVIAL:
|
||||
/* the usual old way; format[i].test.u.tag is a struct */
|
||||
break;
|
||||
case StringTAG_String3:
|
||||
/* the added option */
|
||||
format[i].u.cond.test.u.tag_str3.headFormat =
|
||||
freeFormat(format[i].u.cond.test.u.tag_str3.headFormat,
|
||||
format[i].u.cond.test.u.tag_str3.numHeadTokens);
|
||||
/* We don't need to free the strings; we have not allocated them.
|
||||
And PTOK_STRING case is analogous and also doesn't free the string. */
|
||||
break;
|
||||
default:
|
||||
/* report an error */
|
||||
rpmMessage(RPMMESS_WARNING, _("Unknown test type in \%|?:|; perhaps some memory is leaking right now.\n"));
|
||||
break;
|
||||
}
|
||||
/*@switchbreak@*/ break;
|
||||
case PTOK_NONE:
|
||||
case PTOK_TAG:
|
||||
@ -2493,19 +2516,67 @@ static int parseExpression(sprintfToken token, char * str,
|
||||
|
||||
*endPtr = chptr;
|
||||
|
||||
findTag(str, tags, extensions, &tag, &ext);
|
||||
{ /* branching between the trivial old test for the conditional and
|
||||
the added test for EVR comparison. */
|
||||
char * str2 = strchr(str,'>');
|
||||
if (str2) {
|
||||
char * endOfParsed = NULL;
|
||||
rpmMessage(RPMMESS_WARNING, _("Parsing non-standard test (>) for \%|?{}:{}|.\n"));
|
||||
*str2 ='\0';
|
||||
++str2; /* str2 is the beginning of the second part: after the > sign. */
|
||||
|
||||
if (tag) {
|
||||
token->u.cond.tag.ext = NULL;
|
||||
token->u.cond.tag.tag = tag->val;
|
||||
} else if (ext) {
|
||||
token->u.cond.tag.ext = ext->u.tagFunction;
|
||||
token->u.cond.tag.extNum = ext - extensions;
|
||||
} else {
|
||||
token->u.cond.tag.ext = NULL;
|
||||
token->u.cond.tag.tag = -1;
|
||||
if ( parseFormat(str, tags, extensions,
|
||||
&token->u.cond.test.u.tag_str3.headFormat,
|
||||
&token->u.cond.test.u.tag_str3.numHeadTokens,
|
||||
&endOfParsed, PARSER_IN_EXPR, errmsg)
|
||||
/* this doesn't work, NULL is returned: || ( endOfParsed != str2 ) */ )
|
||||
{
|
||||
/*@-observertrans -readonlytrans@*/
|
||||
if (errmsg
|
||||
&& ! *errmsg /* *errmsg was set to NULL at the function beginnging */ )
|
||||
*errmsg = _("the left part of >-expr finished before the > sign");
|
||||
/*@=observertrans =readonlytrans@*/
|
||||
token->u.cond.ifFormat =
|
||||
freeFormat(token->u.cond.ifFormat, token->u.cond.numIfTokens);
|
||||
token->u.cond.elseFormat =
|
||||
freeFormat(token->u.cond.elseFormat, token->u.cond.numElseTokens);
|
||||
return 1;
|
||||
}
|
||||
|
||||
token->u.cond.test.type = StringTAG_String3;
|
||||
token->u.cond.test.u.tag_str3.predicate = &isChangeNameMoreFresh;
|
||||
|
||||
parseEVR(str2,
|
||||
&token->u.cond.test.u.tag_str3.tail[0],
|
||||
&token->u.cond.test.u.tag_str3.tail[1],
|
||||
&token->u.cond.test.u.tag_str3.tail[2]);
|
||||
/* We could strdup tail[j], but it seems we don't need this: the rest of similar code
|
||||
doesn't perform this. And we don't have to free them. */
|
||||
rpmMessage(RPMMESS_DEBUG, "Will cmp with e=%s, v=%s, r=%s\n",
|
||||
token->u.cond.test.u.tag_str3.tail[0],
|
||||
token->u.cond.test.u.tag_str3.tail[1],
|
||||
token->u.cond.test.u.tag_str3.tail[2]);
|
||||
}
|
||||
else {
|
||||
struct sprintfTag head;
|
||||
rpmMessage(RPMMESS_DEBUG, _("The usual way of parsing the test part for \%|?:|\n"));
|
||||
findTag(str, tags, extensions, &tag, &ext);
|
||||
if (tag) {
|
||||
head.ext = NULL;
|
||||
head.tag = tag->val;
|
||||
} else if (ext) {
|
||||
head.ext = ext->u.tagFunction;
|
||||
head.extNum = ext - extensions;
|
||||
} else {
|
||||
head.ext = NULL;
|
||||
head.tag = -1;
|
||||
}
|
||||
token->u.cond.test.type = TRIVIAL;
|
||||
token->u.cond.test.u.tag = head;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
token->type = PTOK_COND;
|
||||
|
||||
return 0;
|
||||
@ -2774,14 +2845,46 @@ static char * singleSprintf(Header h, sprintfToken token,
|
||||
break;
|
||||
|
||||
case PTOK_COND:
|
||||
if (token->u.cond.tag.ext ||
|
||||
headerIsEntry(h, token->u.cond.tag.tag)) {
|
||||
{
|
||||
int testResult = 0; /* false by default */
|
||||
switch (token->u.cond.test.type) {
|
||||
case TRIVIAL:
|
||||
testResult = token->u.cond.test.u.tag.ext ||
|
||||
headerIsEntry(h, token->u.cond.test.u.tag.tag);
|
||||
break;
|
||||
case StringTAG_String3:
|
||||
{ /* this piece if code is based on headerSprintf() */
|
||||
char * head = NULL; int head_en = 0;
|
||||
int head_alloced = 0;
|
||||
head = xstrdup("");
|
||||
for (i = 0; i < token->u.cond.test.u.tag_str3.numHeadTokens; i++)
|
||||
/* head_t = -- what do we need the return value for? headerSprintf() discards it. */
|
||||
singleSprintf(h, token->u.cond.test.u.tag_str3.headFormat + i,
|
||||
extensions, extCache,
|
||||
element, &head, &head_en, &head_alloced);
|
||||
if (head != NULL && head_en < head_alloced)
|
||||
head = xrealloc(head, head_en+1);
|
||||
testResult = head
|
||||
&& token->u.cond.test.u.tag_str3.predicate(head, token->u.cond.test.u.tag_str3.tail);
|
||||
/* Do we free all the alloced data heer? */
|
||||
_free(head);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* report an error */
|
||||
rpmMessage(RPMMESS_WARNING, _("Unknown test type in \%|?:|; assuming false.\n"));
|
||||
testResult = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
condFormat = token->u.cond.ifFormat;
|
||||
condNumFormats = token->u.cond.numIfTokens;
|
||||
} else {
|
||||
condFormat = token->u.cond.elseFormat;
|
||||
condNumFormats = token->u.cond.numElseTokens;
|
||||
}
|
||||
}
|
||||
|
||||
need = condNumFormats * 20;
|
||||
if (condFormat == NULL || need <= 0) break;
|
||||
|
@ -116,7 +116,19 @@ struct sprintfToken {
|
||||
int numIfTokens;
|
||||
/*@only@*/ /*@null@*/ sprintfToken elseFormat;
|
||||
int numElseTokens;
|
||||
struct sprintfTag tag;
|
||||
struct {
|
||||
enum { TRIVIAL, StringTAG_String3 } type;
|
||||
union {
|
||||
struct sprintfTag tag;
|
||||
struct {
|
||||
int (*predicate)(const char * head, const char * const tail[3]);
|
||||
/* args */
|
||||
sprintfToken headFormat;
|
||||
int numHeadTokens;
|
||||
const char * tail[3];
|
||||
} tag_str3;
|
||||
} u;
|
||||
} test;
|
||||
} cond;
|
||||
} u;
|
||||
};
|
||||
|
23
lib/rpmlib.h
23
lib/rpmlib.h
@ -1463,6 +1463,29 @@ int rpmGetRpmlibProvides(/*@null@*/ /*@out@*/ const char *** provNames,
|
||||
int rpmvercmp(const char * a, const char * b)
|
||||
/*@*/;
|
||||
|
||||
int
|
||||
rpmEVRcmp(const char * const aE, const char * const aV, const char * const aR,
|
||||
const char * const aDepend,
|
||||
const char * const bE, const char * const bV, const char * const bR,
|
||||
const char * const bDepend);
|
||||
|
||||
/**
|
||||
* Split EVR into epoch, version, and release components.
|
||||
* @param evr [epoch:]version[-release] string
|
||||
* @retval *ep pointer to epoch
|
||||
* @retval *vp pointer to version
|
||||
* @retval *rp pointer to release
|
||||
*/
|
||||
void parseEVR(char * evr,
|
||||
/*@exposed@*/ /*@out@*/ const char ** ep,
|
||||
/*@exposed@*/ /*@out@*/ const char ** vp,
|
||||
/*@exposed@*/ /*@out@*/ const char ** rp);
|
||||
/*@modifies *ep, *vp, *rp @*/
|
||||
|
||||
/* A predicate: */
|
||||
int isChangeNameMoreFresh(const char * const head,
|
||||
const char * const tail[3]);
|
||||
|
||||
/** \ingroup rpmtrans
|
||||
* Compare two versioned dependency ranges, looking for overlap.
|
||||
* @param AName 1st dependncy name string
|
||||
|
110
lib/rpmvercmp.c
110
lib/rpmvercmp.c
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include <ctype.h> /* This should be done by configure and friends, I guess. */
|
||||
|
||||
#include "rpmlib.h"
|
||||
|
||||
@ -107,3 +108,112 @@ int rpmvercmp(const char * a, const char * b)
|
||||
/* whichever version still has characters left over wins */
|
||||
if (!*one) return -1; else return 1;
|
||||
}
|
||||
|
||||
/* Moved from depends.c, because we use it in other places, too. */
|
||||
/**
|
||||
* Split EVR into epoch, version, and release components.
|
||||
* @param evr [epoch:]version[-release] string
|
||||
* @retval *ep pointer to epoch
|
||||
* @retval *vp pointer to version
|
||||
* @retval *rp pointer to release
|
||||
*/
|
||||
void parseEVR(char * evr,
|
||||
/*@exposed@*/ /*@out@*/ const char ** ep,
|
||||
/*@exposed@*/ /*@out@*/ const char ** vp,
|
||||
/*@exposed@*/ /*@out@*/ const char ** rp)
|
||||
/*@modifies *ep, *vp, *rp @*/
|
||||
{
|
||||
const char *epoch;
|
||||
const char *version; /* assume only version is present */
|
||||
const char *release;
|
||||
char *s, *se;
|
||||
|
||||
s = evr;
|
||||
while (*s && xisdigit(*s)) s++; /* s points to epoch terminator */
|
||||
se = strrchr(s, '-'); /* se points to version terminator */
|
||||
|
||||
if (*s == ':') {
|
||||
epoch = evr;
|
||||
*s++ = '\0';
|
||||
version = s;
|
||||
if (*epoch == '\0') epoch = "0";
|
||||
} else {
|
||||
epoch = NULL; /* XXX disable epoch compare if missing */
|
||||
version = evr;
|
||||
}
|
||||
if (se) {
|
||||
*se++ = '\0';
|
||||
release = se;
|
||||
} else {
|
||||
release = NULL;
|
||||
}
|
||||
|
||||
if (ep) *ep = epoch;
|
||||
if (vp) *vp = version;
|
||||
if (rp) *rp = release;
|
||||
}
|
||||
|
||||
/* Compare {A,B} [epoch:]version[-release] */
|
||||
int
|
||||
rpmEVRcmp(const char * const aE, const char * const aV, const char * const aR,
|
||||
const char * const aDepend,
|
||||
const char * const bE, const char * const bV, const char * const bR,
|
||||
const char * const bDepend)
|
||||
{
|
||||
int sense = 0;
|
||||
|
||||
rpmMessage(RPMMESS_DEBUG, "cmp e=%s, v=%s, r=%s\n and e=%s, v=%s, r=%s\n ",
|
||||
aE, aV, aR, bE, bV, bR);
|
||||
|
||||
|
||||
if (aE && *aE && bE && *bE)
|
||||
sense = rpmvercmp(aE, bE);
|
||||
else if (aE && *aE && atol(aE) > 0) {
|
||||
/* XXX legacy epoch-less requires/conflicts compatibility */
|
||||
rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency needs an epoch (assuming same as \"A\")\n\tA %s\tB %s\n"),
|
||||
aDepend, bDepend);
|
||||
sense = 0;
|
||||
} else if (bE && *bE && atol(bE) > 0)
|
||||
sense = -1;
|
||||
|
||||
if (sense == 0) {
|
||||
sense = rpmvercmp(aV, bV);
|
||||
if (sense == 0 && aR && *aR && bR && *bR) {
|
||||
sense = rpmvercmp(aR, bR);
|
||||
}
|
||||
}
|
||||
|
||||
return sense;
|
||||
}
|
||||
|
||||
int isChangeNameMoreFresh(const char * const head,
|
||||
const char * const tail[3])
|
||||
{
|
||||
int result;
|
||||
const char * evr[3];
|
||||
const char * wordAfterEmail;
|
||||
char * copy;
|
||||
|
||||
rpmMessage(RPMMESS_DEBUG, "test: is '%s' more fresh than e=%s, v=%s, r=%s?\n",
|
||||
head, tail[0], tail[1], tail[2]);
|
||||
/* find the next to <email> word begin */
|
||||
if ( (wordAfterEmail = strrchr(head, '>')) )
|
||||
++wordAfterEmail;
|
||||
else
|
||||
wordAfterEmail = head;
|
||||
while ( *wordAfterEmail && isspace(*wordAfterEmail) )
|
||||
++wordAfterEmail;
|
||||
/* found. */
|
||||
copy = xstrdup(wordAfterEmail);
|
||||
parseEVR(copy, &evr[0], &evr[1], &evr[2]);
|
||||
/* The order of two argument groups is important:
|
||||
if evr[] (passed as B on the second place) has no epoch,
|
||||
rpmEVRcmp() assumes the same as in tail[];
|
||||
This fits our needs: the epoch may be omitted in a changelog entry (evr[])
|
||||
but there are no problems in specifying it in the format (tail[]). */
|
||||
result = rpmEVRcmp(tail[0], tail[1], tail[2], "",
|
||||
evr[0], evr[1], evr[2], "") < 0;
|
||||
_free(copy);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,10 @@ rpm alias --changelog -q --qf '[* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHA
|
||||
--POPTdesc=$"list change logs for this package"
|
||||
rpm alias --lastchange -q --qf '* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHANGELOGTEXT}\n' \
|
||||
--POPTdesc=$"output last changelog entry for this package"
|
||||
rpm alias --changes-since -q --qf '[%{CHANGELOGNAME:nothing}\
|
||||
%|%{CHANGELOGNAME}>!#:+?{* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHANGELOGTEXT}\n\n}:{}|]' \
|
||||
--POPTdesc=$"list change logs for this package that are fresher than <e:ver-rel> (as indicated by the word next to the packager's email)" \
|
||||
--POPTargs=$"<option>"
|
||||
|
||||
rpm alias --triggerscripts -q --qf '\
|
||||
[trigger%{TRIGGERTYPE} script (through %{TRIGGERSCRIPTPROG}) -- %{TRIGGERCONDS}\n\
|
||||
@ -341,6 +345,10 @@ rpmq alias --changelog -q --qf '[* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CH
|
||||
--POPTdesc=$"list change logs for this package"
|
||||
rpmq alias --lastchange -q --qf '* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHANGELOGTEXT}\n' \
|
||||
--POPTdesc=$"output last changelog entry for this package"
|
||||
rpmq alias --changes-since -q --qf '[%{CHANGELOGNAME:nothing}\
|
||||
%|%{CHANGELOGNAME}>!#:+?{* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHANGELOGTEXT}\n\n}:{}|]' \
|
||||
--POPTdesc=$"list change logs for this package that are fresher than <e:ver-rel> (as indicated by the word next to the packager's email)" \
|
||||
--POPTargs=$"<option>"
|
||||
|
||||
rpmq alias --triggerscripts -q --qf '\
|
||||
[trigger%{TRIGGERTYPE} script (through %{TRIGGERSCRIPTPROG}) -- %{TRIGGERCONDS}\n\
|
||||
|
Loading…
Reference in New Issue
Block a user