Commit a5a70216 authored by Timo Teräs's avatar Timo Teräs

applets: start using solver code

still todo:
  - 'fix' is missing
  - 'del -R' does not work
  - 'upgrade' does not do self-upgrade first

... and a lot of testing.
parent 0e24207c
src/apk
src/apk_test
src/apk.static
test/*.got
*.o
*.d
*.cmd
......
......@@ -19,11 +19,11 @@ $(error Build dependencies are not met)
endif
progs-y += apk
apk-objs := apk.o add.o del.o fix.o update.o info.o \
apk-objs := apk.o add.o del.o update.o info.o \
search.o upgrade.o cache.o ver.o index.o fetch.o \
audit.o verify.o dot.o
libapk.so-objs := common.o state.o database.o package.o archive.o \
libapk.so-objs := common.o database.o package.o archive.o \
version.o io.o url.o gunzip.o blob.o hash.o print.o \
solver.o
......
......@@ -13,11 +13,12 @@
#include <stdio.h>
#include "apk_applet.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h"
#include "apk_solver.h"
struct add_ctx {
const char *virtpkg;
unsigned short solver_flags;
};
static int add_parse(void *ctx, struct apk_db_options *dbopts,
......@@ -30,7 +31,7 @@ static int add_parse(void *ctx, struct apk_db_options *dbopts,
dbopts->open_flags |= APK_OPENF_CREATE;
break;
case 'u':
apk_flags |= APK_UPGRADE;
actx->solver_flags |= APK_SOLVERF_UPGRADE;
break;
case 't':
actx->virtpkg = optarg;
......@@ -60,11 +61,12 @@ static int non_repository_check(struct apk_database *db)
static int add_main(void *ctx, struct apk_database *db, int argc, char **argv)
{
struct add_ctx *actx = (struct add_ctx *) ctx;
struct apk_state *state = NULL;
struct apk_package *virtpkg = NULL;
struct apk_dependency virtdep;
struct apk_dependency *deps;
int i, r = 0, num_deps = 0, errors = 0;
struct apk_dependency_array *world = NULL;
int i, r = 0;
apk_dependency_array_copy(&world, db->world);
if (actx->virtpkg) {
if (non_repository_check(db))
......@@ -82,13 +84,8 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv)
virtpkg->description = strdup("virtual meta package");
virtpkg->arch = apk_blob_atomize(APK_BLOB_STR("noarch"));
apk_dep_from_pkg(&virtdep, db, virtpkg);
virtdep.name->flags |= APK_NAME_TOPLEVEL;
virtpkg = apk_db_pkg_add(db, virtpkg);
num_deps = 1;
} else
num_deps = argc;
deps = alloca(sizeof(struct apk_dependency) * num_deps);
}
for (i = 0; i < argc; i++) {
struct apk_dependency dep;
......@@ -117,35 +114,15 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv)
if (virtpkg)
apk_deps_add(&virtpkg->depends, &dep);
else {
deps[i] = dep;
deps[i].name->flags |= APK_NAME_TOPLEVEL_OVERRIDE;
}
else
apk_deps_add(&world, &dep);
}
if (virtpkg)
deps[0] = virtdep;
apk_deps_add(&world, &virtdep);
state = apk_state_new(db);
if (state == NULL)
return -1;
r = apk_solver_commit(db, actx->solver_flags, world);
apk_dependency_array_free(&world);
for (i = 0; i < num_deps; i++) {
r = apk_state_lock_dependency(state, &deps[i]);
if (r == 0) {
apk_deps_add(&db->world, &deps[i]);
deps[i].name->flags |= APK_NAME_TOPLEVEL;
} else {
errors++;
}
}
if (errors && !(apk_flags & APK_FORCE)) {
apk_state_print_errors(state);
r = -1;
} else {
r = apk_state_commit(state);
}
if (state != NULL)
apk_state_unref(state);
return r;
}
......
......@@ -81,15 +81,12 @@ struct apk_db_dir_instance {
gid_t gid;
};
#define APK_NAME_TOPLEVEL 0x0001
#define APK_NAME_REINSTALL 0x0002
#define APK_NAME_TOPLEVEL_OVERRIDE 0x0004
#define APK_NAME_VISITED 0x8000
struct apk_name {
apk_hash_node hash_node;
unsigned int id;
unsigned int flags;
union {
int state_int;
void *state_ptr;
};
char *name;
struct apk_package_array *pkgs;
struct apk_name_array *rdepends;
......@@ -121,7 +118,7 @@ struct apk_db_options {
struct apk_database {
char *root;
int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd;
unsigned name_id, num_repos;
unsigned num_repos;
const char *cache_dir;
char *cache_remount_dir;
apk_blob_t *arch;
......
......@@ -56,14 +56,11 @@ extern char **apk_argv;
#define APK_SIMULATE 0x0002
#define APK_CLEAN_PROTECTED 0x0004
#define APK_PROGRESS 0x0008
#define APK_UPGRADE 0x0010
#define APK_RECURSIVE 0x0020
#define APK_PREFER_AVAILABLE 0x0040
#define APK_UPDATE_CACHE 0x0080
#define APK_ALLOW_UNTRUSTED 0x0100
#define APK_PURGE 0x0200
#define APK_INTERACTIVE 0x0400
#define APK_RECURSIVE_DELETE 0x0800
#define APK_NO_NETWORK 0x1000
#define APK_OVERLAY_FROM_STDIN 0x2000
......@@ -108,6 +105,12 @@ void *apk_array_resize(void *array, size_t new_size, size_t elem_size);
{ \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
} \
static inline void \
array_type_name##_copy(struct array_type_name **a, struct array_type_name *b)\
{ \
*a = apk_array_resize(*a, b->num, sizeof(elem_type_name));\
memcpy((*a)->item, b->item, b->num * sizeof(elem_type_name));\
} \
static inline elem_type_name * \
array_type_name##_add(struct array_type_name **a) \
{ \
......
......@@ -22,12 +22,19 @@ struct apk_changeset {
struct apk_change_array *changes;
};
void apk_solver_sort(struct apk_database *db);
int apk_solver_solve(struct apk_database *db, struct apk_dependency_array *world,
struct apk_package_array **solution, int allow_errors);
int apk_solver_generate_changeset(struct apk_database *db,
struct apk_package_array *solution,
struct apk_changeset *changeset);
#define APK_SOLVERF_UPGRADE 0x0001
#define APK_SOLVERF_AVAILABLE 0x0002
#define APK_SOLVERF_REINSTALL 0x0004
int apk_solver_solve(struct apk_database *db,
unsigned short solver_flags,
struct apk_dependency_array *world,
struct apk_package_array **solution,
struct apk_changeset *changeset);
int apk_solver_commit(struct apk_database *db,
unsigned short solver_flags,
struct apk_dependency_array *world);
#endif
/* apk_state.h - Alpine Package Keeper (APK)
*
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
* Copyright (C) 2008 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.
*/
#ifndef APK_STATE_H
#define APK_STATE_H
#include "apk_database.h"
typedef void *apk_name_state_t;
struct apk_change {
struct list_head change_list;
struct apk_package *oldpkg;
struct apk_package *newpkg;
};
struct apk_state {
unsigned int refs, num_names, num_changes;
int print_ok;
struct apk_database *db;
struct list_head change_list_head;
struct apk_package_array *conflicts;
struct apk_name_array *missing;
apk_name_state_t name[];
};
struct apk_state *apk_state_new(struct apk_database *db);
struct apk_state *apk_state_dup(struct apk_state *state);
void apk_state_unref(struct apk_state *state);
void apk_state_print_errors(struct apk_state *state);
int apk_state_commit(struct apk_state *state);
int apk_state_lock_dependency(struct apk_state *state,
struct apk_dependency *dep);
int apk_state_lock_name(struct apk_state *state,
struct apk_name *name,
struct apk_package *newpkg);
#endif
......@@ -17,36 +17,30 @@
#include "apk_defines.h"
#include "apk_applet.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_package.h"
#include "apk_print.h"
#include "apk_solver.h"
#define CACHE_CLEAN BIT(0)
#define CACHE_DOWNLOAD BIT(1)
static int cache_download(struct apk_database *db)
{
struct apk_state *state;
struct apk_changeset changeset;
struct apk_change *change;
struct apk_package *pkg;
struct apk_repository *repo;
char item[PATH_MAX], cacheitem[PATH_MAX];
int i, r = 0;
state = apk_state_new(db);
if (state == NULL)
goto err;
for (i = 0; i < db->world->num; i++) {
r = apk_state_lock_dependency(state, &db->world->item[i]);
if (r != 0) {
apk_error("Unable to select version for '%s': %d",
db->world->item[i].name->name, r);
goto err;
}
r = apk_solver_solve(db, 0, db->world, NULL, &changeset);
if (r != 0) {
apk_error("Unable to select packages. Run apk fix.");
return r;
}
list_for_each_entry(change, &state->change_list_head, change_list) {
for (i = 0; i < changeset.changes->num; i++) {
change = &changeset.changes->item[i];
pkg = change->newpkg;
apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem));
......@@ -63,9 +57,6 @@ static int cache_download(struct apk_database *db)
APK_SIGN_VERIFY_IDENTITY);
}
err:
if (state != NULL)
apk_state_unref(state);
return r;
}
......
......@@ -29,7 +29,6 @@
#include "apk_defines.h"
#include "apk_package.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_applet.h"
#include "apk_archive.h"
#include "apk_print.h"
......@@ -207,7 +206,6 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name)
return NULL;
pn->name = apk_blob_cstr(name);
pn->id = db->name_id++;
apk_package_array_init(&pn->pkgs);
apk_name_array_init(&pn->rdepends);
apk_name_array_init(&pn->rinstall_if);
......@@ -885,7 +883,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
struct apk_istream *is;
struct apk_bstream *bs;
apk_blob_t blob;
int i, r;
int r;
/* Read:
* 1. installed repository
......@@ -901,9 +899,6 @@ static int apk_db_read_state(struct apk_database *db, int flags)
return -ENOENT;
apk_deps_parse(db, &db->world, blob);
free(blob.ptr);
for (i = 0; i < db->world->num; i++)
db->world->item[i].name->flags |= APK_NAME_TOPLEVEL;
}
if (!(flags & APK_OPENF_NO_INSTALLED)) {
......
......@@ -11,17 +11,16 @@
#include <stdio.h>
#include "apk_applet.h"
#include "apk_state.h"
#include "apk_database.h"
#include "apk_print.h"
#include "apk_solver.h"
static int del_parse(void *ctx, struct apk_db_options *db,
int optch, int optindex, const char *optarg)
{
switch (optch) {
case 'r':
apk_flags |= APK_RECURSIVE_DELETE;
break;
/* FIXME: Reimplement recursive delete. */
default:
return -1;
}
......@@ -30,40 +29,17 @@ static int del_parse(void *ctx, struct apk_db_options *db,
static int del_main(void *ctx, struct apk_database *db, int argc, char **argv)
{
struct apk_state *state;
struct apk_name *name;
struct apk_dependency_array *world = NULL;
int i, r = 0;
apk_dependency_array_copy(&world, db->world);
for (i = 0; i < argc; i++) {
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
name->flags &= ~APK_NAME_TOPLEVEL;
name->flags |= APK_NAME_TOPLEVEL_OVERRIDE;
apk_deps_del(&db->world, name);
apk_deps_del(&world, name);
}
state = apk_state_new(db);
if (state == NULL)
goto err;
for (i = 0; i < argc; i++) {
struct apk_dependency dep;
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
dep = (struct apk_dependency) {
.name = name,
.version = apk_blob_atomize(APK_BLOB_NULL),
.result_mask = APK_DEPMASK_CONFLICT,
};
r |= apk_state_lock_dependency(state, &dep);
}
if (r == 0)
r = apk_state_commit(state);
else
apk_state_print_errors(state);
err:
if (state != NULL)
apk_state_unref(state);
r = apk_solver_commit(db, 0, world);
apk_dependency_array_free(&world);
return r;
}
......
......@@ -71,10 +71,10 @@ static int dump_pkg(struct dot_ctx *ctx, struct apk_package *pkg)
printf(" \"" PKG_VER_FMT "\" -> \"%s\" [color=red];\n",
PKG_VER_PRINTF(pkg),
name->name);
if (!(name->flags & APK_NAME_VISITED)) {
if (!name->state_int) {
printf(" \"%s\" [style=dashed, color=red, fontcolor=red, shape=octagon];\n",
name->name);
name->flags |= APK_NAME_VISITED;
name->state_int = 1;
}
} else {
for (j = 0; j < name->pkgs->num; j++) {
......
......@@ -18,7 +18,6 @@
#include "apk_applet.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_io.h"
#include "apk_print.h"
......@@ -180,6 +179,7 @@ static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
.result_mask = APK_DEPMASK_REQUIRE,
};
#if 0
if (fctx->flags & FETCH_RECURSIVE) {
struct apk_state *state;
struct apk_change *change;
......@@ -203,7 +203,9 @@ static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
}
apk_state_unref(state);
} else {
} else
#endif
{
struct apk_package *pkg = NULL;
for (j = 0; j < dep.name->pkgs->num; j++)
......
......@@ -16,6 +16,8 @@
#include "apk_state.h"
#include "apk_print.h"
/* FIXME: reimplement fix applet */
struct fix_ctx {
unsigned int reinstall : 1;
};
......
......@@ -15,7 +15,6 @@
#include "apk_applet.h"
#include "apk_package.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h"
struct info_ctx {
......
......@@ -27,7 +27,6 @@
#include "apk_archive.h"
#include "apk_package.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h"
void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to)
......
......@@ -15,7 +15,6 @@
#include "apk_applet.h"
#include "apk_package.h"
#include "apk_database.h"
#include "apk_state.h"
struct search_ctx {
int (*match)(struct apk_package *pkg, const char *str);
......
This diff is collapsed.
This diff is collapsed.
......@@ -14,15 +14,21 @@
#include <zlib.h>
#include "apk_applet.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h"
#include "apk_solver.h"
struct upgrade_ctx {
unsigned short solver_flags;
};
static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
int optch, int optindex, const char *optarg)
{
struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;
switch (optch) {
case 'a':
apk_flags |= APK_PREFER_AVAILABLE;
uctx->solver_flags |= APK_SOLVERF_AVAILABLE;
break;
default:
return -1;
......@@ -30,8 +36,10 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
return 0;
}
int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state)
int apk_do_self_upgrade(struct apk_database *db)
{
#if 0
/* FIXME: Reimplement self-upgrade. */
struct apk_dependency dep;
int r;
......@@ -57,58 +65,24 @@ int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state)
apk_error("PANIC! Failed to re-execute new apk-tools!");
exit(1);
#else
return 0;
#endif
}
static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **argv)
{
struct apk_state *state = NULL;
struct apk_name_array *missing;
int i, r = 0;
apk_flags |= APK_UPGRADE;
apk_name_array_init(&missing);
state = apk_state_new(db);
if (state == NULL)
goto err;
struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;
unsigned short solver_flags;
int r;
r = apk_do_self_upgrade(db, state);
if (r != 0) {
apk_state_print_errors(state);
goto err;
}
solver_flags = APK_SOLVERF_UPGRADE | uctx->solver_flags;
for (i = 0; i < db->world->num; i++) {
struct apk_dependency *dep = &db->world->item[i];
r = apk_do_self_upgrade(db);
if (r != 0)
return r;
if (dep->name->pkgs->num != 0)
r |= apk_state_lock_dependency(state, dep);
else
*apk_name_array_add(&missing) = dep->name;
}
if (r == 0) {
for (i = 0; i < missing->num; i++) {
struct apk_indent indent;
struct apk_name *name = missing->item[i];
if (i == 0) {
apk_warning("The following package names no longer exists in repository:");
indent.x = 0;
indent.indent = 2;
}
apk_print_indented(&indent, APK_BLOB_STR(name->name));
}
if (i != 0)
printf("\n");
r = apk_state_commit(state);
} else
apk_state_print_errors(state);
err:
if (state != NULL)
apk_state_unref(state);
apk_name_array_free(&missing);
return r;
return apk_solver_commit(db, solver_flags, db->world);
}
static struct apk_option upgrade_options[] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment