diff options
author | Timo Teräs <timo.teras@iki.fi> | 2011-07-26 16:56:55 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2011-07-26 17:08:43 +0300 |
commit | 79b53d4d76bbbb4235eaf709a6f07247f47316de (patch) | |
tree | 295502ba11139d40fd1621d653b3ac43753590a9 /src/test.c | |
parent | 169cb3a97e2ef61b2087278484c8934e0d62cf3d (diff) | |
download | apk-tools-79b53d4d76bbbb4235eaf709a6f07247f47316de.tar.gz apk-tools-79b53d4d76bbbb4235eaf709a6f07247f47316de.tar.bz2 apk-tools-79b53d4d76bbbb4235eaf709a6f07247f47316de.tar.xz apk-tools-79b53d4d76bbbb4235eaf709a6f07247f47316de.zip |
solver: new package selection logic (which is not yet used)
* basic code for a backtracking, forward checking dependency satisfier
* works better when there are tricky dependencies to solve
(when can't just upgrade everything to most preferred versions)
* the new code always evaluates all of 'world' constraints
(old code just does incremental updates based on heuristics)
* is probably somewhat slower than old code (probably unnoticeable
difference in most cases)
* makes easier to write support for provides and repository pinning
* test applet and a bunch of test cases added which uses the new code
* from the old feature set install_if is not yet implemented
Diffstat (limited to 'src/test.c')
-rw-r--r-- | src/test.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..b074de8 --- /dev/null +++ b/src/test.c @@ -0,0 +1,163 @@ +/* test.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2011 Timo Teräs <timo.teras@iki.fi> + * 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 <errno.h> +#include <fcntl.h> +#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); + 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]); + 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); |