X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-findpkg.c;h=3fd608c56327f5ed1653fb6fbbbef31811b18c79;hb=fc0e2fbaf7051e42be1a6449a5a004fb3e665d45;hp=b7cb3fdb9272241af642003ad945d28b7632bc0c;hpb=84f276b21e57aa8fe1e16d01e75fee1097d5daf8;p=zpackage diff --git a/zpm-findpkg.c b/zpm-findpkg.c index b7cb3fd..3fd608c 100644 --- a/zpm-findpkg.c +++ b/zpm-findpkg.c @@ -1,7 +1,18 @@ +#define _POSIX_C_SOURCE 2 + #include #include +#include +#include + #include "zpm.h" +static int found = 0; + +void usage(void) { + fprintf(stderr, "zpm-findpkg [-I] [-s ...] [-S ] [package]\n"); +} + static int prow(void *f, int ncols, char **vals, char **cols) { FILE *out = f; int i; @@ -14,50 +25,156 @@ static int prow(void *f, int ncols, char **vals, char **cols) { fprintf(out, "%s", vals[i]); } fprintf(out, "\n"); + found++; return 0; } +void parse_package(char *pstr, char *name, char *ver, int *rel) { + if (name) *name = 0; + if (ver) *ver = 0; + if (rel) *rel = -1; + + /* string - ver - rel */ + /* rel is all digits */ + /* possible forms: + * ^(.+)-([0-9][^-]*)-([\d+])$ + * ^(.+)-([0-9][^-]*)$ + * ^(.+)$ + * The main problem in parsing is that the package name itself + * can contain a '-', so you can't just split on '-' + * Also, the version can be just digits. + */ + + /* everything up to the first '-' is in the name */ + while (*pstr) { + if (*pstr == '-' && isdigit(*(pstr+1))) { + break; + } + if (name) { + *name++ = *pstr; + } + pstr++; + } + if (name) *name = 0; + if (*pstr == '-') { + pstr++; + } + while (*pstr && *pstr != '-') { + if (ver) { + *ver++ = *pstr; + } + pstr++; + } + if (ver) *ver = 0; + if (*pstr == '-') { + pstr++; + } + if (rel && *pstr) { + *rel = atoi(pstr); + } +} + int main(int ac, char **av){ + int opt; struct zpm pkg; + char *dbfile, *pkgstr; char *select = "select package, version, release, package||'-'||version||'-'||release as pkgid from packages"; char *group = "group by package having max( version||'-'||release collate vercmp) order by length(package), package, version||'-'||release collate vercmp"; -// char *select = "select package, version, release, package||'-'||version||'-'||release as pkgid from packages"; -// char *order = "order by package, version collate vercmp, cast(release as integer)"; - char sql[2048]; + char *sql; + sqlite3_str *include; + sqlite3_str *exclude; + sqlite3_str *query; - if (ac < 2) { - fprintf(stderr, "usage: db path\n"); - return 1; + dbfile = getenv("ZPMDB"); + + query = sqlite3_str_new(NULL); + include = sqlite3_str_new(NULL); + exclude = sqlite3_str_new(NULL); + + while ((opt = getopt(ac, av, "f:s:S:I")) != -1) { + switch (opt) { + case 'f': dbfile = optarg; break; + case 's': sqlite3_str_appendf(include,",%Q", optarg); + break; + case 'S': sqlite3_str_appendf(exclude,",%Q", optarg); + break; + case 'I': sqlite3_str_appendall(include,",'installed'"); + break; + default: + usage(); + exit(EXIT_FAILURE); + break; + } } + int argn = optind; - /* this is really just read env */ - zpm_readopts(&pkg, ac, av); + if (!dbfile) { + fprintf(stderr, "must specify db\n"); + return 1; + } /* given a package name, get the packages */ /* no package name, get all */ - if (zpm_open(&pkg, av[1])) { +#ifdef DEBUG + fprintf(stderr, "opening db %s\n", dbfile); +#endif + + if (zpm_open(&pkg, dbfile)) { char *errmsg; -// char where[1024] = ""; + char *excludes, *includes; - /* TODO allow more args to nail down version and release */ - if (ac >= 3) { - sprintf(sql, "%s where package = '%s' %s;", - select, av[2], group); - } else { - sprintf(sql, "%s %s;", select, group); + excludes = sqlite3_str_value(exclude); + includes = sqlite3_str_value(include); + + sqlite3_str_appendall(query, " "); + sqlite3_str_appendall(query, select); + sqlite3_str_appendall(query, " where true"); + + if (includes) { + sqlite3_str_appendf(query, " and status in (%s)", includes+1); + } + if (excludes) { + sqlite3_str_appendf(query, " and status not in (%s)", excludes+1); + } + + if (ac >= argn) { + int release; + char version[32]; + char package[32]; + + pkgstr = av[argn]; + + parse_package(pkgstr, package, version, &release); + if (*package != 0) { + sqlite3_str_appendf(query, " and package = %Q", + package); + } + if (*version != 0) { + sqlite3_str_appendf(query, " and version = %Q", + version); + } + if (release != -1) { + sqlite3_str_appendf(query, " and release = %d", + release); + } } - /* install a collation function */ - zpm_addvercmp(&pkg); - /* sqlite seems to need the columns in the result to - * do the sort right */ -// zpm_exec(&pkg, "select package, version, release, package||'-'||version||'-'||release as pkgid from packages order by package, version collate vercmp, cast(release as integer)", prow, stdout, &errmsg); -// fprintf(stdout, "\n"); + sqlite3_str_appendall(query, " "); + sqlite3_str_appendall(query, group); + sqlite3_str_appendall(query, ";"); - zpm_exec(&pkg, sql, prow, stdout, &errmsg); + sql = sqlite3_str_value(query); + if (sql) { +#ifdef DEBUG + fprintf(stderr, "q: %s\n", sql); +#endif + zpm_exec(&pkg, sql, prow, stdout, &errmsg); + } else { + fprintf(stderr, "unable to form database query\n"); + } } zpm_close(&pkg); - return 0; + return found ? 0 : 1; }