]> pd.if.org Git - zpackage/blobdiff - src/search.c
add tracing to zpm-search
[zpackage] / src / search.c
index 9b6ec887cd015f45b88f72e0de32df74d31303a2..a546d6ce808868422091ce528f9e9887ec2a9677 100644 (file)
@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
 
 #include <glob.h>
 
@@ -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;
 }