X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsearch.c;h=a546d6ce808868422091ce528f9e9887ec2a9677;hb=HEAD;hp=9b6ec887cd015f45b88f72e0de32df74d31303a2;hpb=5dd3c3e64a9574112dda77a5afc167f5daa53fd8;p=zpackage diff --git a/src/search.c b/src/search.c index 9b6ec88..a546d6c 100644 --- a/src/search.c +++ b/src/search.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include @@ -28,10 +30,21 @@ struct search_ctl { int matchinstalled; int suppressinstalled; int onlylocalinstalled; + int foundonly; int verbose; int dbrepos; }; +void trace(int level, struct search_ctl *ctl, char *fmt, ...) { + va_list ap; + + if (level <= ctl->verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } +} + char *pathcat(char *dir, char *path) { size_t dirlen = 0, pathlen = 0; char *cat; @@ -61,7 +74,7 @@ char *pathcat(char *dir, char *path) { return cat; } -char *checkfile(char *pkgstr, char *path) { +char *checkfile(char *pkgstr, char *path, int orgreater) { struct zpm pkgfile; char *pkgid = 0; @@ -69,7 +82,11 @@ char *checkfile(char *pkgstr, char *path) { return NULL; } - pkgid = zpm_findpkg(&pkgfile, pkgstr, NULL); + if (orgreater) { + pkgid = zpm_findpkg_range(&pkgfile, pkgstr, 0, 0, 0); + } else { + pkgid = zpm_findpkg(&pkgfile, pkgstr, NULL); + } zpm_close(&pkgfile); return pkgid; @@ -145,6 +162,9 @@ int find_globs(struct search_ctl *opt) { return 1; } +/* + * find a package and packagefile that supplies a library + */ int find_lib(char *soname, struct search_ctl *opt, struct pkgloc *pkg) { char *latest = 0; char *installed = 0, *found = 0; @@ -192,6 +212,69 @@ int find_lib(char *soname, struct search_ctl *opt, struct pkgloc *pkg) { return 0; } +struct pkgloc *find_atleast_package(char *pkgstr, struct search_ctl *opt, int stopifinstalled) { + char *latest = 0; + char *installed = 0, *found = 0; + char *pkgfile = 0; + struct pkgloc *pkg = 0; + int rv; + unsigned int i; + + if (opt->localdb) { + installed = zpm_findpkg_range(opt->zpmdb, pkgstr, 0, "status = 'installed'", 0); + if (installed) { + latest = installed; + pkgfile = opt->zpmdb->path; + if (stopifinstalled) { + pkg = malloc(sizeof *pkg); + pkg->id = strdup(latest); + pkg->file = pkgfile; + pkg->installed = 1; + return pkg; + } + } + if (!opt->onlylocalinstalled) { + found = zpm_findpkg_range(opt->zpmdb, pkgstr, 0, NULL, 0); + if (found) { + rv = zpm_vercmp(found, latest); + if (rv == 1) { + latest = found; + pkgfile = opt->zpmdb->path; + } + } + } + } + + for (i = 0; i < opt->repos.gl_pathc; i++) { + if (!opt->matchallpkgfile + && !strstr(opt->repos.gl_pathv[i], pkgstr) + && !strstr(opt->repos.gl_pathv[i], ".repo") + ) { + continue; + } + found = checkfile(pkgstr, opt->repos.gl_pathv[i], 1); + if (found) { + rv = zpm_vercmp(found, latest); + if (rv == 1) { + latest = found; + pkgfile = strdup(opt->repos.gl_pathv[i]); + } + } + } + + if (latest && pkgfile) { + pkg = malloc(sizeof *pkg); + pkg->id = strdup(latest); + pkg->file = pkgfile; + pkg->installed = 0; + if (installed) { + pkg->installed = !strcmp(latest, installed); + } + } + + return pkg; +} + struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) { char *latest = 0; char *installed = 0, *found = 0; @@ -201,14 +284,19 @@ struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) { unsigned int i; if (opt->localdb) { + trace(1, opt, "checking local database for installed %s\n", pkgstr); installed = zpm_findpkg(opt->zpmdb, pkgstr, "status = 'installed'"); if (installed) { + trace(1, opt, "found installed %s as %s\n", pkgstr, installed); latest = installed; pkgfile = opt->zpmdb->path; } + if (!opt->onlylocalinstalled) { + trace(1, opt, "checking local database for any %s\n", pkgstr); found = zpm_findpkg(opt->zpmdb, pkgstr, NULL); if (found) { + trace(1, opt, "found %s as %s\n", pkgstr, installed); rv = zpm_vercmp(found, latest); if (rv == 1) { latest = found; @@ -224,20 +312,26 @@ struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) { #endif } + trace(1, opt, "checking repositories\n"); for (i = 0; i < opt->repos.gl_pathc; i++) { + trace(1, opt, "checking repo/pkg %s\n", opt->repos.gl_pathv[i]); if (!opt->matchallpkgfile && !strstr(opt->repos.gl_pathv[i], pkgstr) && !strstr(opt->repos.gl_pathv[i], ".repo") ) { + trace(1, opt, "skipping repo/pkg %s\n", opt->repos.gl_pathv[i]); continue; } - found = checkfile(pkgstr, opt->repos.gl_pathv[i]); + found = checkfile(pkgstr, opt->repos.gl_pathv[i], 0); + trace(1, opt, "found %s\n", found); if (found) { + trace(1, opt, "comparing found %s to latest (%s)\n", found, latest); rv = zpm_vercmp(found, latest); if (rv == 1) { latest = found; pkgfile = strdup(opt->repos.gl_pathv[i]); } + trace(1, opt, "latest %s\n", latest); } } @@ -249,6 +343,7 @@ struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) { if (installed) { pkg->installed = !strcmp(latest, installed); } + trace(1, opt, "set up pkgloc = {%s, %s, %d}\n", pkg->id, pkg->file, pkg->installed); } return pkg; @@ -271,6 +366,8 @@ with pkglibs as (\ where PL.pkgid = %Q\ "; +char *pkgdeps = "select requires from packagedeps_pkgid where pkgid = %Q"; + static int afind_strcmp(const void *a, const void *b) { return strcmp(a, b); } @@ -282,13 +379,13 @@ void checklibs(struct search_ctl *opts, /* checked_libs is a list of checked sonames * checked is a list of checked packages - * needed is list of libs for package + * needed is list of libs for package, or list of package deps */ jsw_atree_t *needed = 0, *checked, *checked_libs; - int libs; + int libs, count; jsw_atrav_t *i; - char *soname; + char *soname, *package; checked = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); checked_libs = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); @@ -327,14 +424,45 @@ void checklibs(struct search_ctl *opts, exit(EXIT_FAILURE); } - /* get the libraries needed by this package */ + /* get the libraries and packages needed by this package */ if (!zpm_open(&src, pkgfile)) { fprintf(stderr, "can't zpm open %s\n", pkgfile); break; } - if (needed) jsw_adelete(needed); - needed = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); + jsw_adelete(needed); + needed = jsw_anew_str(); + count = zpm_packages_needed(&src, pkgid, needed); + if (count) { + struct pkgloc *pkg = 0; + i = jsw_atnew(); + + if (pkg) { + free(pkg->file); + free(pkg->id); + free(pkg); + } + + for (package = jsw_atfirst(i, needed); package; package = jsw_atnext(i)) { + pkg = find_atleast_package(package, opts, 1); + if (!pkg || pkg->installed) { + continue; + } + /* look for a package at least that version */ + /* if package is installed, or already + * handled, skip. Otherwise, add it + * to the list of installed + */ + } + if (pkg) { + free(pkg->file); + free(pkg->id); + free(pkg); + } + } + + jsw_adelete(needed); + needed = jsw_anew_str(); libs = zpm_libraries_needed(&src, pkgid, needed); zpm_close(&src); @@ -348,7 +476,8 @@ void checklibs(struct search_ctl *opts, int found; struct pkgloc pkginfo; - /* if it's in checked_libs, we've already looked at this one */ + /* if it's in checked_libs, we've already looked at + * this one */ if (jsw_afind(checked_libs, soname)) { if (opts->verbose > 1) { fprintf(stderr, "already checked %s\n", soname); @@ -389,19 +518,39 @@ void checklibs(struct search_ctl *opts, free(pkgfile); } -void print_pkghash(jsw_hash_t *hash, int json) { +void print_pkghash(jsw_hash_t *hash, int json, int idonly) { const char *pkgid, *file; char *fmt; - char *sep; + char *sep = "\n"; int count = 0; - - fmt = json ? "\"%s\": \"%s\"" : "%s:%s"; - sep = json ? ", " : "\n"; + char *start = ""; + char *end = ""; if (json) { - printf("{ "); + sep = ", "; + if (idonly) { + fmt = "\"%s\""; + start = "[ "; + end = " ]\n"; + } else { + fmt = "\"%s\": \"%s\""; + start = "{ "; + end = " }\n"; + } + } else { + if (idonly) { + fmt = "%s"; + start = ""; + end = ""; + } else { + fmt = "%s:%s"; + start = ""; + end = ""; + } } + printf("%s", start); + if (jsw_hsize(hash) > 0) { for (jsw_hreset(hash); jsw_hitem(hash); jsw_hnext(hash)) { pkgid = jsw_hkey(hash); @@ -409,16 +558,20 @@ void print_pkghash(jsw_hash_t *hash, int json) { if (count++) { printf("%s", sep); } - printf(fmt, pkgid, file); + if (idonly) { + printf(fmt, pkgid); + } else { + printf(fmt, pkgid, file); + } } + if (!json) printf("\n"); } - if (json) printf(" }"); - printf("\n"); + printf("%s", end); } int main(int ac, char *av[]) { - int option, argn; - int findlibs = 0, json = 0; + int option, argn, rv = 0; + int findlibs = 0, json = 0, idonly = 0; struct pkgloc *found; jsw_hash_t *packages, *check, *forlibs, *nolib; jsw_atree_t *nfound; @@ -434,7 +587,6 @@ int main(int ac, char *av[]) { opt.repodir = getenv("ZPM_REPO_DIR"); if (!opt.repodir) opt.repodir = "/var/lib/zpm/repo"; - /* -l also find packages needed for libs * -j output json * -q quiet - suppress output @@ -462,7 +614,7 @@ int main(int ac, char *av[]) { */ int output = 1; - while ((option = getopt(ac, av, "ljqPRDvp:r:d:MiIO")) != -1) { + while ((option = getopt(ac, av, "fljqPRDvp:r:d:MiIOn")) != -1) { switch (option) { case 'l': findlibs = 1; break; case 'j': json = 1; break; @@ -472,6 +624,7 @@ int main(int ac, char *av[]) { case 'I': opt.suppressinstalled = 1; break; /* only find localdb pkgs if installed */ case 'O': opt.onlylocalinstalled = 1; break; + case 'f': opt.foundonly = 1; break; case 'd': opt.localdb = optarg; break; case 'p': opt.pkgdir = optarg; break; case 'r': opt.repodir = optarg; break; @@ -484,6 +637,7 @@ int main(int ac, char *av[]) { */ case 'M': opt.matchallpkgfile = 1; break; case 'v': opt.verbose++; break; + case 'n': idonly = 1; break; default: exit(EXIT_FAILURE); break; @@ -559,10 +713,10 @@ int main(int ac, char *av[]) { if (output) { if (jsw_hsize(packages)) { - print_pkghash(packages, json); + print_pkghash(packages, json, idonly); } if (jsw_hsize(forlibs)) { - print_pkghash(forlibs, json); + print_pkghash(forlibs, json, idonly); } } @@ -573,9 +727,10 @@ int main(int ac, char *av[]) { file = jsw_hitem(nolib); fprintf(stderr, "no lib found %s:%s\n", pkgid, file); } + rv = 1; } - if (jsw_asize(nfound) > 0) { + if (jsw_asize(nfound) > 0 && !opt.foundonly) { jsw_atrav_t *i; i = jsw_atnew(); char *pkgstr; @@ -583,7 +738,8 @@ int main(int ac, char *av[]) { for (pkgstr = jsw_atfirst(i, nfound); pkgstr; pkgstr = jsw_atnext(i)) { fprintf(stderr, "%s: not found\n", pkgstr); } + rv = 1; } - return jsw_asize(nfound) > 0 || jsw_hsize(nolib) > 0 ? 1 : 0; + return rv; }