X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=lib%2Ffindpkg.c;h=8dd0ad14b1a4b7f83b96af8410eaaf9ac54ff79b;hb=b6f9b692cd319ffbe43fbd191b13613532d82e37;hp=a8d8ff49f791b7010be411f537a2e171b26f8380;hpb=fc72c51a467305eb7b8f1154465ae63c22477f5c;p=zpackage diff --git a/lib/findpkg.c b/lib/findpkg.c index a8d8ff4..8dd0ad1 100644 --- a/lib/findpkg.c +++ b/lib/findpkg.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -6,60 +8,9 @@ #include "zpm.h" #include "sqlite3.h" +#include "lib/jsw/jsw_atree.h" -int zpm_parse_package(char *pstr, char *name, char *ver, int *rel) { - if (name) *name = 0; - if (ver) *ver = 0; - if (rel) *rel = 0; - int havename = 0; - int havever = 0; - int haverel = 0; - - /* 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++; - havename = 1; - } - if (name) *name = 0; - if (*pstr == '-') { - pstr++; - } - while (*pstr && *pstr != '-') { - if (ver) { - *ver++ = *pstr; - } - pstr++; - havever = 1; - } - if (ver) *ver = 0; - if (*pstr == '-') { - pstr++; - } - /* TODO use strtol */ - if (rel && *pstr) { - haverel = 1; - *rel = atoi(pstr); - } - - return havename + havever + haverel; -} +#define DMARK fprintf(stderr, "mark %s %s:%d\n", __FILE__, __func__, __LINE__) /* * flags 0 = find installed @@ -81,27 +32,126 @@ struct zpm_package *zpm_package_alloc(struct zpm *zpm) { void zpm_sqlite_error(struct zpm *zpm) { zpm->error = 1; if (zpm->errmsg) free(zpm->errmsg); - zpm->errmsg = zpm_strdup((char *)sqlite3_errmsg(zpm->db)); + zpm->errmsg = strdup((const char *)sqlite3_errmsg(zpm->db)); } -char *zpm_findpkg(struct zpm *zpm, char *pkgstr) { +char *zpm_findlib(struct zpm *zpm, char *soname, char *where) { + sqlite3_str *sql; + char *query, *pkgid = 0; + +char *select = "select printf('%%s-%%s-%%s',P.package,P.version,P.release) as pkgid, P.package, P.version, P.release\ + from packagefiles PF\ + join elflibraries EL on EL.file = PF.hash\ + join packages P on P.package = PF.package and P.version = PF.version and P.release = PF.release"; + char *order = "order by P.package, P.version, cast(P.release as integer)"; + + /* null pkgstr find "best" package + * best is shortest complete package if any are complete + * shortest incomplete if any are incomplete + * where more than one version is in those sets, best is + * latest as determined by vercmp + */ + + sql = sqlite3_str_new(zpm->db); + + sqlite3_str_appendall(sql, select); + sqlite3_str_appendf(sql, " where P.hash is not null and EL.soname = %Q", soname); + + if (where) { + sqlite3_str_appendall(sql, " and "); + sqlite3_str_appendall(sql, where); + } + + sqlite3_str_appendall(sql, " "); + sqlite3_str_appendall(sql, order); + sqlite3_str_appendall(sql, " limit 1;"); + + if (sqlite3_str_errcode(sql)) { + zpm->error = 1; + sqlite3_free(sqlite3_str_finish(sql)); + return 0; + } + + query = sqlite3_str_finish(sql); + + pkgid = zpm_db_string(zpm, query);; + + sqlite3_free(query); + + return pkgid; +} + +int zpm_packages_needed(struct zpm *zpm, char *pkgid, jsw_atree_t *list) { + char *pkglibsneeded = "select soname, selfsatisfied from package_libraries_needed where pkgid = %Q"; + sqlite3_stmt *st; + int count = 0; + int rv; + + st = zpm_dbquery(zpm, pkglibsneeded, pkgid); + + while ((rv = sqlite3_step(st)) == SQLITE_ROW) { + char *soname; + int self; + + soname = (char *)sqlite3_column_text(st, 0); + /* TODO check and skip self sats */ + self = sqlite3_column_int(st,1); + if (self) { + continue; + } + count++; + + /* if it's in needed, we've already looked at this one */ + if (list && !jsw_afind(list, soname)) { + jsw_ainsert(list, soname); + } + } + + sqlite3_finalize(st); + return count; +} + + +int zpm_libraries_needed(struct zpm *zpm, char *pkgid, jsw_atree_t *list) { + char *pkglibsneeded = "select soname, selfsatisfied from package_libraries_needed where pkgid = %Q"; + sqlite3_stmt *st; + int count = 0; + int rv; + + st = zpm_dbquery(zpm, pkglibsneeded, pkgid); + + while ((rv = sqlite3_step(st)) == SQLITE_ROW) { + char *soname; + int self; + + soname = (char *)sqlite3_column_text(st, 0); + /* TODO check and skip self sats */ + self = sqlite3_column_int(st,1); + if (self) { + continue; + } + count++; + + /* if it's in needed, we've already looked at this one */ + if (list && !jsw_afind(list, soname)) { + jsw_ainsert(list, soname); + } + } + + sqlite3_finalize(st); + return count; +} + +char *zpm_findpkg(struct zpm *zpm, char *pkgstr, char *where) { char *select = "select pkgid, package, version, release from packages_pkgid"; - char *group = "group by package having max( version||'-'||release collate vercmp) order by length(package), package, version||'-'||release collate vercmp limit 1"; #if 0 - char *sstr[] = { - "status = 'installed'", - "", - "status != 'installed'" - }; + char *group = "group by package having max( version||'-'||release collate vercmp) order by length(package), package, version||'-'||release collate vercmp"; +#else + char *group = "order by package, version collate vercmp desc, cast(release as integer)"; + //group = "order by package, version , cast(release as integer)"; #endif - -// char *order = "order by package, version collate vercmp, cast(release as integer)"; sqlite3_str *sql; - sqlite3_stmt *stmt; - char *query; - char package[32]; - char version[32]; - int release; + char *query, *pkgid = 0; /* null pkgstr find "best" package * best is shortest complete package if any are complete @@ -110,29 +160,110 @@ char *zpm_findpkg(struct zpm *zpm, char *pkgstr) { * latest as determined by vercmp */ - /* given a package name, get the packages */ - /* no package name, get all */ + sql = sqlite3_str_new(zpm->db); + + sqlite3_str_appendall(sql, select); + sqlite3_str_appendall(sql, " where true"); + + if (pkgstr) { + int release; + char version[32]; + char package[32]; + + zpm_parse_package(pkgstr, package, version, &release); + if (*package != 0) { + sqlite3_str_appendf(sql, " and package = %Q", + package); + } + if (*version != 0) { + sqlite3_str_appendf(sql, " and version = %Q", + version); + } + if (release != 0) { + sqlite3_str_appendf(sql, " and release = %d", + release); + } + } + + if (where) { + sqlite3_str_appendall(sql, " and "); + sqlite3_str_appendall(sql, where); + } + + + sqlite3_str_appendall(sql, " "); + sqlite3_str_appendall(sql, group); + sqlite3_str_appendall(sql, " limit 1;"); + + if (sqlite3_str_errcode(sql)) { + zpm->error = 1; + sqlite3_free(sqlite3_str_finish(sql)); + return 0; + } + + query = sqlite3_str_finish(sql); + + pkgid = zpm_db_string(zpm, query);; - // char where[1024] = ""; + sqlite3_free(query); - zpm_parse_package(pkgstr, package, version, &release); + return pkgid; +} - /* install a collation function */ - zpm_addvercmp(zpm); +char *zpm_findpkg_range(struct zpm *zpm, char *minpkg, char *maxpkg, char *where, int wantleast) { + int release; + char version[32]; + char package[32]; - /* TODO allow more args to nail down version and release */ + char *select = "select pkgid, package, version, release from packages_pkgid"; + char *last = "order by version collate vercmp desc, cast(release as integer) desc"; + char *first = "order by version collate vercmp, cast(release as integer)"; + char *group; + + char *query, *pkgid = 0; + sqlite3_str *sql; + + group = wantleast ? first : last; + /* null pkgstr find "best" package + * best is shortest complete package if any are complete + * shortest incomplete if any are incomplete + * where more than one version is in those sets, best is + * latest as determined by vercmp + */ sql = sqlite3_str_new(zpm->db); + sqlite3_str_appendall(sql, select); - sqlite3_str_appendf(sql, " where package = %q", package); - if (*version) { - sqlite3_str_appendf(sql, " and version = %q", version); + sqlite3_str_appendall(sql, " where true"); + + if (minpkg) { + sqlite3_str_appendf(sql, " and pkgid >= %Q collate vercmp", + minpkg); + zpm_parse_package(minpkg, package, version, &release); + if (*package != 0) { + sqlite3_str_appendf(sql, " and package = %Q", + package); + } + } + + if (maxpkg) { + sqlite3_str_appendf(sql, " and pkgid <= %Q collate vercmp", + maxpkg); + zpm_parse_package(maxpkg, package, version, &release); + if (*package != 0) { + sqlite3_str_appendf(sql, " and package = %Q", + package); + } } - if (release) { - sqlite3_str_appendf(sql, " and release = %d", release); + + if (where) { + sqlite3_str_appendall(sql, " and "); + sqlite3_str_appendall(sql, where); } - sqlite3_str_appendf(sql, " %s", group); - sqlite3_str_appendf(sql, " limit 1"); + + sqlite3_str_appendall(sql, " "); + sqlite3_str_appendall(sql, group); + sqlite3_str_appendall(sql, " limit 1;"); if (sqlite3_str_errcode(sql)) { zpm->error = 1; @@ -141,24 +272,10 @@ char *zpm_findpkg(struct zpm *zpm, char *pkgstr) { } query = sqlite3_str_finish(sql); - sqlite3_prepare_v2(zpm->db, query, strlen(query), &stmt, NULL); - sqlite3_free(query); - free(zpm->pkgid); - zpm->pkgid = 0; - - switch (sqlite3_step(stmt)) { - case SQLITE_ROW: - zpm->pkgid = zpm_strdup((char *)sqlite3_column_text(stmt, 0)); - break; - case SQLITE_DONE: - /* not found */ - break; - default: - zpm_sqlite_error(zpm); - break; - } - sqlite3_finalize(stmt); + pkgid = zpm_db_string(zpm, query);; + + sqlite3_free(query); - return zpm->pkgid; + return pkgid; }