Closed michaelrsweet closed 16 years ago
Original reporter: Michael Sweet
Sven Dowideit wrote:
... Is there a better way to achieve this? or should i just code it up, and hand it over to you guys?
Yeah, that kind of stuff gets tricky since you quickly fall into the issue of format differences, e.g. not all formats allow for that, and some things can interfere with the normal packaging with the stuff we automatically generate.
If you just need to %define stuff, then we can probably add support for that specifically and map it to other formats as possible/ necessary.
Original reporter: Michael Sweet
I was thinking that the %literal would be an advanced directive, that would enable format specific hacks only - maybe there's a way to dissallow them for 'format all'
this way, instead of EPM being forced to choose between supporting all the oddities and less used parts of the platforms, there would be a general fallback.
after implementing just the rpm and parser portion, I started to think about the debian version, and realised that more will be required - perhaps a format specific qualifier - in debian's case which file the literal text should go into..
thus, my proposal (and the code i'll write and send you) would have something like (ignore for a moment the pointlessness of specifying the template file like this )
%format rpm %literal %define __perl_provides $prefix/perl.prov %literal %define __perl_requires $prefix/perl.req %format deb %literal(templates) %literal(templates) Template: twiki/wikiwebmaster %literal(templates) Type: string %literal(templates) Default: webmaster@localhost %literal(templates) _Description: Email address of the webmaster for %literal(templates) this TWiki: %literal(templates) This email address gets mail for new user %literal(templates) registration, and is listed on the "oops" page when %literal(templates) things go wrong. %format all
patch for epm and rpm attached :)
Sven
Original reporter:
I prepared a version of the %literal patch that is implemented as an extension of struct command_t and function add_command(). It allows to specify commands with "%literal(keyword)" similar to "%postinstall" etc. These commands will be stored with type COMMAND_SPECIAL and the specified keyword in the new key field. The package type specific modules (rpm.c, pkg.c etc) can do whatever is needed with these commands. I tried to be compatible to the original patch for RPM's spec file and added "%literal(request)" to specify request scripts for SVR4 (Solaris) pkg format.
Bodo
Original reporter:
The patch epm-literal2.patch I posted today does not work. I will post a fixed version.
Bodo
Original reporter: Michael Sweet
Fixed in Subversion repository.
"epm-literal.patch":
Index: epm.h
===================================================================
--- epm.h (revision 758)
+++ epm.h (working copy)
@@ -203,6 +203,12 @@
const char *subpackage; /* Sub-package name */
} description_t;
+typedef struct /**** Literal Structure ****/
+{
+ char *literal; /* literal string to be added for a format */
+ const char *subpackage; /* Sub-package name (i think this is not needed?) */
+} literal_t;
+
typedef struct /**** Distribution Structure ****/
{
char product[256], /* Product name */
@@ -217,6 +223,8 @@
char **subpackages; /* Subpackage names */
int num_descriptions; /* Number of description strings */
description_t *descriptions; /* Description strings */
+ int num_literals; /* Number of literal strings */
+ literal_t *literals; /* Literal strings */
int vernumber, /* Version number */
epoch; /* Epoch number */
int num_commands; /* Number of commands */
@@ -251,6 +259,8 @@
const char *subpkg);
extern void add_description(dist_t *dist, FILE *fp, const char *description,
const char *subpkg);
+extern void add_literal(dist_t *dist, FILE *fp, const char *literal,
+ const char *subpkg);
extern file_t *add_file(dist_t *dist, const char *subpkg);
extern char *add_subpackage(dist_t *dist, const char *subpkg);
extern int copy_file(const char *dst, const char *src,
Index: rpm.c
===================================================================
--- rpm.c (revision 758)
+++ rpm.c (working copy)
@@ -569,6 +569,7 @@
int i; /* Looping var */
char name[1024]; /* Full product name */
const char *product; /* Product to depend on */
+ literal_t *literal; /* Current literal line */
file_t *file; /* Current distribution file */
command_t *c; /* Current command */
depend_t *d; /* Current dependency */
@@ -693,6 +694,9 @@
else
have_commands = 0;
+ for (i = dist->num_literals, literal = dist->literals; i > 0; i --, literal ++)
+ fprintf(fp, "%s\n", literal->literal);
+
for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
if (tolower(file->type) == 'i' && file->subpackage == subpackage)
break;
Index: dist.c
===================================================================
--- dist.c (revision 758)
+++ dist.c (working copy)
@@ -19,6 +19,7 @@
*
* add_command() - Add a command to the distribution...
* add_depend() - Add a dependency to the distribution...
+ * add_literal() - Add a literal string to the distribution.
* add_description() - Add a description to the distribution.
* add_file() - Add a file to the distribution.
* add_subpackage() - Add a subpackage to the distribution.
@@ -334,7 +335,59 @@
perror("epm: Out of memory duplicating description");
}
+/*
+ * 'add_literal()' - Add a literal strings to the distribution.
+ */
+void
+add_literal(dist_t *dist, /* I - Distribution */
+ FILE *fp, /* I - Source file */
+ const char *literal,/* I - Literal string */
+ const char *subpkg) /* I - Subpackage name */
+{
+ literal_t *temp; /* Temporary literal array */
+ char buf[16384]; /* File import buffer */
+
+
+ if (strncmp(literal, "<<", 2) == 0)
+ {
+ for (literal += 2; isspace(*literal & 255); literal ++);
+
+ literal = get_inline(literal, fp, buf, sizeof(buf));
+ }
+ else if (literal[0] == '<' && literal[1])
+ {
+ for (literal ++; isspace(*literal & 255); literal ++);
+
+ literal = get_file(literal, buf, sizeof(buf));
+ }
+
+ if (literal == NULL)
+ return;
+
+ if (dist->num_literals == 0)
+ temp = malloc(sizeof(literal_t));
+ else
+ temp = realloc(dist->literals,
+ (dist->num_literals + 1) * sizeof(literal_t));
+
+ if (temp == NULL)
+ {
+ perror("epm: Out of memory adding literal");
+ return;
+ }
+
+ dist->literals = temp;
+ temp += dist->num_literals;
+ dist->num_literals ++;
+
+ temp->subpackage = subpkg;
+
+ if ((temp->literal = strdup(literal)) == NULL)
+ perror("epm: Out of memory duplicating literal");
+}
+
+
/*
* 'add_file()' - Add a file to the distribution.
*/
@@ -861,6 +914,8 @@
}
else if (strcmp(line, "%description") == 0)
add_description(dist, listfiles[listlevel], temp, subpkg);
+ else if (strcmp(line, "%literal") == 0)
+ add_literal(dist, listfiles[listlevel], temp, subpkg);
else if (strcmp(line, "%preinstall") == 0)
add_command(dist, listfiles[listlevel], COMMAND_PRE_INSTALL, temp,
subpkg);
[root@localhost epm-svn]#
"epm-literal2.patch":
? epm-literal.patch
Index: dist.c
===================================================================
RCS file: /export/cvs/lib/epm/dist.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 dist.c
--- dist.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ dist.c 11 Apr 2008 13:59:13 -0000
@@ -120,7 +120,26 @@
{
command_t *temp; /* New command */
char buf[16384]; /* File import buffer */
+ char *key = NULL; /* key string for special command */
+ /* handle key string for special commands */
+ if(type == COMMAND_SPECIAL)
+ {
+ char *ptr;
+ if (command[0] == '(')
+ {
+ command++;
+ ptr = strchr(command, ')');
+ if (ptr != NULL)
+ {
+ *ptr = '\0';
+ key = strdup(command);
+ command = ptr + 1;
+ }
+ /* FIXME: error handling for missing ')' */
+ }
+ if (key == NULL) key = strdup("");
+ }
if (strncmp(command, "<<", 2) == 0)
{
@@ -136,7 +155,10 @@
}
if (command == NULL)
+ {
+ if(key != NULL) free(key);
return;
+ }
if (dist->num_commands == 0)
temp = malloc(sizeof(command_t));
@@ -146,6 +168,7 @@
if (temp == NULL)
{
perror("epm: Out of memory allocating a command");
+ if(key != NULL) free(key);
return;
}
@@ -154,10 +177,12 @@
temp->type = type;
temp->command = strdup(command);
temp->subpackage = subpkg;
+ temp->key = key;
if (temp->command == NULL)
{
perror("epm: Out of memory duplicating a command string");
+ if (key != NULL) free(key);
return;
}
@@ -908,6 +933,11 @@
strcmp(line, "%postpatch") == 0)
add_command(dist, listfiles[listlevel], COMMAND_POST_PATCH, temp,
subpkg);
+ else if (strcmp(line, "%literal") == 0 ||
+ strncmp(line, "%literal(", 9) == 0)
+ /* we use line+8 instead of temp to allow parsing "(key)" */
+ add_command(dist, listfiles[listlevel], COMMAND_SPECIAL, line+8,
+ subpkg);
else if (strcmp(line, "%product") == 0)
{
if (!dist->product[0])
Index: epm.h
===================================================================
RCS file: /export/cvs/lib/epm/epm.h,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 epm.h
--- epm.h 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ epm.h 11 Apr 2008 13:17:54 -0000
@@ -119,7 +119,9 @@
COMMAND_PRE_PATCH, /* Command to run before patch */
COMMAND_POST_PATCH, /* Command to run after patch */
COMMAND_PRE_REMOVE, /* Command to run before remove */
- COMMAND_POST_REMOVE /* Command to run after remove */
+ COMMAND_POST_REMOVE, /* Command to run after remove */
+ COMMAND_SPECIAL /* special command data (depends
+ on package format type) */
};
/*
@@ -188,6 +190,7 @@
int type; /* Command type */
char *command; /* Command string */
const char *subpackage; /* Sub-package name */
+ const char *key; /* key string for special commands */
} command_t;
typedef struct /**** Dependencies ****/
Index: pkg.c
===================================================================
RCS file: /export/cvs/lib/epm/pkg.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 pkg.c
--- pkg.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ pkg.c 11 Apr 2008 13:17:54 -0000
@@ -56,7 +56,8 @@
preinstall[1024], /* Pre install script */
postinstall[1024], /* Post install script */
preremove[1024], /* Pre remove script */
- postremove[1024]; /* Post remove script */
+ postremove[1024], /* Post remove script */
+ request[1024]; /* Request script */
char current[1024]; /* Current directory */
file_t *file; /* Current distribution file */
command_t *c; /* Current command */
@@ -336,6 +337,47 @@
postremove[0] = '\0';
/*
+ * Write the request file for pkgmk...
+ */
+
+ for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
+ if ((c->type == COMMAND_SPECIAL) && (strcmp(c->key, "request") == 0))
+ break;
+
+ if (i)
+ {
+ /*
+ * Write the request file for pkgmk...
+ */
+
+ if (Verbosity)
+ puts("Creating request script...");
+
+ snprintf(request, sizeof(request), "%s/%s.request", directory,
+ prodname);
+
+ if ((fp = fopen(request, "w")) == NULL)
+ {
+ fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", request,
+ strerror(errno));
+ return (1);
+ }
+
+ fchmod(fileno(fp), 0755);
+
+ fputs("#!/bin/sh\n", fp);
+ fputs("# " EPM_VERSION "\n", fp);
+
+ for (; i > 0; i --, c ++)
+ if ((c->type == COMMAND_SPECIAL) && (strcmp(c->key, "request") == 0))
+ fprintf(fp, "%s\n", c->command);
+
+ fclose(fp);
+ }
+ else
+ request[0] = '\0';
+
+ /*
* Add symlinks for init scripts...
*/
@@ -419,6 +461,8 @@
fprintf(fp, "i preremove=%s\n", pkg_path(preremove, current));
if (postremove[0])
fprintf(fp, "i postremove=%s\n", pkg_path(postremove, current));
+ if (request[0])
+ fprintf(fp, "i request=%s\n", pkg_path(request, current));
for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
switch (tolower(file->type))
@@ -524,6 +568,8 @@
unlink(preremove);
if (postremove[0])
unlink(postremove);
+ if (request[0])
+ unlink(request);
}
/*
Index: rpm.c
===================================================================
RCS file: /export/cvs/lib/epm/rpm.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 rpm.c
--- rpm.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ rpm.c 11 Apr 2008 13:17:54 -0000
@@ -704,6 +704,24 @@
else
have_commands = 0;
+ for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
+ if (c->type == COMMAND_SPECIAL && c->subpackage == subpackage &&
+ /* allow empty key for compatibility with patch provided
+ by Sven Dowideit or key "spec" */
+ ( c->key[0] == '\0' || strcmp(c->key, "spec") == 0 ) )
+ break;
+
+ if (i > 0)
+ {
+ for (; i > 0; i --, c ++)
+ if (c->type == COMMAND_SPECIAL && c->subpackage == subpackage &&
+ /* allow empty key for compatibility with patch provided
+ by Sven Dowideit or key "spec" */
+ ( c->key[0] == '\0' || strcmp(c->key, "spec") == 0 ) )
+ fprintf(fp, "%s\n", c->command);
+
+ }
+
for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
if (tolower(file->type) == 'i' && file->subpackage == subpackage)
break;
"epm-literal3.patch":
? epm-literal.patch
Index: pkg.c
===================================================================
RCS file: /export/cvs/lib/epm/pkg.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 pkg.c
--- pkg.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ pkg.c 11 Apr 2008 13:17:54 -0000
@@ -56,7 +56,8 @@
preinstall[1024], /* Pre install script */
postinstall[1024], /* Post install script */
preremove[1024], /* Pre remove script */
- postremove[1024]; /* Post remove script */
+ postremove[1024], /* Post remove script */
+ request[1024]; /* Request script */
char current[1024]; /* Current directory */
file_t *file; /* Current distribution file */
command_t *c; /* Current command */
@@ -336,6 +337,47 @@
postremove[0] = '\0';
/*
+ * Write the request file for pkgmk...
+ */
+
+ for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
+ if ((c->type == COMMAND_SPECIAL) && (strcmp(c->key, "request") == 0))
+ break;
+
+ if (i)
+ {
+ /*
+ * Write the request file for pkgmk...
+ */
+
+ if (Verbosity)
+ puts("Creating request script...");
+
+ snprintf(request, sizeof(request), "%s/%s.request", directory,
+ prodname);
+
+ if ((fp = fopen(request, "w")) == NULL)
+ {
+ fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", request,
+ strerror(errno));
+ return (1);
+ }
+
+ fchmod(fileno(fp), 0755);
+
+ fputs("#!/bin/sh\n", fp);
+ fputs("# " EPM_VERSION "\n", fp);
+
+ for (; i > 0; i --, c ++)
+ if ((c->type == COMMAND_SPECIAL) && (strcmp(c->key, "request") == 0))
+ fprintf(fp, "%s\n", c->command);
+
+ fclose(fp);
+ }
+ else
+ request[0] = '\0';
+
+ /*
* Add symlinks for init scripts...
*/
@@ -419,6 +461,8 @@
fprintf(fp, "i preremove=%s\n", pkg_path(preremove, current));
if (postremove[0])
fprintf(fp, "i postremove=%s\n", pkg_path(postremove, current));
+ if (request[0])
+ fprintf(fp, "i request=%s\n", pkg_path(request, current));
for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
switch (tolower(file->type))
@@ -524,6 +568,8 @@
unlink(preremove);
if (postremove[0])
unlink(postremove);
+ if (request[0])
+ unlink(request);
}
/*
Index: rpm.c
===================================================================
RCS file: /export/cvs/lib/epm/rpm.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 rpm.c
--- rpm.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ rpm.c 11 Apr 2008 13:17:54 -0000
@@ -704,6 +704,24 @@
else
have_commands = 0;
+ for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
+ if (c->type == COMMAND_SPECIAL && c->subpackage == subpackage &&
+ /* allow empty key for compatibility with patch provided
+ by Sven Dowideit or key "spec" */
+ ( c->key[0] == '\0' || strcmp(c->key, "spec") == 0 ) )
+ break;
+
+ if (i > 0)
+ {
+ for (; i > 0; i --, c ++)
+ if (c->type == COMMAND_SPECIAL && c->subpackage == subpackage &&
+ /* allow empty key for compatibility with patch provided
+ by Sven Dowideit or key "spec" */
+ ( c->key[0] == '\0' || strcmp(c->key, "spec") == 0 ) )
+ fprintf(fp, "%s\n", c->command);
+
+ }
+
for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
if (tolower(file->type) == 'i' && file->subpackage == subpackage)
break;
Index: epm.h
===================================================================
RCS file: /export/cvs/lib/epm/epm.h,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.3
diff -u -r1.1.2.1 -r1.1.2.3
--- epm.h 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ epm.h 11 Apr 2008 15:46:12 -0000 1.1.2.3
@@ -119,7 +119,9 @@
COMMAND_PRE_PATCH, /* Command to run before patch */
COMMAND_POST_PATCH, /* Command to run after patch */
COMMAND_PRE_REMOVE, /* Command to run before remove */
- COMMAND_POST_REMOVE /* Command to run after remove */
+ COMMAND_POST_REMOVE, /* Command to run after remove */
+ COMMAND_SPECIAL /* special command data (depends
+ on package format type) */
};
/*
@@ -188,6 +190,7 @@
int type; /* Command type */
char *command; /* Command string */
const char *subpackage; /* Sub-package name */
+ const char *key; /* key string for special commands */
} command_t;
typedef struct /**** Dependencies ****/
@@ -248,7 +251,8 @@
*/
extern void add_command(dist_t *dist, FILE *fp, int type,
- const char *command, const char *subpkg);
+ const char *command, const char *subpkg,
+ const char *key);
extern void add_depend(dist_t *dist, int type, const char *line,
const char *subpkg);
extern void add_description(dist_t *dist, FILE *fp, const char *description,
Index: dist.c
===================================================================
RCS file: /export/cvs/lib/epm/dist.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.5
diff -u -r1.1.2.1 -r1.1.2.5
--- dist.c 3 Mar 2008 15:52:50 -0000 1.1.2.1
+++ dist.c 11 Apr 2008 15:51:26 -0000 1.1.2.5
@@ -116,12 +116,12 @@
FILE *fp, /* I - Distribution file */
int type, /* I - Command type */
const char *command, /* I - Command string */
- const char *subpkg) /* I - Subpackage */
+ const char *subpkg, /* I - Subpackage */
+ const char *key) /* I - Key for special command */
{
command_t *temp; /* New command */
char buf[16384]; /* File import buffer */
-
if (strncmp(command, "<<", 2) == 0)
{
for (command += 2; isspace(*command & 255); command ++);
@@ -136,7 +136,9 @@
}
if (command == NULL)
+ {
return;
+ }
if (dist->num_commands == 0)
temp = malloc(sizeof(command_t));
@@ -153,13 +155,22 @@
temp += dist->num_commands;
temp->type = type;
temp->command = strdup(command);
- temp->subpackage = subpkg;
-
if (temp->command == NULL)
{
perror("epm: Out of memory duplicating a command string");
return;
}
+ temp->subpackage = subpkg;
+ if(key != NULL)
+ {
+ temp->key = strdup(key);
+ if (temp->key == NULL)
+ {
+ perror("epm: Out of memory duplicating a command string");
+ free(temp->command);
+ return;
+ }
+ }
dist->num_commands ++;
}
@@ -889,25 +900,46 @@
add_description(dist, listfiles[listlevel], temp, subpkg);
else if (strcmp(line, "%preinstall") == 0)
add_command(dist, listfiles[listlevel], COMMAND_PRE_INSTALL, temp,
- subpkg);
+ subpkg, NULL);
else if (strcmp(line, "%install") == 0 ||
strcmp(line, "%postinstall") == 0)
add_command(dist, listfiles[listlevel], COMMAND_POST_INSTALL, temp,
- subpkg);
+ subpkg, NULL);
else if (strcmp(line, "%remove") == 0 ||
strcmp(line, "%preremove") == 0)
add_command(dist, listfiles[listlevel], COMMAND_PRE_REMOVE, temp,
- subpkg);
+ subpkg, NULL);
else if (strcmp(line, "%postremove") == 0)
add_command(dist, listfiles[listlevel], COMMAND_POST_REMOVE, temp,
- subpkg);
+ subpkg, NULL);
else if (strcmp(line, "%prepatch") == 0)
add_command(dist, listfiles[listlevel], COMMAND_PRE_PATCH, temp,
- subpkg);
+ subpkg, NULL);
else if (strcmp(line, "%patch") == 0 ||
strcmp(line, "%postpatch") == 0)
add_command(dist, listfiles[listlevel], COMMAND_POST_PATCH, temp,
- subpkg);
+ subpkg, NULL);
+ else if (strcmp(line, "%literal") == 0 ||
+ strncmp(line, "%literal(", 9) == 0)
+ {
+ char *ptr;
+ char *key = NULL;
+ ptr = strchr(line, '(');
+ if(ptr != NULL)
+ {
+ key = ptr + 1;
+ ptr = strchr(key, ')');
+ if (ptr != NULL)
+ {
+ *ptr = '\0';
+ }
+ /* FIXME: error handling for missing ')' */
+ }
+ if (key == NULL) key = "";
+
+ add_command(dist, listfiles[listlevel], COMMAND_SPECIAL, temp,
+ subpkg, key);
+ }
else if (strcmp(line, "%product") == 0)
{
if (!dist->product[0])
Version: -feature Original reporter: Michael Sweet
Hello,
I've been writing an epm based installer for TWiki (perl based), and have gotten to the point where rpmbuild is making a mess that I need to prevent.
when I hard code in the magic rpm defines to add a custom provides and requires script as per the following url's
http://fedoraproject.org/wiki/PackagingDrafts/FilteringAutomaticDependencies http://fedoraproject.org/wiki/Packaging/Perl
my package does not get dependencies on things like perl(further) due to redhat's rather nasty magical dependency code.
SO I was thinking to solve this by: adding a way for EPM list files to contain literal strings into whatever output files are made (presumably re-using the %format qualifier).
the syntax i'm thinking, would just be to have lines that start with '%literal' be appended to each other, and then inserted into the native package's file.
so in my case i'd add something like
%format rpm %literal %define __perl_provides $prefix/perl.prov %literal %define __perl_requires $prefix/perl.req %format all
thus adding %define __perl_provides "/var/www/twiki/perl.prov" %define __perl_requires "/var/www/twiki/perl.req"
to the spec file
I will need help with the platforms i don't have access to (like HP/UX).
Is there a better way to achieve this? or should i just code it up, and hand it over to you guys?
Cheers
Sven