Commit 57c1be4a authored by Bernhard Link's avatar Bernhard Link

add , , , , , as special fields in formulas

parent 0891d7e1
2009-07-25
* add $Version, $Source, $SourceVersion, $Architecture, $Component,
$PackageType as special fields in formulas.
2009-07-21
* fix build-needing to look at the correct Architecture field in
.dsc files.
......
......@@ -18,14 +18,14 @@ AM_CPPFLAGS = -std=gnu99 -Wall $(ARCHIVECPP) $(DBCPPFLAGS)
reprepro_LDADD = $(ARCHIVELIBS) $(DBLIBS)
changestool_LDADD = $(ARCHIVELIBS)
reprepro_SOURCES = 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 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 = 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
noinst_HEADERS = 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 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 = 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 since 3.11.0:
- new changestool option --create-with-all-fields
- new --morguedir option (or morguedir in conf/options, of course)
- new $Version, $Source, $SourceVersion et al on formulas
- bugfixes
Updates between 3.10.0 and 3.11.0:
- new --list-max and --list-skip options
......
/* This file is part of "reprepro"
* Copyright (C) 2003,2004,2005,2006,2007,2008 Bernhard R. Link
* Copyright (C) 2003,2004,2005,2006,2007,2008,2009 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.
......@@ -160,6 +160,18 @@ packagetype_t packagetype_find(const char *value) {
else
return atom_unknown;
}
packagetype_t packagetype_find_l(const char *value, size_t len) {
if( len == 3 ) {
if( strncmp(value, "dsc", 3) == 0 )
return pt_dsc;
else if( strncmp(value, "deb",3) == 0 )
return pt_deb;
} else if( len == 4 && strncmp(value, "udeb",4) == 0 )
return pt_udeb;
return atom_unknown;
}
static inline command_t command_find(const char *value) {
command_t c;
......
......@@ -34,6 +34,7 @@ component_t component_find(const char *);
component_t component_find_l(const char *, size_t);
component_t components_count(void);
packagetype_t packagetype_find(const char *);
packagetype_t packagetype_find_l(const char *, size_t);
atom_t atom_find(enum atom_type, const char *);
retvalue atom_intern(enum atom_type, const char *, /*@out@*/atom_t *);
......
......@@ -276,8 +276,7 @@ static retvalue configparser_ ## sname ## _set_ ## field(UNUSED(void *dummy), UN
r = config_getall(iter, &formula); \
if( ! RET_IS_OK(r) ) \
return r; \
r = term_compile(&item->field, formula, \
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL); \
r = term_compilefortargetdecision(&item->field, formula); \
free(formula); \
return r; \
}
......@@ -289,8 +288,7 @@ static retvalue configparser_ ## sname ## _set_ ## field(UNUSED(void *dummy), UN
r = config_getall(iter, &formula); \
if( ! RET_IS_OK(r) ) \
return r; \
r = term_compile(&item->field, formula, \
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL); \
r = term_compilefortargetdecision(&item->field, formula); \
free(formula); \
item->field ## _set = true; \
return r; \
......
......@@ -31,6 +31,7 @@
#include "files.h"
#include "target.h"
#include "terms.h"
#include "termdecide.h"
#include "dpkgversions.h"
#include "tracking.h"
#include "filecntl.h"
......@@ -638,7 +639,7 @@ static retvalue by_formula(struct package_list *list, struct database *database,
return r;
result = RET_NOTHING;
while( target_nextpackage(&iterator, &packagename, &chunk) ) {
r = term_decidechunk(condition, chunk);
r = term_decidechunktarget(condition, chunk, desttarget );
if( r == RET_NOTHING )
continue;
if( RET_WAS_ERROR(r) ) {
......@@ -713,8 +714,7 @@ retvalue copy_by_formula(struct database *database, struct distribution *into, s
memset(&list, 0, sizeof(list));
r = term_compile(&condition, filter,
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL);
r = term_compilefortargetdecision(&condition, filter);
if( !RET_IS_OK(r) ) {
return r;
}
......@@ -783,10 +783,10 @@ static retvalue choose_by_source(struct target *target, const char *packagename,
return RET_OK;
}
static retvalue choose_by_condition(UNUSED(struct target *target), UNUSED(const char *packagename), UNUSED(const char *version), const char *chunk, void *privdata) {
static retvalue choose_by_condition(struct target *target, UNUSED(const char *packagename), UNUSED(const char *version), const char *chunk, void *privdata) {
term *condition = privdata;
return term_decidechunk(condition, chunk);
return term_decidechunktarget(condition, chunk, target);
}
static retvalue choose_by_glob(UNUSED(struct target *target), const char *packagename, UNUSED(const char *version), UNUSED(const char *chunk), void *privdata) {
......@@ -983,8 +983,7 @@ retvalue restore_by_formula(struct database *database, struct distribution *into
term *condition;
retvalue r;
r = term_compile(&condition, filter,
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL);
r = term_compilefortargetdecision(&condition, filter);
if( !RET_IS_OK(r) ) {
return r;
}
......
reprepro (3.11.1-0) UNRELEASED; urgency=low
* new bugfix/minor-extensions release:
- add --create-with-all-fields option to changestool to create
.changes files dupload does not choke on. (Closes: 536788)
- add --morguedir option to specify a place where files removed
from the pool are stored. (Closes: 461314)
- fix build-needing not looking at dsc's Architecture field
(Closes: #537770)
- allow specifying source or version easier in formulas (Closes: 468485)
-- Bernhard R. Link <brlink@debian.org> Wed, 15 Jul 2009 11:46:49 +0200
-- Bernhard R. Link <brlink@debian.org> Sat, 25 Jul 2009 16:07:17 +0200
reprepro (3.11.0-1) unstable; urgency=low
......
......@@ -461,6 +461,34 @@ Additionally since reprepro 3.11.0, '\fB%\fP' can be used as comparison operator
denoting matching a name with shell like wildcard
(with '\fB*\fP', '\fB?\fP' and '\fB[\fP..\fB]\fP').
The special field names starting with '\fB$\fP' have special meaning
(available since 3.11.1):
.B $Version
The version of the package, comparison is not alphabetically, but as
Debian version strings.
.B $Source
The source name of the package.
.B $SourceVersion
The source version of the package.
.B $Architecture
The architecture the package is in (listfilter) or to be put into.
.B $Component
The component the package is in (listfilter) or to be put into.
.B $Packagetype
The packagetype of the package.
Examples:
.B reprepro \-b . listfilter test2 'Section (== admin)'
......@@ -473,6 +501,12 @@ no Source field and a Package field blub.
(That means all package generated by a source package \fIblub\fP,
except those also specifying a version number with its Source).
.B reprepro \-b . \-T deb listfilter test2 '$Source (==\fIblub\fP)
is the better way to do this (but only available since 3.11.1).
.B reprepro \-b . listfilter test2 '$PackageType (==deb), $Source (==\fIblub\fP)
is another (less efficient) way.
.B reprepro \-b . listfilter test2 'Package (% linux\-*\-2.6*)'
lists alls packages with names starting with \fBlinux-\fP and later
having an \fB\-2.6\fP.
......
......@@ -55,7 +55,7 @@
#include "checkindsc.h"
#include "checkin.h"
#include "downloadcache.h"
#include "terms.h"
#include "termdecide.h"
#include "tracking.h"
#include "optionsfile.h"
#include "dpkgversions.h"
......@@ -816,10 +816,10 @@ ACTION_D(n, n, y, removesrc) {
return result;
}
static retvalue package_matches_condition(UNUSED(struct database *da), UNUSED(struct distribution *di), UNUSED(struct target *ta), UNUSED(const char *pa), const char *control, void *data) {
static retvalue package_matches_condition(UNUSED(struct database *da), UNUSED(struct distribution *di), struct target *target, UNUSED(const char *pa), const char *control, void *data) {
term *condition = data;
return term_decidechunk(condition, control);
return term_decidechunktarget(condition, control, target);
}
ACTION_D(y, n, y, removefilter) {
......@@ -842,8 +842,7 @@ ACTION_D(y, n, y, removefilter) {
return RET_ERROR;
}
result = term_compile(&condition, argv[2],
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL);
result = term_compilefortargetdecision(&condition, argv[2]);
if( RET_WAS_ERROR(result) )
return result;
......@@ -1184,7 +1183,7 @@ static retvalue listfilterprint(UNUSED(struct database *da), UNUSED(struct distr
if( listmax == 0 )
return RET_NOTHING;
r = term_decidechunk(condition, control);
r = term_decidechunktarget(condition, control, target);
if( RET_IS_OK(r) ) {
if( listskip <= 0 ) {
if( listmax > 0 )
......@@ -1211,8 +1210,7 @@ ACTION_B(y, n, y, listfilter) {
if( RET_WAS_ERROR(r) ) {
return r;
}
result = term_compile(&condition, argv[2],
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL);
result = term_compilefortargetdecision(&condition, argv[2]);
if( RET_WAS_ERROR(result) ) {
return result;
}
......
......@@ -30,7 +30,7 @@
#include "upgradelist.h"
#include "distribution.h"
#include "tracking.h"
#include "terms.h"
#include "termdecide.h"
#include "filterlist.h"
#include "log.h"
#include "configparser.h"
......@@ -646,7 +646,7 @@ retvalue pull_prepare(struct distribution *alldistributions, struct pull_rule *r
* decide what gets pulled *
**************************************************************************/
static upgrade_decision ud_decide_by_rule(void *privdata, const char *package, /*@null@*/const char *old_version, UNUSED(const char *new_version), const char *newcontrolchunk) {
static upgrade_decision ud_decide_by_rule(void *privdata, const struct target *target, const char *package, /*@null@*/const char *old_version, UNUSED(const char *new_version), const char *newcontrolchunk) {
struct pull_rule *rule = privdata;
upgrade_decision decision = UD_UPGRADE;
retvalue r;
......@@ -674,7 +674,8 @@ static upgrade_decision ud_decide_by_rule(void *privdata, const char *package, /
}
if( rule->includecondition != NULL ) {
r = term_decidechunk(rule->includecondition,newcontrolchunk);
r = term_decidechunktarget(rule->includecondition,
newcontrolchunk, target);
if( RET_WAS_ERROR(r) )
return UD_ERROR;
if( r == RET_NOTHING ) {
......
/* This file is part of "reprepro"
* Copyright (C) 2004,2005,2007,2009 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
#include "error.h"
#include "mprintf.h"
#include "strlist.h"
#include "names.h"
#include "chunks.h"
#include "globmatch.h"
#include "dpkgversions.h"
#include "terms.h"
#include "termdecide.h"
static inline bool check_field(enum term_comparison c, const char *value, const char *with) {
if( c == tc_none) {
return true;
} else if( c == tc_globmatch ) {
return globmatch(value, with);
} else if(c == tc_notglobmatch ) {
return !globmatch(value, with);
} else {
int i;
i = strcmp(value, with);
if( i < 0 )
return c == tc_strictless
|| c == tc_lessorequal
|| c == tc_notequal;
else if( i > 0 )
return c == tc_strictmore
|| c == tc_moreorequal
|| c == tc_notequal;
else
return c == tc_lessorequal
|| c == tc_moreorequal
|| c == tc_equal;
}
}
retvalue term_decidechunk(const term *condition, const char *controlchunk, const void *privdata) {
const struct term_atom *atom = condition;
while( atom != NULL ) {
bool correct;char *value;
enum term_comparison c = atom->comparison;
retvalue r;
if( atom->isspecial ) {
correct = atom->special.type->compare(c,
&atom->special.comparewith,
controlchunk, privdata);
} else {
r = chunk_getvalue(controlchunk,
atom->generic.key, &value);
if( RET_WAS_ERROR(r) )
return r;
if( r == RET_NOTHING ) {
correct = ( c == tc_notequal
|| c == tc_notglobmatch);
} else {
correct = check_field(c, value,
atom->generic.comparewith);
free(value);
}
}
if( atom->negated )
correct = !correct;
if( correct ) {
atom = atom->nextiftrue;
} else {
atom = atom->nextiffalse;
if( atom == NULL) {
/* do not include */
return RET_NOTHING;
}
}
}
/* do include */
return RET_OK;
}
static retvalue parsestring(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
if( c == tc_none ) {
fprintf(stderr,
"Error: Special formula predicates (those starting with '$') are always\n"
"defined, thus specifying them without parameter to compare against\n"
"makes not sense!\n");
return RET_ERROR;
}
v->pointer = strndup(value, len);
if( FAILEDTOALLOC(v->pointer) )
return RET_ERROR_OOM;
return RET_OK;
}
// TODO: check for well-formed versions
#define parseversion parsestring
static bool comparesource(enum term_comparison c, const struct compare_with *v, const void *d1, const void *d2) {
const char *control = d1;
const struct target *target = d2;
char *package, *source, *version;
retvalue r;
bool matches;
// TODO: make more efficient
r = chunk_getvalue(control, "Package", &package);
if( !RET_IS_OK(r) )
return false;
r = target->getsourceandversion(control, package, &source, &version);
free(package);
if( !RET_IS_OK(r) )
return false;
free(version);
matches = check_field(c, source, v->pointer);
free(source);
return matches;
}
static inline bool compare_dpkgversions(enum term_comparison c, const char *version, const char *param) {
if( c != tc_globmatch && c != tc_notglobmatch ) {
int cmp;
retvalue r;
r = dpkgversions_cmp(version, param, &cmp);
if( RET_IS_OK(r) ) {
if( cmp < 0 )
return c == tc_strictless
|| c == tc_lessorequal
|| c == tc_notequal;
else if( cmp > 0 )
return c == tc_strictmore
|| c == tc_moreorequal
|| c == tc_notequal;
else
return c == tc_lessorequal
|| c == tc_moreorequal
|| c == tc_equal;
} else
return false;
} else
return check_field(c, version, param);
}
static bool compareversion(enum term_comparison c, const struct compare_with *v, const void *d1, const void *d2) {
const char *control = d1;
const struct target *target = d2;
char *version;
retvalue r;
bool matches;
r = target->getversion(control, &version);
if( !RET_IS_OK(r) )
return false;
matches = compare_dpkgversions(c, version, v->pointer);
free(version);
return matches;
}
static bool comparesourceversion(enum term_comparison c, const struct compare_with *v, const void *d1, const void *d2) {
const char *control = d1;
const struct target *target = d2;
char *package, *source, *version;
retvalue r;
bool matches;
// TODO: make more efficient
r = chunk_getvalue(control, "Package", &package);
if( !RET_IS_OK(r) )
return false;
r = target->getsourceandversion(control, package, &source, &version);
free(package);
if( !RET_IS_OK(r) )
return false;
free(source);
matches = compare_dpkgversions(c, version, v->pointer);
free(version);
return matches;
}
static void freestring(UNUSED(enum term_comparison c), struct compare_with *d) {
free(d->pointer);
}
static void freeatom(enum term_comparison c, struct compare_with *d) {
if( c != tc_equal && c != tc_notequal )
free(d->pointer);
}
static retvalue parsetype(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
if( c == tc_none ) {
fprintf(stderr,
"Error: $Type is always defined, it does not make sense without parameter\n"
"to compare against!\n");
return RET_ERROR;
}
if( c != tc_equal && c != tc_notequal ) {
v->pointer = strndup(value, len);
if( FAILEDTOALLOC(v->pointer) )
return RET_ERROR_OOM;
return RET_OK;
}
v->number = packagetype_find_l(value, len);
if( atom_defined(v->number) )
return RET_OK;
fprintf(stderr, "Unknown package type '%.*s' in formula!\n",
(int)len, value);
return RET_ERROR;
}
static retvalue parsearchitecture(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
if( c == tc_none ) {
fprintf(stderr,
"Error: $Architecture is always defined, it does not make sense without parameter\n"
"to compare against!\n");
return RET_ERROR;
}
if( c != tc_equal && c != tc_notequal ) {
v->pointer = strndup(value, len);
if( FAILEDTOALLOC(v->pointer) )
return RET_ERROR_OOM;
return RET_OK;
}
v->number = architecture_find_l(value, len);
if( atom_defined(v->number) )
return RET_OK;
fprintf(stderr, "Unknown architecture '%.*s' in formula (must be listed in conf/distributions to be known)!\n",
(int)len, value);
return RET_ERROR;
}
static retvalue parsecomponent(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
if( c == tc_none ) {
fprintf(stderr,
"Error: $Component is always defined, it does not make sense without parameter\n"
"to compare against!\n");
return RET_ERROR;
}
if( c != tc_equal && c != tc_notequal ) {
v->pointer = strndup(value, len);
if( FAILEDTOALLOC(v->pointer) )
return RET_ERROR_OOM;
return RET_OK;
}
v->number = component_find_l(value, len);
if( atom_defined(v->number) )
return RET_OK;
fprintf(stderr, "Unknown component '%.*s' in formula (must be listed in conf/distributions to be known)!\n", (int)len, value);
return RET_ERROR;
}
static bool comparetype(enum term_comparison c, const struct compare_with *v, UNUSED(const void *d1), const void *d2) {
const struct target *target = d2;
if( c == tc_equal )
return v->number == target->packagetype_atom;
else if( c == tc_notequal )
return v->number != target->packagetype_atom;
else
return check_field(c,
atoms_packagetypes[target->packagetype_atom],
v->pointer);
}
static bool comparearchitecture(enum term_comparison c, const struct compare_with *v, UNUSED(const void *d1), const void *d2) {
const struct target *target = d2;
if( c == tc_equal )
return v->number == target->architecture_atom;
else if( c == tc_notequal )
return v->number != target->architecture_atom;
else
return check_field(c,
atoms_architectures[target->architecture_atom],
v->pointer);
}
static bool comparecomponent(enum term_comparison c, const struct compare_with *v, UNUSED(const void *d1), const void *d2) {
const struct target *target = d2;
if( c == tc_equal )
return v->number == target->component_atom;
else if( c == tc_notequal )
return v->number != target->component_atom;
else
return check_field(c,
atoms_components[target->component_atom],
v->pointer);
}
static struct term_special targetdecisionspecial[] = {
{"$Source", parsestring, comparesource, freestring},
{"$SourceVersion", parseversion, comparesourceversion, freestring},
{"$Version", parseversion, compareversion, freestring},
{"$Architecture", parsearchitecture, comparearchitecture, freeatom},
{"$Component", parsecomponent, comparecomponent, freeatom},
{"$Type", parsetype, comparetype, freeatom},
{"$PackageType", parsetype, comparetype, freeatom},
{NULL, NULL, NULL, NULL}
};
retvalue term_compilefortargetdecision(term **term_p, const char *formula) {
return term_compile(term_p, formula,
T_GLOBMATCH|T_OR|T_BRACKETS|T_NEGATION|T_VERSION|T_NOTEQUAL,
targetdecisionspecial);
}
retvalue term_decidechunktarget(const term *condition, const char *controlchunk, const struct target *target) {
return term_decidechunk(condition, controlchunk, target);
}
#ifndef REPREPRO_TERMDECIDE_H
#define REPREPRO_TERMDECIDE_H
#ifndef REPREPRO_TERMS_H
#include <terms.h>
#endif
#ifndef REPREPRO_TARGET_H
#include <target.h>
#endif
/* decide based on a chunk, (warning: string comparisons even for version!)*/
retvalue term_decidechunk(const term *, const char *, /*@null@*/const void *);
retvalue term_compilefortargetdecision(/*@out@*/term **, const char *);
retvalue term_decidechunktarget(const term *, const char *, const struct target *);
#endif
/* This file is part of "reprepro"
* Copyright (C) 2004,2005,2007 Bernhard R. Link
* Copyright (C) 2004,2005,2007,2009 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.
......@@ -34,15 +34,23 @@
void term_free(term *t) {
while( t != NULL ) {
struct term_atom *next = t->next;
free(t->key);
free(t->comparewith);
if( t->isspecial ) {
if( t->special.type != NULL &&
t->special.type->done != NULL )
t->special.type->done(t->comparison,
&t->special.comparewith);
} else {
free(t->generic.key);
free(t->generic.comparewith);
}
strlist_done(&t->architectures);
free(t);
t = next;
}
}
static retvalue parseatom(const char **formula,/*@out@*/struct term_atom **atom,int options) {
static retvalue parseatom(const char **formula, /*@out@*/struct term_atom **atom, int options, const struct term_special *specials) {
struct term_atom *a;
const char *f = *formula;
#define overspace() while( *f != '\0' && xisspace(*f) ) f++
......@@ -50,6 +58,7 @@ static retvalue parseatom(const char **formula,/*@out@*/struct term_atom **atom,
const char *valuestart,*valueend;
enum term_comparison comparison = tc_none;
bool negated = false;
const struct term_special *s;
overspace();
......@@ -160,33 +169,50 @@ static retvalue parseatom(const char **formula,/*@out@*/struct term_atom **atom,
//TODO: implement this one...
assert( "Not yet implemented!" == NULL);
}
for( s = specials ; s->name != NULL ; s++ ) {
if( strncasecmp(s->name, keystart, keyend-keystart) == 0 &&
s->name[keyend-keystart] == '\0' )
break;
}
a = calloc(1,sizeof(struct term_atom));
if( a == NULL )
return RET_ERROR_OOM;
a->negated = negated;
a->key = strndup(keystart,keyend-keystart);
if( a->key == NULL ) {
term_free(a);
return RET_ERROR_OOM;
}
a->comparison = comparison;
if( comparison != tc_none ) {
if( valueend - valuestart > 2048 &&
(comparison == tc_globmatch ||
comparison == tc_notglobmatch) ) {
fprintf(stderr, "Ridicilous long globmatch '%.10s...'!\n",
valuestart);
if( s->name != NULL ) {
retvalue r;
a->isspecial = true;
a->special.type = s;
r = s->parse(comparison, valuestart, valueend-valuestart,
&a->special.comparewith);
if( RET_WAS_ERROR(r) ) {
term_free(a);
return RET_ERROR;
return r;
}
a->comparewith = strndup(valuestart,valueend-valuestart);
if( a->comparewith == NULL ) {
} else {
a->isspecial = false;
a->generic.key = strndup(keystart,keyend-keystart);
if( FAILEDTOALLOC(a->generic.key) ) {
term_free(a);
return RET_ERROR_OOM;
}
if( comparison != tc_none ) {
if( valueend - valuestart > 2048 &&
(comparison == tc_globmatch ||
comparison == tc_notglobmatch) ) {
fprintf(stderr, "Ridicilous long globmatch '%.10s...'!\n",
valuestart);
term_free(a);
return RET_ERROR;
}
a->generic.comparewith = strndup(valuestart,valueend-valuestart);
if( a->generic.comparewith == NULL ) {
term_free(a);
return RET_ERROR_OOM;
}
}
}
//TODO: here architectures, too
*atom = a;
......@@ -220,7 +246,7 @@ static void andterm(term *termtochange, /*@dependent@*/term *termtoand) {
}