/* * qpkg.c - Quick package database query * * Written 2010 by Werner Almesberger * Copyright 2010 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include "jrb.h" #include "id.h" #include "prereq.h" #include "gobble.h" #include "fixup.h" #include "pkg.h" #include "qpkg.h" struct tree *packages = NULL; struct tree *versions = NULL; int debug = 0; static void list_all_packages(void) { const struct jrb *n; const struct pkg *pkg; for (n = jrb_first(packages->root); n != jrb_nil(packages->root); n = jrb_next(n)) { const struct id *id = n->key; for (pkg = n->val; pkg; pkg = pkg->more) { printf("%.*s", ID2PF(id)); if (!pkg) printf(" (virtual)"); else { if (pkg->version) printf(" (%.*s)", ID2PF(pkg->version)); if (pkg->more) printf(" +++"); } printf("\n"); } } } static void list_one_package(const char *name) { const struct jrb *n = find_id(packages, name, strlen(name)); const struct pkg *pkg; if (!n) { fprintf(stderr, "no such package \"%s\"\n", name); exit(1); } for (pkg = n->val; pkg; pkg = pkg->more) printf("%.*s\n", ID2PF(pkg->version)); } static void find_prereq(const char *name, const char *version) { const struct jrb *n = find_id(packages, name, strlen(name)); struct pkg *pkg; struct pkg **pkgs; if (!n) { fprintf(stderr, "no such package \"%s\"\n", name); exit(1); } pkg = n->val; if (!pkg) { fprintf(stderr, "package %s is a ghost\n", name); exit(1); } if (version) { n = find_id(versions, version, strlen(version)); if (!n) { fprintf(stderr, "no such version\"%s\"\n", version); exit(1); } while (pkg && pkg->version != n->key) pkg = pkg->more; if (pkg) { fprintf(stderr, "no %s version\"%s\" found\n", name, version); exit(1); } } pkgs = prereq(pkg); if (!pkgs) { fprintf(stderr, "can't resolve %s%s%s\n", name, version ? " version " : "", version ? version : ""); exit(1); } while (*pkgs) { const char *file = (*pkgs)->filename; const char *end; assert(file); end = strchr(file, '\n'); printf("%.*s\n", (int) (end-file), file); pkgs++; } } static void do_fixups(void) { sort_versions(); complete_provisions(); } static void usage(const char *name) { fprintf(stderr, "usage: %s options [pkg-list ...] list [pkg]\n" " %s options [pkg-list ...] prereq pkg [version]\n\n" " -d enable debugging output\n" , name, name); exit(1); } int main(int argc, char **argv) { int arg; packages = make_tree(comp_id); versions = make_tree(comp_id); if (argc == 1) usage(*argv); for (arg = 1; arg != argc; arg++) { if (!strcmp(argv[arg], "-d")) { debug = 1; continue; } if (*argv[arg] == '-') usage(*argv); if (!strcmp(argv[arg], "list")) { do_fixups(); switch (argc-arg) { case 1: list_all_packages(); return 0; case 2: list_one_package(argv[arg+1]); return 0; default: usage(*argv); } } else if (!strcmp(argv[arg], "prereq")) { do_fixups(); switch (argc-arg) { case 2: find_prereq(argv[arg+1], NULL); return 0; case 3: find_prereq(argv[arg+1], argv[arg+2]); return 0; default: usage(*argv); } } else { gobble(argv[arg]); } } return 0; }