Commit b3608952 authored by Bernhard Link's avatar Bernhard Link

add ByHandHooks to conf/distributions for hooks called by processincoming (and...

add ByHandHooks to conf/distributions for hooks called by processincoming (and in the future perhaps by include)
parent bcee4732
2010-01-24
* add ByHandHooks to conf/distributions for hooks
called by processincoming (and in the future perhaps by include)
2010-01-18
* properly handle relative LogDir in conf/incoming
......
......@@ -18,14 +18,14 @@ AM_CPPFLAGS = -Wall $(ARCHIVECPP) $(DBCPPFLAGS)
reprepro_LDADD = $(ARCHIVELIBS) $(DBLIBS)
changestool_LDADD = $(ARCHIVELIBS)
reprepro_SOURCES = archallflood.c needbuild.c globmatch.c printlistformat.c diffindex.c rredpatch.c pool.c atoms.c uncompression.c remoterepository.c indexfile.c copypackages.c sourceextraction.c checksums.c readtextfile.c filecntl.c sha1.c sha256.c configparser.c database.c freespace.c log.c changes.c incoming.c uploaderslist.c guesscomponent.c files.c md5.c dirs.c chunks.c reference.c binaries.c sources.c checks.c names.c dpkgversions.c release.c mprintf.c updates.c strlist.c signature_check.c signature.c distribution.c checkindeb.c checkindsc.c checkin.c upgradelist.c target.c aptmethod.c downloadcache.c main.c override.c terms.c termdecide.c ignore.c filterlist.c exports.c tracking.c optionsfile.c readrelease.c donefile.c pull.c contents.c filelist.c $(ARCHIVE_USED) $(ARCHIVE_CONTENTS)
reprepro_SOURCES = byhandhook.c archallflood.c needbuild.c globmatch.c printlistformat.c diffindex.c rredpatch.c pool.c atoms.c uncompression.c remoterepository.c indexfile.c copypackages.c sourceextraction.c checksums.c readtextfile.c filecntl.c sha1.c sha256.c configparser.c database.c freespace.c log.c changes.c incoming.c uploaderslist.c guesscomponent.c files.c md5.c dirs.c chunks.c reference.c binaries.c sources.c checks.c names.c dpkgversions.c release.c mprintf.c updates.c strlist.c signature_check.c signature.c distribution.c checkindeb.c checkindsc.c checkin.c upgradelist.c target.c aptmethod.c downloadcache.c main.c override.c terms.c termdecide.c ignore.c filterlist.c exports.c tracking.c optionsfile.c readrelease.c donefile.c pull.c contents.c filelist.c $(ARCHIVE_USED) $(ARCHIVE_CONTENTS)
EXTRA_reprepro_SOURCE = $(ARCHIVE_UNUSED)
changestool_SOURCES = uncompression.c sourceextraction.c readtextfile.c filecntl.c tool.c chunkedit.c strlist.c checksums.c sha1.c sha256.c md5.c mprintf.c chunks.c signature.c dirs.c names.c $(ARCHIVE_USED)
rredtool_SOURCES = rredtool.c rredpatch.c mprintf.c filecntl.c sha1.c
noinst_HEADERS = archallflood.h needbuild.h globmatch.h printlistformat.h pool.h atoms.h uncompression.h remoterepository.h copypackages.h sourceextraction.h checksums.h readtextfile.h filecntl.h sha1.h sha256.h configparser.h database_p.h database.h freespace.h log.h changes.h incoming.h guesscomponent.h md5.h dirs.h files.h chunks.h reference.h binaries.h sources.h checks.h names.h release.h error.h mprintf.h updates.h strlist.h signature.h signature_p.h distribution.h debfile.h checkindeb.h checkindsc.h upgradelist.h target.h aptmethod.h downloadcache.h override.h terms.h termdecide.h ignore.h filterlist.h dpkgversions.h checkin.h exports.h globals.h tracking.h trackingt.h optionsfile.h readrelease.h donefile.h pull.h ar.h filelist.h contents.h chunkedit.h uploaderslist.h indexfile.h rredpatch.h diffindex.h
noinst_HEADERS = byhandhook.h archallflood.h needbuild.h globmatch.h printlistformat.h pool.h atoms.h uncompression.h remoterepository.h copypackages.h sourceextraction.h checksums.h readtextfile.h filecntl.h sha1.h sha256.h configparser.h database_p.h database.h freespace.h log.h changes.h incoming.h guesscomponent.h md5.h dirs.h files.h chunks.h reference.h binaries.h sources.h checks.h names.h release.h error.h mprintf.h updates.h strlist.h signature.h signature_p.h distribution.h debfile.h checkindeb.h checkindsc.h upgradelist.h target.h aptmethod.h downloadcache.h override.h terms.h termdecide.h ignore.h filterlist.h dpkgversions.h checkin.h exports.h globals.h tracking.h trackingt.h optionsfile.h readrelease.h donefile.h pull.h ar.h filelist.h contents.h chunkedit.h uploaderslist.h indexfile.h rredpatch.h diffindex.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/configure $(srcdir)/stamp-h.in $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
......
Updates between 4.0.2 and 4.1.0:
- rredtool can be used as index hook to maintain a .diff/Index file.
- properly handle relative LogDir in conf/incoming
- add ByHandHooks to conf/distributions (only used by processincoming yet)
Updates between 4.0.1 and 4.0.2:
- add support for xz de-compression
......
/* This file is part of "reprepro"
* Copyright (C) 2010 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <config.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "error.h"
#include "filecntl.h"
#include "names.h"
#include "configparser.h"
#include "globmatch.h"
#include "log.h" // for causing*
#include "byhandhook.h"
struct byhandhook {
/*@null@*/struct byhandhook *next;
char *sectionglob;
char *priorityglob;
char *filenameglob;
char *script;
};
void byhandhooks_free(struct byhandhook *l) {
while( l != NULL ) {
/*@null@*/struct byhandhook *n = l->next;
free(l->sectionglob);
free(l->priorityglob);
free(l->filenameglob);
free(l->script);
free(l);
l = n;
}
}
retvalue byhandhooks_parse(struct configiterator *iter, struct byhandhook **hooks_p) {
retvalue r;
char *v;
struct byhandhook *h, *hooks = NULL, **nexthook_p = &hooks;
r = config_getwordinline(iter, &v);
if( RET_IS_OK(r) ) {
fprintf(stderr, "Error parsing %s, line %u, column %u: unexpected input '%s' (each hook must be in its own line)!\n",
config_filename(iter),
config_markerline(iter),
config_markercolumn(iter),
v);
free(v);
r = RET_ERROR;
}
if( RET_WAS_ERROR(r) )
return r;
while( config_nextline(iter) ) {
r = config_getwordinline(iter, &v);
if( r == RET_NOTHING )
continue;
if( RET_WAS_ERROR(r) )
return r;
h = calloc(1, sizeof(struct byhandhook));
if( FAILEDTOALLOC(h) ) {
byhandhooks_free(hooks);
return RET_ERROR_OOM;
}
h->sectionglob = v;
r = config_getwordinline(iter, &v);
if( r == RET_NOTHING ) {
fprintf(stderr, "Error parsing %s, line %u, column %u: each byhand hooks needs 4 arguments, found only 1!\n",
config_filename(iter),
config_markerline(iter),
config_markercolumn(iter));
r = RET_ERROR;
}
if( RET_WAS_ERROR(r) ) {
byhandhooks_free(hooks);
return r;
}
h->priorityglob = v;
r = config_getwordinline(iter, &v);
if( r == RET_NOTHING ) {
fprintf(stderr, "Error parsing %s, line %u, column %u: each byhand hooks needs 4 arguments, found only 2!\n",
config_filename(iter),
config_markerline(iter),
config_markercolumn(iter));
r = RET_ERROR;
}
if( RET_WAS_ERROR(r) ) {
byhandhooks_free(hooks);
return r;
}
h->filenameglob = v;
r = config_getwordinline(iter, &v);
if( r == RET_NOTHING ) {
fprintf(stderr, "Error parsing %s, line %u, column %u: each byhand hooks needs 4 arguments, found only 2!\n",
config_filename(iter),
config_markerline(iter),
config_markercolumn(iter));
r = RET_ERROR;
}
if( RET_WAS_ERROR(r) ) {
byhandhooks_free(hooks);
return r;
}
assert( v != NULL && v[0] != '\0' ); \
if( v[0] != '/' ) {
h->script = calc_dirconcat(global.confdir, v);
free(v);
if( h->script == NULL ) {
byhandhooks_free(hooks);
return RET_ERROR_OOM;
}
} else
h->script = v;
r = config_getwordinline(iter, &v);
if( RET_IS_OK(r) ) {
fprintf(stderr, "Error parsing %s, line %u, column %u: each byhand hooks needs exactly 4 arguments, but there are more (first unexpected: '%s'!\n",
config_filename(iter),
config_markerline(iter),
config_markercolumn(iter), v);
free(v);
r = RET_ERROR;
}
if( RET_WAS_ERROR(r) ) {
byhandhooks_free(hooks);
return r;
}
*nexthook_p = h;
nexthook_p = &h->next;
}
*hooks_p = hooks;
return RET_OK;
}
bool byhandhooks_matched(const struct byhandhook *list, const struct byhandhook **touse, const char *section, const char *priority, const char *filename) {
const struct byhandhook *h;
/* for each file the first matching hook is called
* it might later be extended to allow multiple with some keywords */
if( *touse != NULL )
/* if( (*touse)->nonexclusive ) list = (*touse)->next ; else */
return false;
for( h = list ; h != NULL ; h = h->next ) {
if( !globmatch(section, h->sectionglob) )
continue;
if( !globmatch(priority, h->priorityglob) )
continue;
if( !globmatch(filename, h->filenameglob) )
continue;
*touse = h;
return true;
}
return false;
}
retvalue byhandhook_call(const struct byhandhook *h, const char *codename, const char *section, const char *priority, const char *name, const char *fullfilename) {
pid_t child;
child = fork();
if( child == 0 ) {
/* Try to close all open fd but 0,1,2 */
closefrom(3);
if( causingfile != NULL )
setenv("REPREPRO_CAUSING_FILE", causingfile, true);
else
unsetenv("REPREPRO_CAUSING_FILE");
if( atom_defined(causingcommand_atom) )
setenv("REPREPRO_CAUSING_COMMAND",
atoms_commands[causingcommand_atom],
true);
else
unsetenv("REPREPRO_CAUSING_COMMAND");
setenv("REPREPRO_BASE_DIR", global.basedir, true);
setenv("REPREPRO_OUT_DIR", global.outdir, true);
setenv("REPREPRO_CONF_DIR", global.confdir, true);
setenv("REPREPRO_DIST_DIR", global.distdir, true);
setenv("REPREPRO_LOG_DIR", global.logdir, true);
(void)execl(h->script, h->script, codename,
section, priority, name,
fullfilename, (char*)NULL);
{
int e = errno;
fprintf(stderr, "Error %d executing '%s': %s\n",
e, h->script,
strerror(e));
}
_exit(255);
}
if( child < 0 ) {
int e = errno;
fprintf(stderr, "Error %d forking: %s!\n", e, strerror(e));
return RET_ERRNO(e);
}
while( true ) {
int status;
pid_t pid;
pid = waitpid(child, &status, 0);
if( pid == child ) {
if( WIFEXITED(status) ) {
if( WEXITSTATUS(status) == 0) {
return RET_OK;
}
fprintf(stderr,
"Byhandhook '%s' '%s' '%s' '%s' '%s' '%s' failed with exit code %d!\n",
h->script, codename,
section, priority, name,
fullfilename,
(int)(WEXITSTATUS(status)));
} else if( WIFSIGNALED(status) ) {
fprintf(stderr,
"Byhandhook '%s' '%s' '%s' '%s' '%s' '%s' killed by signal %d!\n",
h->script, codename,
section, priority, name,
fullfilename,
(int)(WTERMSIG(status)));
} else {
fprintf(stderr,
"Byhandhook '%s' '%s' '%s' '%s' '%s' '%s' failed!\n",
h->script, codename,
section, priority, name,
fullfilename);
}
return RET_ERROR;
} else if( pid == (pid_t)-1 ) {
int e = errno;
if( e == EINTR )
continue;
fprintf(stderr,
"Error %d calling waitpid on byhandhook child: %s\n",
e, strerror(e));
return RET_ERRNO(e);
}
}
/* NOT REACHED */
}
#ifndef REPREPRO_BYHANDHOOK_H
#define REPREPRO_BYHANDHOOK_H
#ifndef REPREPRO_ERROR_H
#include "error.h"
#warning "What's hapening here?"
#endif
#ifndef REPREPRO_ERROR_H
#include "error.h"
#warning "What's hapening here?"
#endif
struct byhandhook;
retvalue byhandhooks_parse(struct configiterator *, /*@out@*/struct byhandhook **);
/* 2nd argument starts as NULL, returns true as long as there are hooks */
bool byhandhooks_matched(const struct byhandhook *, const struct byhandhook **, const char *section, const char *priority, const char *name);
retvalue byhandhook_call(const struct byhandhook *, const char *codename, const char *section, const char *priority, const char *basename, const char *fullfilename);
void byhandhooks_free(/*@null@*//*@only@*/struct byhandhook *);
#endif
/* This file is part of "reprepro"
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Bernhard R. Link
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
......@@ -39,6 +39,7 @@
#include "ignore.h"
#include "uploaderslist.h"
#include "configparser.h"
#include "byhandhook.h"
#include "distribution.h"
static retvalue distribution_free(struct distribution *distribution) {
......@@ -77,6 +78,7 @@ static retvalue distribution_free(struct distribution *distribution) {
if( distribution->uploaderslist != NULL ) {
uploaders_unlock(distribution->uploaderslist);
}
byhandhooks_free(distribution->byhandhooks);
result = RET_OK;
while( distribution->targets != NULL ) {
......@@ -422,9 +424,17 @@ CFUSETPROC(distribution, Tracking) {
return tracking_parse(d, iter);
}
CFUSETPROC(distribution, byhandhooks) {
CFSETPROCVAR(distribution, d);
return byhandhooks_parse(iter, &d->byhandhooks);
}
static const struct configfield distributionconfigfields[] = {
CF("AlsoAcceptFor", distribution, alsoaccept),
CFr("Architectures", distribution, architectures),
CF("ByHandHooks", distribution, byhandhooks),
CFr("Codename", distribution, codename),
CFr("Components", distribution, components),
CF("ContentsArchitectures", distribution, contents_architectures),
......
......@@ -83,6 +83,8 @@ struct distribution {
/*@null@*/struct uploaders *uploaderslist;
/* how and where to log */
/*@null@*/struct logger *logger;
/* scripts to feed byhand/raw-* files in */
/*@null@*/struct byhandhook *byhandhooks;
/* a list of names beside Codename and Suite to accept .changes
* files via include */
struct strlist alsoaccept;
......
EXTRA_DIST = short-howto reprepro.1 changestool.1 rredtool.1 recovery bzip.example tiffany.example di.example/README di.example/DI-filter.sh di.example/distributions di.example/updates reprepro.bash_completion reprepro.zsh_completion FAQ changelogs.example manual.html
EXTRA_DIST = short-howto reprepro.1 changestool.1 rredtool.1 recovery bzip.example tiffany.example di.example/README di.example/DI-filter.sh di.example/distributions di.example/updates reprepro.bash_completion reprepro.zsh_completion FAQ changelogs.example manual.html copybyhand.example
man_MANS = reprepro.1 changestool.1 rredtool.1
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
#!/bin/sh
# This is an example script for a byhandhook.
# Add to you conf/distributions something like
##ByhandHooks:
## * * * copybyhand.sh
# and copy this script as copybyhand.sh in your conf/
# directory (or give the full path), and processincoming
# will copy all byhand/raw files to dists/codename/extra/*
set -e
if [ $# != 5 ] ; then
echo "to be called by reprepro as byhandhook" >&2
exit 1
fi
if [ -z "$REPREPRO_DIST_DIR" ] ; then
echo "to be called by reprepro as byhandhook" >&2
exit 1
fi
codename="$1"
section="$2"
priority="$3"
basefilename="$4"
fullfilename="$5"
mkdir -p "$REPREPRO_DIST_DIR/$codename/extra"
install -T -- "$fullfilename" "$REPREPRO_DIST_DIR/$codename/extra/$basefilename"
......@@ -1305,6 +1305,23 @@ header in Release files that points 42 days into the future.
.B ReadOnly
Disallow all modifications of this distribution or its directory
in \fBdists/\fP\fIcodename\fP (with the exception of snapshot subdirectories).
.TP
.B ByHandHooks
This species hooks to call for handling byhand/raw files by processincoming
(and in future versions perhaps by include).
Each line consists out of 4 arguments:
A glob pattern for the section
(clasically \fBbyhand\fP, though Ubuntu uses \fBraw-\fP*),
a glob pattern for the priority (not usually used),
and a glob pattern for the filename.
The 4th argument is the script to be called when all of the above match.
It gets 5 arguments: the codename of the distribution,
the section (usually \fBbyhand\fP),
the priority (usually only \fB\-\fP),
the filename in the changes file and
the full filename (with processincoming in the secure TmpDir).
.SS conf/updates
.TP
.B Name
......
/* This file is part of "reprepro"
* Copyright (C) 2006,2007,2008,2009 Bernhard R. Link
* Copyright (C) 2006,2007,2008,2009,2010 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
......@@ -50,6 +50,7 @@
#include "incoming.h"
#include "files.h"
#include "configparser.h"
#include "byhandhook.h"
#include "changes.h"
enum permitflags {
......@@ -487,7 +488,7 @@ struct candidate {
struct candidate_perdistribution {
struct candidate_perdistribution *next;
struct distribution *into;
bool skip, byhandhook;
bool skip;
struct candidate_package {
/* a package is something installing files, including
* the pseudo-package for the .changes file, if that is
......@@ -507,6 +508,11 @@ struct candidate {
/* true if skipped because already there or newer */
bool skip;
} *packages;
struct byhandfile {
struct byhandfile *next;
const struct candidate_file *file;
const struct byhandhook *hook;
} *byhandhookstocall;
} *perdistribution;
/* the logsubdir, and the list of files to put there, otherwise both NULL */
char *logsubdir;
......@@ -559,6 +565,11 @@ static void candidate_free(/*@only@*/struct candidate *c) {
d->packages = p->next;
candidate_package_free(p);
}
while( d->byhandhookstocall != NULL ) {
struct byhandfile *h = d->byhandhookstocall;
d->byhandhookstocall = h->next;
free(h);
}
free(d);
}
while( c->files != NULL ) {
......@@ -1467,6 +1478,35 @@ static retvalue candidate_preparelogs(struct database *database, const struct in
return RET_OK;
}
static retvalue prepare_hookedbyhand(const struct incoming *i, const struct candidate *c, struct candidate_perdistribution *per, struct candidate_file *file) {
const struct distribution *d = per->into;
const struct byhandhook *h = NULL;
struct byhandfile **b_p, *b;
retvalue result = RET_NOTHING;
retvalue r;
b_p = &per->byhandhookstocall;
while( *b_p != NULL )
b_p = &(*b_p)->next;
while( byhandhooks_matched(d->byhandhooks, &h,
file->section, file->priority,
BASENAME(i, file->ofs)) ) {
r = candidate_usefile(i, c, file);
if( RET_WAS_ERROR(r) )
return r;
b = calloc(1, sizeof(struct byhandfile));
if( FAILEDTOALLOC(b) )
return RET_ERROR_OOM;
b->file = file;
b->hook = h;
*b_p = b;
b_p = &b->next;
result = RET_OK;
}
return result;
}
static retvalue prepare_for_distribution(struct database *database,const struct incoming *i,const struct candidate *c,struct candidate_perdistribution *d) {
struct candidate_file *file;
retvalue r;
......@@ -1483,8 +1523,7 @@ static retvalue prepare_for_distribution(struct database *database,const struct
r = prepare_dsc(database, i, c, d, file);
break;
case fe_BYHAND:
// if (...) d->byhandhook = true;
r = RET_NOTHING;
r = prepare_hookedbyhand(i, c, d, file);
break;
default:
r = RET_NOTHING;
......@@ -1969,7 +2008,18 @@ static retvalue candidate_finish_logdir(struct incoming *i, struct candidate *c)
}
static retvalue candidate_add_byhands(struct incoming *i, struct candidate *c, struct candidate_perdistribution *d) {
// TODO: call hook to actually include selected files.
struct byhandfile *b;
retvalue r;
for( b = d->byhandhookstocall ; b != NULL ; b = b->next ){
const struct candidate_file *f = b->file;
r = byhandhook_call(b->hook, d->into->codename,
f->section, f->priority, BASENAME(i, f->ofs),
f->tempfilename);
if( RET_WAS_ERROR(r) )
return r;
}
return RET_OK;
}
......@@ -1980,7 +2030,7 @@ static retvalue candidate_really_add(struct database *database, struct incoming
retvalue r;
for( d = c->perdistribution ; d != NULL ; d = d->next ) {
if( !d->byhandhook)
if( d->byhandhookstocall == NULL )
continue;
r = candidate_add_byhands(i, c, d);
if( RET_WAS_ERROR(r) )
......@@ -2015,7 +2065,7 @@ static retvalue candidate_really_add(struct database *database, struct incoming
&changesfilekey);
if( RET_WAS_ERROR(r) )
return r;
} if( !d->byhandhook )
} if( d->byhandhookstocall == NULL )
continue;
logger_logchanges(into->logger, into->codename,
c->source, c->changesversion, c->control,
......@@ -2094,7 +2144,7 @@ static retvalue candidate_add(struct database *database, struct incoming *i, str
return r;
if( r == RET_NOTHING ) {
d->skip = true;
if( d->byhandhook )
if( d->byhandhookstocall != NULL )
somethingtodo = true;
} else
somethingtodo = true;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment