errors: rewrite the logic how errors are reported
Instead of the dependency oriented logic, switch to print them for each package or name needed. Might give a bit more readable errors now. There's still few corner cases that proper error is not output, which are cought by the test cases.cute-signatures
parent
25ff68a87e
commit
e51232e710
|
@ -143,6 +143,9 @@ void *apk_array_resize(void *array, size_t new_size, size_t elem_size);
|
||||||
|
|
||||||
APK_ARRAY(apk_string_array, char *);
|
APK_ARRAY(apk_string_array, char *);
|
||||||
|
|
||||||
|
#define foreach_array_item(iter, array) \
|
||||||
|
for (iter = &(array)->item[0]; iter < &(array)->item[(array)->num]; iter++)
|
||||||
|
|
||||||
#define LIST_END (void *) 0xe01
|
#define LIST_END (void *) 0xe01
|
||||||
#define LIST_POISON1 (void *) 0xdeadbeef
|
#define LIST_POISON1 (void *) 0xdeadbeef
|
||||||
#define LIST_POISON2 (void *) 0xabbaabba
|
#define LIST_POISON2 (void *) 0xabbaabba
|
||||||
|
|
|
@ -37,6 +37,10 @@ struct apk_provider;
|
||||||
#define APK_SIGN_GENERATE 4
|
#define APK_SIGN_GENERATE 4
|
||||||
#define APK_SIGN_VERIFY_AND_GENERATE 5
|
#define APK_SIGN_VERIFY_AND_GENERATE 5
|
||||||
|
|
||||||
|
#define APK_DEP_IRRELEVANT 0
|
||||||
|
#define APK_DEP_SATISFIED 1
|
||||||
|
#define APK_DEP_CONFLICTED 2
|
||||||
|
|
||||||
struct apk_sign_ctx {
|
struct apk_sign_ctx {
|
||||||
int keys_fd;
|
int keys_fd;
|
||||||
int action;
|
int action;
|
||||||
|
@ -129,6 +133,8 @@ void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db,
|
||||||
int apk_dep_is_materialized(struct apk_dependency *dep, struct apk_package *pkg);
|
int apk_dep_is_materialized(struct apk_dependency *dep, struct apk_package *pkg);
|
||||||
int apk_dep_is_materialized_or_provided(struct apk_dependency *dep, struct apk_package *pkg);
|
int apk_dep_is_materialized_or_provided(struct apk_dependency *dep, struct apk_package *pkg);
|
||||||
int apk_dep_is_provided(struct apk_dependency *dep, struct apk_provider *p);
|
int apk_dep_is_provided(struct apk_dependency *dep, struct apk_provider *p);
|
||||||
|
int apk_dep_analyze(struct apk_dependency *dep, struct apk_package *pkg);
|
||||||
|
char *apk_dep_snprintf(char *buf, size_t n, struct apk_dependency *dep);
|
||||||
|
|
||||||
void apk_blob_push_dep(apk_blob_t *to, struct apk_database *, struct apk_dependency *dep);
|
void apk_blob_push_dep(apk_blob_t *to, struct apk_database *, struct apk_dependency *dep);
|
||||||
void apk_blob_push_deps(apk_blob_t *to, struct apk_database *, struct apk_dependency_array *deps);
|
void apk_blob_push_deps(apk_blob_t *to, struct apk_database *, struct apk_dependency_array *deps);
|
||||||
|
|
|
@ -31,5 +31,6 @@ struct apk_indent {
|
||||||
|
|
||||||
int apk_print_indented(struct apk_indent *i, apk_blob_t blob);
|
int apk_print_indented(struct apk_indent *i, apk_blob_t blob);
|
||||||
void apk_print_indented_words(struct apk_indent *i, const char *text);
|
void apk_print_indented_words(struct apk_indent *i, const char *text);
|
||||||
|
void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
365
src/commit.c
365
src/commit.c
|
@ -18,6 +18,46 @@
|
||||||
|
|
||||||
#include "apk_print.h"
|
#include "apk_print.h"
|
||||||
|
|
||||||
|
static void foreach_package_reverse_dependency2(
|
||||||
|
struct apk_package *pkg,
|
||||||
|
struct apk_name_array *rdepends,
|
||||||
|
int match,
|
||||||
|
void cb(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx),
|
||||||
|
void *ctx)
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for (i = 0; i < rdepends->num; i++) {
|
||||||
|
struct apk_name *name0 = rdepends->item[i];
|
||||||
|
|
||||||
|
for (j = 0; j < name0->providers->num; j++) {
|
||||||
|
struct apk_package *pkg0 = name0->providers->item[j].pkg;
|
||||||
|
|
||||||
|
for (k = 0; k < pkg0->depends->num; k++) {
|
||||||
|
struct apk_dependency *d0 = &pkg0->depends->item[k];
|
||||||
|
if (apk_dep_analyze(d0, pkg) == match)
|
||||||
|
cb(pkg0, d0, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreach_package_reverse_dependency(
|
||||||
|
struct apk_package *pkg,
|
||||||
|
int match,
|
||||||
|
void cb(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx),
|
||||||
|
void *ctx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (pkg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach_package_reverse_dependency2(pkg, pkg->name->rdepends, match, cb, ctx);
|
||||||
|
for (i = 0; i < pkg->provides->num; i++)
|
||||||
|
foreach_package_reverse_dependency2(pkg, pkg->provides->item[i].name->rdepends, match, cb, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pkg_available(struct apk_database *db, struct apk_package *pkg)
|
static inline int pkg_available(struct apk_database *db, struct apk_package *pkg)
|
||||||
{
|
{
|
||||||
if (pkg->repos & db->available_repos)
|
if (pkg->repos & db->available_repos)
|
||||||
|
@ -370,27 +410,46 @@ all_done:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_name_if_virtual(struct apk_name_array **names, struct apk_name *name)
|
enum {
|
||||||
|
STATE_UNSET = 0,
|
||||||
|
STATE_PRESENT,
|
||||||
|
STATE_MISSING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct print_state {
|
||||||
|
struct apk_database *db;
|
||||||
|
struct apk_dependency_array *world;
|
||||||
|
struct apk_indent i;
|
||||||
|
struct apk_name_array *missing;
|
||||||
|
const char *label;
|
||||||
|
int num_labels;
|
||||||
|
int match;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void label_start(struct print_state *ps, const char *text)
|
||||||
{
|
{
|
||||||
int i;
|
if (ps->label) {
|
||||||
|
printf(" %s:\n", ps->label);
|
||||||
if (name->providers->num == 0)
|
ps->label = NULL;
|
||||||
return;
|
ps->i.x = ps->i.indent = 0;
|
||||||
|
ps->num_labels++;
|
||||||
for (i = 0; i < name->providers->num; i++)
|
}
|
||||||
if (name->providers->item[i].pkg->name == name)
|
if (ps->i.x == 0) {
|
||||||
return;
|
ps->i.x = printf(" %s", text);
|
||||||
|
ps->i.indent = ps->i.x + 1;
|
||||||
for (i = 0; i < (*names)->num; i++)
|
}
|
||||||
if ((*names)->item[i] == name)
|
}
|
||||||
return;
|
static void label_end(struct print_state *ps)
|
||||||
|
{
|
||||||
*apk_name_array_add(names) = name;
|
if (ps->i.x != 0) {
|
||||||
|
printf("\n");
|
||||||
|
ps->i.x = ps->i.indent = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_pinning_errors(struct apk_database *db, char *label,
|
static void print_pinning_errors(struct print_state *ps, struct apk_package *pkg, unsigned int tag)
|
||||||
struct apk_package *pkg, unsigned int tag)
|
|
||||||
{
|
{
|
||||||
|
struct apk_database *db = ps->db;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pkg->ipkg != NULL)
|
if (pkg->ipkg != NULL)
|
||||||
|
@ -398,68 +457,146 @@ static void print_pinning_errors(struct apk_database *db, char *label,
|
||||||
if (pkg->repos & apk_db_get_pinning_mask_repos(db, APK_DEFAULT_PINNING_MASK | BIT(tag)))
|
if (pkg->repos & apk_db_get_pinning_mask_repos(db, APK_DEFAULT_PINNING_MASK | BIT(tag)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf(" %s: not pinned:", label);
|
|
||||||
for (i = 0; i < db->num_repo_tags; i++) {
|
for (i = 0; i < db->num_repo_tags; i++) {
|
||||||
if (pkg->repos & db->repo_tags[i].allowed_repos)
|
if (pkg->repos & db->repo_tags[i].allowed_repos) {
|
||||||
printf(" @" BLOB_FMT, BLOB_PRINTF(*db->repo_tags[i].name));
|
label_start(ps, "masked in:");
|
||||||
|
apk_print_indented(&ps->i, *db->repo_tags[i].name);
|
||||||
}
|
}
|
||||||
printf("\n");
|
}
|
||||||
|
label_end(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_dep_errors(struct apk_database *db, char *label,
|
static void print_conflicts(struct print_state *ps, struct apk_package *pkg)
|
||||||
struct apk_dependency_array *deps,
|
|
||||||
struct apk_name_array **names)
|
|
||||||
{
|
{
|
||||||
int i, print_label = 1;
|
struct apk_provider *p;
|
||||||
char buf[256];
|
struct apk_dependency *d;
|
||||||
apk_blob_t p;
|
|
||||||
struct apk_indent indent;
|
|
||||||
|
|
||||||
for (i = 0; i < deps->num; i++) {
|
foreach_array_item(p, pkg->name->providers) {
|
||||||
struct apk_dependency *dep = &deps->item[i];
|
if (p->pkg == pkg || p->pkg->state_ptr == STATE_UNSET)
|
||||||
struct apk_package *pkg;
|
|
||||||
|
|
||||||
pkg = (struct apk_package*) (dep->name->state_int & ~1);
|
|
||||||
if (apk_dep_is_materialized_or_provided(dep, pkg))
|
|
||||||
continue;
|
continue;
|
||||||
|
label_start(ps, "conflicts:");
|
||||||
if (pkg == NULL)
|
apk_print_indented_fmt(&ps->i, PKG_VER_FMT, PKG_VER_PRINTF(p->pkg));
|
||||||
add_name_if_virtual(names, dep->name);
|
|
||||||
|
|
||||||
if (print_label) {
|
|
||||||
print_label = 0;
|
|
||||||
indent.x = printf(" %s:", label);
|
|
||||||
indent.indent = indent.x + 1;
|
|
||||||
}
|
}
|
||||||
p = APK_BLOB_BUF(buf);
|
foreach_array_item(d, pkg->provides) {
|
||||||
apk_blob_push_dep(&p, db, dep);
|
foreach_array_item(p, d->name->providers) {
|
||||||
p = apk_blob_pushed(APK_BLOB_BUF(buf), p);
|
if (p->pkg == pkg || p->pkg->state_ptr == STATE_UNSET)
|
||||||
apk_print_indented(&indent, p);
|
continue;
|
||||||
|
label_start(ps, "conflicts:");
|
||||||
|
apk_print_indented_fmt(
|
||||||
|
&ps->i,
|
||||||
|
PKG_VER_FMT "[%s]",
|
||||||
|
PKG_VER_PRINTF(p->pkg),
|
||||||
|
d->name->name);
|
||||||
}
|
}
|
||||||
if (!print_label)
|
}
|
||||||
printf("\n");
|
label_end(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_provides_errors(struct apk_database *db, char *label,
|
static void print_dep(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx)
|
||||||
struct apk_package *pkg)
|
|
||||||
{
|
{
|
||||||
int i;
|
struct print_state *ps = (struct print_state *) ctx;
|
||||||
|
const char *label = (ps->match == APK_DEP_SATISFIED) ? "satisfies:" : "breaks:";
|
||||||
|
char tmp[256];
|
||||||
|
|
||||||
for (i = 0; i < pkg->provides->num; i++) {
|
if (pkg0 != NULL && pkg0->state_ptr == STATE_UNSET)
|
||||||
struct apk_name *pn = pkg->provides->item[i].name;
|
return;
|
||||||
struct apk_provider p = APK_PROVIDER_FROM_PROVIDES(pkg, &pkg->provides->item[i]);
|
|
||||||
struct apk_package *pkgC = (struct apk_package *) (pn->state_int & ~1);
|
|
||||||
|
|
||||||
if (pkgC == NULL && p.version == &apk_null_blob)
|
label_start(ps, label);
|
||||||
continue;
|
if (pkg0 == NULL)
|
||||||
|
apk_print_indented_fmt(&ps->i, "world[%s]", apk_dep_snprintf(tmp, sizeof(tmp), d0));
|
||||||
|
else
|
||||||
|
apk_print_indented_fmt(&ps->i, PKG_VER_FMT "[%s]",
|
||||||
|
PKG_VER_PRINTF(pkg0),
|
||||||
|
apk_dep_snprintf(tmp, sizeof(tmp), d0));
|
||||||
|
}
|
||||||
|
|
||||||
if ((pkgC == pkg) && (pn->state_int & 1) == 0) {
|
static void print_deps(struct print_state *ps, struct apk_package *pkg, int match)
|
||||||
pn->state_int |= 1;
|
{
|
||||||
continue;
|
struct apk_dependency *d0;
|
||||||
|
|
||||||
|
ps->match = match;
|
||||||
|
foreach_array_item(d0, ps->world) {
|
||||||
|
if (apk_dep_analyze(d0, pkg) == match)
|
||||||
|
print_dep(NULL, d0, ps);
|
||||||
|
}
|
||||||
|
foreach_package_reverse_dependency(pkg, ps->match, print_dep, ps);
|
||||||
|
label_end(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void analyze_package(struct print_state *ps, struct apk_package *pkg, unsigned int tag)
|
||||||
|
{
|
||||||
|
char pkgtext[256];
|
||||||
|
|
||||||
|
snprintf(pkgtext, sizeof(pkgtext), PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
||||||
|
ps->label = pkgtext;
|
||||||
|
|
||||||
|
print_pinning_errors(ps, pkg, tag);
|
||||||
|
print_conflicts(ps, pkg);
|
||||||
|
print_deps(ps, pkg, APK_DEP_CONFLICTED);
|
||||||
|
if (ps->label == NULL)
|
||||||
|
print_deps(ps, pkg, APK_DEP_SATISFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void analyze_name(struct print_state *ps, struct apk_name *name)
|
||||||
|
{
|
||||||
|
struct apk_name **pname0, *name0;
|
||||||
|
struct apk_provider *p0;
|
||||||
|
struct apk_dependency *d0;
|
||||||
|
char tmp[256];
|
||||||
|
|
||||||
|
if (name->providers->num) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s (virtual)", name->name);
|
||||||
|
ps->label = tmp;
|
||||||
|
|
||||||
|
label_start(ps, "provided by:");
|
||||||
|
foreach_array_item(p0, name->providers) {
|
||||||
|
/* FIXME: print only name if all pkgs provide it */
|
||||||
|
struct apk_package *pkg = p0->pkg;
|
||||||
|
apk_print_indented_fmt(&ps->i, PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
||||||
|
}
|
||||||
|
label_end(ps);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s (missing)", name->name);
|
||||||
|
ps->label = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" %s provides " PROVIDER_FMT " conflicting with " PKG_VER_FMT "\n",
|
label_start(ps, "required by:");
|
||||||
label, PROVIDER_PRINTF(pn, &p), PKG_VER_PRINTF(pkgC));
|
foreach_array_item(d0, ps->world) {
|
||||||
|
if (d0->name != name || d0->conflict)
|
||||||
|
continue;
|
||||||
|
apk_print_indented_fmt(&ps->i, "world[%s]",
|
||||||
|
apk_dep_snprintf(tmp, sizeof(tmp), d0));
|
||||||
|
}
|
||||||
|
foreach_array_item(pname0, name->rdepends) {
|
||||||
|
name0 = *pname0;
|
||||||
|
foreach_array_item(p0, name0->providers) {
|
||||||
|
if (p0->pkg->state_ptr == STATE_UNSET)
|
||||||
|
continue;
|
||||||
|
foreach_array_item(d0, p0->pkg->depends) {
|
||||||
|
if (d0->name != name || d0->conflict)
|
||||||
|
continue;
|
||||||
|
apk_print_indented_fmt(&ps->i,
|
||||||
|
PKG_VER_FMT "[%s]",
|
||||||
|
PKG_VER_PRINTF(p0->pkg),
|
||||||
|
apk_dep_snprintf(tmp, sizeof(tmp), d0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (d0 != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label_end(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void analyze_deps(struct print_state *ps, struct apk_dependency_array *deps)
|
||||||
|
{
|
||||||
|
struct apk_dependency *d0;
|
||||||
|
|
||||||
|
foreach_array_item(d0, deps) {
|
||||||
|
if (d0->name->state_int != STATE_UNSET)
|
||||||
|
continue;
|
||||||
|
d0->name->state_int = STATE_MISSING;
|
||||||
|
analyze_name(ps, d0->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,60 +604,76 @@ void apk_solver_print_errors(struct apk_database *db,
|
||||||
struct apk_changeset *changeset,
|
struct apk_changeset *changeset,
|
||||||
struct apk_dependency_array *world)
|
struct apk_dependency_array *world)
|
||||||
{
|
{
|
||||||
struct apk_name_array *names;
|
struct print_state ps;
|
||||||
char pkgtext[256];
|
struct apk_change *change;
|
||||||
int i, j;
|
struct apk_dependency *p;
|
||||||
|
|
||||||
apk_name_array_init(&names);
|
/* ERROR: unsatisfiable dependencies:
|
||||||
/* FIXME: Print more rational error messages. Group failed
|
* name:
|
||||||
* dependencies by package name. As in,
|
* required by: a b c d e
|
||||||
* pkg-1.2 selected, but:
|
* not available in any repository
|
||||||
* world: pkg>2
|
* name (virtual):
|
||||||
|
* required by: a b c d e
|
||||||
|
* provided by: foo bar zed
|
||||||
|
* pkg-1.2:
|
||||||
|
* masked by: @testing
|
||||||
|
* satisfies: a[pkg]
|
||||||
|
* conflicts: pkg-2.0 foo-1.2 bar-1.2
|
||||||
|
* breaks: b[pkg>2] c[foo>2] d[!pkg]
|
||||||
|
*
|
||||||
|
* When two packages provide same name 'foo':
|
||||||
|
* a-1:
|
||||||
|
* satisfies: world[a]
|
||||||
|
* conflicts: b-1[foo]
|
||||||
|
* b-1:
|
||||||
|
* satisfies: world[b]
|
||||||
|
* conflicts: a-1[foo]
|
||||||
|
*
|
||||||
|
* c-1:
|
||||||
|
* satisfies: world[a]
|
||||||
|
* conflicts: c-1[foo] (self-conflict by providing foo twice)
|
||||||
|
*
|
||||||
|
* When two packages get pulled in:
|
||||||
|
* a-1:
|
||||||
|
* satisfies: app1[so:a.so.1]
|
||||||
|
* conflicts: a-2
|
||||||
|
* a-2:
|
||||||
|
* satisfies: app2[so:a.so.2]
|
||||||
|
* conflicts: a-1
|
||||||
|
*
|
||||||
|
* satisfies lists all dependencies that is not satisfiable by
|
||||||
|
* any other selected version. or all of them with -v.
|
||||||
*/
|
*/
|
||||||
apk_error("unsatisfiable dependencies:");
|
|
||||||
|
|
||||||
for (i = 0; i < changeset->changes->num; i++) {
|
apk_error("unsatisfiable constraints:");
|
||||||
struct apk_package *pkg = changeset->changes->item[i].new_pkg;
|
|
||||||
if (pkg == NULL)
|
|
||||||
continue;
|
|
||||||
pkg->state_int = 1;
|
|
||||||
pkg->name->state_ptr = pkg;
|
|
||||||
for (j = 0; j < pkg->provides->num; j++) {
|
|
||||||
if (pkg->provides->item[j].version == &apk_null_blob)
|
|
||||||
continue;
|
|
||||||
if (pkg->provides->item[j].name->state_ptr == NULL)
|
|
||||||
pkg->provides->item[j].name->state_ptr = pkg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_dep_errors(db, "world", world, &names);
|
/* Construct information about names */
|
||||||
for (i = 0; i < changeset->changes->num; i++) {
|
foreach_array_item(change, changeset->changes) {
|
||||||
struct apk_change *change = &changeset->changes->item[i];
|
|
||||||
struct apk_package *pkg = change->new_pkg;
|
struct apk_package *pkg = change->new_pkg;
|
||||||
if (pkg == NULL)
|
if (pkg == NULL)
|
||||||
continue;
|
continue;
|
||||||
snprintf(pkgtext, sizeof(pkgtext), PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
pkg->state_int = STATE_PRESENT;
|
||||||
print_pinning_errors(db, pkgtext, pkg, change->new_repository_tag);
|
pkg->name->state_int = STATE_PRESENT;
|
||||||
print_dep_errors(db, pkgtext, pkg->depends, &names);
|
foreach_array_item(p, pkg->provides)
|
||||||
print_provides_errors(db, pkgtext, pkg);
|
p->name->state_int = STATE_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < names->num; i++) {
|
/* Analyze is package, and missing names referred to */
|
||||||
struct apk_indent indent;
|
ps = (struct print_state) {
|
||||||
struct apk_name *name = names->item[i];
|
.db = db,
|
||||||
|
.world = world,
|
||||||
printf("\n %s is a virtual package provided by:\n ", name->name);
|
};
|
||||||
indent.x = 4;
|
analyze_deps(&ps, world);
|
||||||
indent.indent = 4;
|
foreach_array_item(change, changeset->changes) {
|
||||||
|
struct apk_package *pkg = change->new_pkg;
|
||||||
for (j = 0; j < name->providers->num; j++) {
|
if (pkg == NULL)
|
||||||
struct apk_package *pkg = name->providers->item[j].pkg;
|
continue;
|
||||||
snprintf(pkgtext, sizeof(pkgtext), PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
analyze_package(&ps, pkg, change->new_repository_tag);
|
||||||
apk_print_indented(&indent, APK_BLOB_STR(pkgtext));
|
analyze_deps(&ps, pkg->depends);
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
if (ps.num_labels == 0)
|
||||||
apk_name_array_free(&names);
|
printf(" Huh? Error reporter did not find the broken constraints.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int apk_solver_commit(struct apk_database *db,
|
int apk_solver_commit(struct apk_database *db,
|
||||||
|
|
|
@ -399,6 +399,40 @@ int apk_dep_is_materialized_or_provided(struct apk_dependency *dep, struct apk_p
|
||||||
return dep->conflict;
|
return dep->conflict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int apk_dep_analyze(struct apk_dependency *dep, struct apk_package *pkg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (pkg == NULL)
|
||||||
|
return APK_DEP_IRRELEVANT;
|
||||||
|
|
||||||
|
if (dep->name == pkg->name)
|
||||||
|
return apk_dep_is_materialized(dep, pkg) ? APK_DEP_SATISFIED : APK_DEP_CONFLICTED;
|
||||||
|
|
||||||
|
for (i = 0; i < pkg->provides->num; i++) {
|
||||||
|
struct apk_provider p;
|
||||||
|
|
||||||
|
if (pkg->provides->item[i].name != dep->name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = APK_PROVIDER_FROM_PROVIDES(pkg, &pkg->provides->item[i]);
|
||||||
|
return apk_dep_is_provided(dep, &p) ? APK_DEP_SATISFIED : APK_DEP_CONFLICTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return APK_DEP_IRRELEVANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *apk_dep_snprintf(char *buf, size_t n, struct apk_dependency *dep)
|
||||||
|
{
|
||||||
|
apk_blob_t b = APK_BLOB_PTR_LEN(buf, n);
|
||||||
|
apk_blob_push_dep(&b, NULL, dep);
|
||||||
|
if (b.len)
|
||||||
|
apk_blob_push_blob(&b, APK_BLOB_PTR_LEN("", 1));
|
||||||
|
else
|
||||||
|
b.ptr[-1] = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
void apk_blob_push_dep(apk_blob_t *to, struct apk_database *db, struct apk_dependency *dep)
|
void apk_blob_push_dep(apk_blob_t *to, struct apk_database *db, struct apk_dependency *dep)
|
||||||
{
|
{
|
||||||
int result_mask = dep->result_mask;
|
int result_mask = dep->result_mask;
|
||||||
|
|
12
src/print.c
12
src/print.c
|
@ -57,6 +57,18 @@ void apk_print_indented_words(struct apk_indent *i, const char *text)
|
||||||
(apk_blob_cb) apk_print_indented, i);
|
(apk_blob_cb) apk_print_indented, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
size_t n;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, fmt);
|
||||||
|
n = vsnprintf(tmp, sizeof(tmp), fmt, va);
|
||||||
|
apk_print_indented(i, APK_BLOB_PTR_LEN(tmp, n));
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
const char *apk_error_str(int error)
|
const char *apk_error_str(int error)
|
||||||
{
|
{
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
|
|
|
@ -435,6 +435,9 @@ static int compare_providers(struct apk_solver_state *ss,
|
||||||
|
|
||||||
/* Prefer those that were in last dependency merging group */
|
/* Prefer those that were in last dependency merging group */
|
||||||
r = (int)pkgA->ss.dependencies_used - (int)pkgB->ss.dependencies_used;
|
r = (int)pkgA->ss.dependencies_used - (int)pkgB->ss.dependencies_used;
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
r = pkgB->ss.conflicts - pkgA->ss.conflicts;
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
--test-repo conflict.repo
|
--test-repo conflict.repo
|
||||||
add a b>1
|
add a b>1
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
world: b>1
|
b-2:
|
||||||
|
breaks: a-1[!b>1]
|
||||||
|
satisfies: world[b>1]
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
--test-repo complicated1.repo
|
--test-repo complicated1.repo
|
||||||
add a d>1.5
|
add a d>1.5
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
b-1: d<2.0
|
d-2.0:
|
||||||
|
breaks: b-1[d<2.0]
|
||||||
|
satisfies: world[d>1.5] c-1[d>1.0]
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
--test-repo complicated1.repo
|
--test-repo complicated1.repo
|
||||||
add a d<1.5
|
add a d<1.5
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
world: d<1.5
|
d-1.0:
|
||||||
|
breaks: c-1[d>1.0]
|
||||||
|
satisfies: world[d<1.5] b-1[d<2.0]
|
||||||
|
|
|
@ -2,5 +2,10 @@
|
||||||
--test-repo complicated1.repo
|
--test-repo complicated1.repo
|
||||||
add a !b
|
add a !b
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
a-3: b
|
d-2.0:
|
||||||
|
breaks: b-1[d<2.0]
|
||||||
|
satisfies: c-1[d>1.0]
|
||||||
|
b-1:
|
||||||
|
breaks: world[!b]
|
||||||
|
satisfies: a-3[b]
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
--test-repo complicated1.repo
|
--test-repo complicated1.repo
|
||||||
add a nonexistant
|
add a nonexistant
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
world: nonexistant
|
nonexistant (missing):
|
||||||
|
required by: world[nonexistant]
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
--test-repo complicated1.repo
|
--test-repo complicated1.repo
|
||||||
add a>2
|
add a>2
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
b-1: d<2.0
|
b-1: d<2.0
|
||||||
|
|
|
@ -4,5 +4,7 @@
|
||||||
--test-world "a@testing"
|
--test-world "a@testing"
|
||||||
add c>=3
|
add c>=3
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
c-3: not pinned: @testing
|
c-3:
|
||||||
|
masked in: testing
|
||||||
|
satisfies: world[c>=3]
|
||||||
|
|
|
@ -5,6 +5,13 @@ S:1
|
||||||
I:1
|
I:1
|
||||||
p:so:foo.so.1=1.0
|
p:so:foo.so.1=1.0
|
||||||
|
|
||||||
|
C:Q1EyN5AdpAOBJWKMR89pp/C66o+FE=
|
||||||
|
P:libfoo
|
||||||
|
V:2
|
||||||
|
S:1
|
||||||
|
I:1
|
||||||
|
p:so:foo.so.2=1.0
|
||||||
|
|
||||||
C:Q1eVpkasfqZAukAXFYbgwt4xAMZWU=
|
C:Q1eVpkasfqZAukAXFYbgwt4xAMZWU=
|
||||||
P:app
|
P:app
|
||||||
V:2
|
V:2
|
||||||
|
@ -12,6 +19,13 @@ S:1
|
||||||
I:1
|
I:1
|
||||||
D:so:foo.so.1
|
D:so:foo.so.1
|
||||||
|
|
||||||
|
C:Q1eVpsasfqZAukAXFYbgwt4xAMZWX=
|
||||||
|
P:app2
|
||||||
|
V:2
|
||||||
|
S:1
|
||||||
|
I:1
|
||||||
|
D:so:foo.so.2
|
||||||
|
|
||||||
C:Q1EyN5AdpAOBJWKMR89pp/C66FFFF=
|
C:Q1EyN5AdpAOBJWKMR89pp/C66FFFF=
|
||||||
P:mymailreader
|
P:mymailreader
|
||||||
V:1
|
V:1
|
||||||
|
@ -40,3 +54,10 @@ S:1
|
||||||
I:1
|
I:1
|
||||||
p:theservice=2
|
p:theservice=2
|
||||||
|
|
||||||
|
C:Q1eVpkasfqZAukAXFYbgwt444Edde=
|
||||||
|
P:selfconflicting
|
||||||
|
V:1
|
||||||
|
S:1
|
||||||
|
I:1
|
||||||
|
p:selfprovided=2
|
||||||
|
p:selfprovided=3
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
--test-repo provides.repo
|
--test-repo provides.repo
|
||||||
add mail-reader
|
add mail-reader
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
world: mail-reader
|
mail-reader (virtual):
|
||||||
|
provided by: mymailreader-1 mailreadplus-1
|
||||||
mail-reader is a virtual package provided by:
|
required by: world[mail-reader]
|
||||||
mymailreader-1 mailreadplus-1
|
|
||||||
|
|
|
@ -2,5 +2,10 @@
|
||||||
--test-repo provides.repo
|
--test-repo provides.repo
|
||||||
add server-a server-b
|
add server-a server-b
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable dependencies:
|
ERROR: unsatisfiable constraints:
|
||||||
world: server-a
|
server-a-1:
|
||||||
|
conflicts: server-b-1[theservice]
|
||||||
|
satisfies: world[server-a]
|
||||||
|
server-b-1:
|
||||||
|
conflicts: server-a-1[theservice]
|
||||||
|
satisfies: world[server-b]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
@ARGS
|
||||||
|
--test-repo provides.repo
|
||||||
|
add app app2
|
||||||
|
@EXPECT
|
||||||
|
ERROR: unsatisfiable constraints:
|
||||||
|
libfoo-1:
|
||||||
|
conflicts: libfoo-2
|
||||||
|
satisfies: app-2[so:foo.so.1]
|
||||||
|
libfoo-2:
|
||||||
|
conflicts: libfoo-1
|
||||||
|
satisfies: app2-2[so:foo.so.2]
|
|
@ -0,0 +1,4 @@
|
||||||
|
@ARGS
|
||||||
|
--test-repo provides.repo
|
||||||
|
add selfconflicting
|
||||||
|
@EXPECT
|
Loading…
Reference in New Issue