Re: [Rpm-maint] RFC: experiments with rich dependencies

2015-01-14 Thread Lubos Kardos
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

2014-09-12 Thread Michael Schroeder
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

2014-09-11 Thread Panu Matilainen

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

2014-09-11 Thread Florian Festi
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

2014-09-11 Thread Michael Schroeder
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

2014-09-11 Thread Florian Festi
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

2014-09-11 Thread Panu Matilainen

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

2014-09-11 Thread Michael Schroeder
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

2014-09-09 Thread Michael Schroeder
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

2014-09-08 Thread Michael Schroeder

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 |