/* test.c - Alpine Package Keeper (APK) * * Copyright (C) 2011 Timo Teräs * All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. See http://www.gnu.org/ for details. */ #include #include #include "apk_applet.h" #include "apk_database.h" #include "apk_solver.h" #include "apk_io.h" #include "apk_print.h" struct test_ctx { const char *installed_db; struct apk_string_array *repos; }; static int test_parse(void *pctx, struct apk_db_options *dbopts, int optch, int optindex, const char *optarg) { struct test_ctx *ctx = (struct test_ctx *) pctx; switch (optch) { case 0x10000: ctx->installed_db = optarg; break; case 0x10001: if (ctx->repos == NULL) apk_string_array_init(&ctx->repos); *apk_string_array_add(&ctx->repos) = (char*) optarg; break; case 'u': apk_flags |= APK_UPGRADE; break; case 'a': apk_flags |= APK_PREFER_AVAILABLE; break; default: return -1; } return 0; } static inline void print_change(struct apk_package *oldpkg, struct apk_package *newpkg) { const char *msg = NULL; struct apk_name *name; int r; if (oldpkg != NULL) name = oldpkg->name; else name = newpkg->name; if (oldpkg == NULL) { apk_message("Installing %s (" BLOB_FMT ")", name->name, BLOB_PRINTF(*newpkg->version)); } else if (newpkg == NULL) { apk_message("Purging %s (" BLOB_FMT ")", name->name, BLOB_PRINTF(*oldpkg->version)); } else { r = apk_pkg_version_compare(newpkg, oldpkg); switch (r) { case APK_VERSION_LESS: msg = "Downgrading"; break; case APK_VERSION_EQUAL: if (newpkg == oldpkg) msg = "Re-installing"; else msg = "Replacing"; break; case APK_VERSION_GREATER: msg = "Upgrading"; break; } apk_message("%s %s (" BLOB_FMT " -> " BLOB_FMT ")", msg, name->name, BLOB_PRINTF(*oldpkg->version), BLOB_PRINTF(*newpkg->version)); } } static int test_main(void *pctx, struct apk_database *db, int argc, char **argv) { struct test_ctx *ctx = (struct test_ctx *) pctx; struct apk_bstream *bs; struct apk_package_array *solution = NULL; struct apk_changeset changeset; int i; if (argc != 1) return -EINVAL; /* load installed db */ if (ctx->installed_db != NULL) { bs = apk_bstream_from_file(AT_FDCWD, ctx->installed_db); if (bs != NULL) { apk_db_index_read(db, bs, -1); bs->close(bs, NULL); } } /* load additional indexes */ if (ctx->repos) { for (i = 0; i < ctx->repos->num; i++) { bs = apk_bstream_from_file(AT_FDCWD, ctx->repos->item[i]); if (bs != NULL) { apk_db_index_read(db, bs, i); bs->close(bs, NULL); } } } /* construct new world */ apk_deps_parse(db, &db->world, APK_BLOB_STR(argv[0])); /* run solver */ apk_solver_sort(db); if (apk_solver_solve(db, db->world, &solution) != 0) return 1; memset(&changeset, 0, sizeof(changeset)); if (apk_solver_generate_changeset(db, solution, &changeset) == 0) { /* dump changeset */ for (i = 0; i < changeset.changes->num; i++) { struct apk_change *c = &changeset.changes->item[i]; print_change(c->oldpkg, c->newpkg); } } return 0; } static struct apk_option test_options[] = { { 0x10000, "installed", "Installed database", required_argument, "DB" }, { 0x10001, "raw-repository", "Add unsigned test repository index", required_argument, "INDEX" }, { 'u', "upgrade", "Prefer to upgrade package" }, { 'a', "available", "Re-install or downgrade if currently installed package is not " "currently available from any repository" }, }; static struct apk_applet test_applet = { .name = "test", .help = "Test dependency graph solver (uses simple repository and installed db)", .arguments = "'WORLD'", .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS, .context_size = sizeof(struct test_ctx), .num_options = ARRAY_SIZE(test_options), .options = test_options, .parse = test_parse, .main = test_main, }; APK_DEFINE_APPLET(test_applet);