wernermisc/qpkg/qpkg.c

186 lines
3.5 KiB
C

/*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#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;
}