state, info: implement install_if (fixes #443)
Implement the logic for install_if lines. Update info applet to also display the install_if related fields.cute-signatures
parent
9eeb95470b
commit
0f6475b884
80
src/info.c
80
src/info.c
|
@ -33,6 +33,8 @@ struct info_ctx {
|
|||
#define APK_INFO_RDEPENDS 0x10
|
||||
#define APK_INFO_CONTENTS 0x20
|
||||
#define APK_INFO_TRIGGERS 0x40
|
||||
#define APK_INFO_INSTALL_IF 0x80
|
||||
#define APK_INFO_RINSTALL_IF 0x100
|
||||
|
||||
static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity)
|
||||
{
|
||||
|
@ -168,15 +170,22 @@ static void info_print_size(struct apk_package *pkg)
|
|||
|
||||
static void info_print_depends(struct apk_package *pkg)
|
||||
{
|
||||
apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
|
||||
char dep[256];
|
||||
int i;
|
||||
char *separator = apk_verbosity > 1 ? " " : "\n";
|
||||
|
||||
if (apk_verbosity == 1)
|
||||
printf(PKG_VER_FMT " depends on:\n",
|
||||
PKG_VER_PRINTF(pkg));
|
||||
if (apk_verbosity > 1)
|
||||
printf("%s: ", pkg->name->name);
|
||||
for (i = 0; i < pkg->depends->num; i++)
|
||||
printf("%s%s", pkg->depends->item[i].name->name, separator);
|
||||
for (i = 0; i < pkg->depends->num; i++) {
|
||||
apk_blob_t b = APK_BLOB_BUF(dep);
|
||||
apk_blob_push_dep(&b, &pkg->depends->item[i]);
|
||||
apk_blob_push_blob(&b, separator);
|
||||
b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
|
||||
fwrite(b.ptr, b.len, 1, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
static void info_print_required_by(struct apk_package *pkg)
|
||||
|
@ -211,6 +220,58 @@ static void info_print_required_by(struct apk_package *pkg)
|
|||
}
|
||||
}
|
||||
|
||||
static void info_print_install_if(struct apk_package *pkg)
|
||||
{
|
||||
apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
|
||||
char dep[256];
|
||||
int i;
|
||||
|
||||
if (apk_verbosity == 1)
|
||||
printf(PKG_VER_FMT " has auto-install rule:\n",
|
||||
PKG_VER_PRINTF(pkg));
|
||||
if (apk_verbosity > 1)
|
||||
printf("%s: ", pkg->name->name);
|
||||
for (i = 0; i < pkg->install_if->num; i++) {
|
||||
apk_blob_t b = APK_BLOB_BUF(dep);
|
||||
apk_blob_push_dep(&b, &pkg->install_if->item[i]);
|
||||
apk_blob_push_blob(&b, separator);
|
||||
b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
|
||||
fwrite(b.ptr, b.len, 1, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
static void info_print_rinstall_if(struct apk_package *pkg)
|
||||
{
|
||||
int i, j, k;
|
||||
char *separator = apk_verbosity > 1 ? " " : "\n";
|
||||
|
||||
if (apk_verbosity == 1)
|
||||
printf(PKG_VER_FMT " affects auto-installation of:\n",
|
||||
PKG_VER_PRINTF(pkg));
|
||||
if (apk_verbosity > 1)
|
||||
printf("%s: ", pkg->name->name);
|
||||
for (i = 0; i < pkg->name->rinstall_if->num; i++) {
|
||||
struct apk_name *name0 = pkg->name->rinstall_if->item[i];
|
||||
|
||||
/* Check only the package that is installed, and that
|
||||
* it actually has this package in install_if. */
|
||||
for (j = 0; j < name0->pkgs->num; j++) {
|
||||
struct apk_package *pkg0 = name0->pkgs->item[j];
|
||||
|
||||
if (pkg0->ipkg == NULL)
|
||||
continue;
|
||||
for (k = 0; k < pkg0->install_if->num; k++) {
|
||||
if (pkg0->install_if->item[k].name != pkg->name)
|
||||
continue;
|
||||
printf(PKG_VER_FMT "%s",
|
||||
PKG_VER_PRINTF(pkg0),
|
||||
separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void info_print_contents(struct apk_package *pkg)
|
||||
{
|
||||
struct apk_installed_package *ipkg = pkg->ipkg;
|
||||
|
@ -260,9 +321,12 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg)
|
|||
info_print_required_by,
|
||||
info_print_contents,
|
||||
info_print_triggers,
|
||||
info_print_install_if,
|
||||
info_print_rinstall_if,
|
||||
};
|
||||
const int requireipkg =
|
||||
APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS;
|
||||
APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS |
|
||||
APK_INFO_RINSTALL_IF;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(subactions); i++) {
|
||||
|
@ -317,6 +381,12 @@ static int info_parse(void *ctx, struct apk_db_options *dbopts,
|
|||
case 'r':
|
||||
ictx->subaction_mask |= APK_INFO_RDEPENDS;
|
||||
break;
|
||||
case 'I':
|
||||
ictx->subaction_mask |= APK_INFO_INSTALL_IF;
|
||||
break;
|
||||
case 'i':
|
||||
ictx->subaction_mask |= APK_INFO_RINSTALL_IF;
|
||||
break;
|
||||
case 's':
|
||||
ictx->subaction_mask |= APK_INFO_SIZE;
|
||||
break;
|
||||
|
@ -354,6 +424,8 @@ static struct apk_option info_options[] = {
|
|||
{ 'W', "who-owns", "Print the package owning the specified file" },
|
||||
{ 'R', "depends", "List packages that the PACKAGE depends on" },
|
||||
{ 'r', "rdepends", "List all packages depending on PACKAGE" },
|
||||
{ 'i', "install-if", "List the PACKAGE's install-if rule" },
|
||||
{ 'I', "rinstall-if", "List all packages having install-if referencing PACKAGE" },
|
||||
{ 'w', "webpage", "Show URL for more information about PACKAGE" },
|
||||
{ 's', "size", "Show installed size of PACKAGE" },
|
||||
{ 'd', "description", "Print description for PACKAGE" },
|
||||
|
|
165
src/state.c
165
src/state.c
|
@ -238,6 +238,50 @@ void apk_state_unref(struct apk_state *state)
|
|||
free(state);
|
||||
}
|
||||
|
||||
static struct apk_package *get_locked_or_installed_package(
|
||||
struct apk_state *state,
|
||||
struct apk_name *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ns_locked(state->name[name->id]))
|
||||
return ns_to_pkg(state->name[name->id]);
|
||||
|
||||
if (!ns_empty(state->name[name->id])) {
|
||||
struct apk_name_choices *ns =
|
||||
ns_to_choices(state->name[name->id]);
|
||||
|
||||
for (i = 0; i < ns->num; i++) {
|
||||
if (ns->pkgs[i]->ipkg != NULL)
|
||||
return ns->pkgs[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < name->pkgs->num; i++) {
|
||||
if (name->pkgs->item[i]->ipkg != NULL)
|
||||
return name->pkgs->item[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int check_dependency_array(struct apk_state *state,
|
||||
struct apk_dependency_array *da)
|
||||
{
|
||||
struct apk_package *pkg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < da->num; i++) {
|
||||
pkg = get_locked_or_installed_package(state, da->item[i].name);
|
||||
if (pkg == NULL && da->item[i].result_mask != APK_DEPMASK_CONFLICT)
|
||||
return 0;
|
||||
if (!apk_dep_is_satisfied(&da->item[i], pkg))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return da->num;
|
||||
}
|
||||
|
||||
static int apk_state_add_change(struct apk_state *state,
|
||||
struct apk_package *oldpkg,
|
||||
struct apk_package *newpkg)
|
||||
|
@ -340,20 +384,22 @@ int apk_state_prune_dependency(struct apk_state *state,
|
|||
return c->num;
|
||||
}
|
||||
|
||||
int apk_state_lock_dependency(struct apk_state *state,
|
||||
struct apk_dependency *dep)
|
||||
int apk_state_autolock_name(struct apk_state *state, struct apk_name *name,
|
||||
int install_if)
|
||||
{
|
||||
struct apk_name *name = dep->name;
|
||||
struct apk_name_choices *c;
|
||||
struct apk_package *installed = NULL, *latest = NULL, *use;
|
||||
int i, r;
|
||||
|
||||
r = apk_state_prune_dependency(state, dep);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
struct apk_package *installed = NULL, *latest = NULL, *use;
|
||||
int i;
|
||||
|
||||
if (ns_pending(state->name[name->id]))
|
||||
return apk_state_lock_name(state, name, ns_to_pkg(state->name[name->id]));
|
||||
if (ns_locked(state->name[name->id]))
|
||||
return 0;
|
||||
if (ns_empty(state->name[name->id])) {
|
||||
/* This name has not been visited yet.
|
||||
* Construct list of candidates. */
|
||||
state->name[name->id] = ns_from_choices(name_choices_new(state->db, name));
|
||||
}
|
||||
|
||||
c = ns_to_choices(state->name[name->id]);
|
||||
#if 1
|
||||
|
@ -361,6 +407,10 @@ int apk_state_lock_dependency(struct apk_state *state,
|
|||
for (i = 0; i < c->num; i++) {
|
||||
struct apk_package *pkg = c->pkgs[i];
|
||||
|
||||
if (install_if &&
|
||||
!check_dependency_array(state, pkg->install_if))
|
||||
continue;
|
||||
|
||||
if (pkg->ipkg != NULL)
|
||||
installed = pkg;
|
||||
else if (!apk_state_pkg_available(state, pkg))
|
||||
|
@ -402,7 +452,7 @@ int apk_state_lock_dependency(struct apk_state *state,
|
|||
use = latest;
|
||||
}
|
||||
if (use == NULL)
|
||||
return -1;
|
||||
return -2;
|
||||
|
||||
return apk_state_lock_name(state, name, use);
|
||||
#else
|
||||
|
@ -417,6 +467,18 @@ int apk_state_lock_dependency(struct apk_state *state,
|
|||
#endif
|
||||
}
|
||||
|
||||
int apk_state_lock_dependency(struct apk_state *state,
|
||||
struct apk_dependency *dep)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = apk_state_prune_dependency(state, dep);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
return apk_state_autolock_name(state, dep->name, FALSE);
|
||||
}
|
||||
|
||||
static int apk_state_fix_package(struct apk_state *state,
|
||||
struct apk_package *pkg)
|
||||
{
|
||||
|
@ -438,7 +500,6 @@ static int apk_state_fix_package(struct apk_state *state,
|
|||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -480,48 +541,19 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
|
|||
void *ctx)
|
||||
{
|
||||
struct apk_package *pkg0;
|
||||
int i, j, r;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < name->rdepends->num; i++) {
|
||||
struct apk_name *name0 = name->rdepends->item[i];
|
||||
|
||||
if (ns_locked(state->name[name0->id])) {
|
||||
pkg0 = ns_to_pkg(state->name[name0->id]);
|
||||
if (pkg0 == NULL)
|
||||
continue;
|
||||
r = call_if_dependency_broke(state, pkg0, name,
|
||||
cb, ctx);
|
||||
if (r != 0)
|
||||
return r;
|
||||
} else if (!ns_empty(state->name[name0->id])) {
|
||||
struct apk_name_choices *ns =
|
||||
ns_to_choices(state->name[name0->id]);
|
||||
pkg0 = get_locked_or_installed_package(state, name0);
|
||||
if (pkg0 == NULL)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < ns->num; j++) {
|
||||
if (ns->pkgs[j]->ipkg == NULL)
|
||||
continue;
|
||||
r = call_if_dependency_broke(state,
|
||||
ns->pkgs[j],
|
||||
name, cb, ctx);
|
||||
if (r != 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < name0->pkgs->num; j++) {
|
||||
pkg0 = name0->pkgs->item[j];
|
||||
|
||||
if (pkg0->ipkg == NULL)
|
||||
continue;
|
||||
|
||||
r = call_if_dependency_broke(state,
|
||||
name0->pkgs->item[j],
|
||||
name, cb, ctx);
|
||||
if (r != 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
r = call_if_dependency_broke(state, pkg0, name,
|
||||
cb, ctx);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -591,15 +623,19 @@ int apk_state_lock_name(struct apk_state *state,
|
|||
}
|
||||
|
||||
/* If the chosen package is installed, all is done here */
|
||||
if (oldpkg == newpkg &&
|
||||
(newpkg == NULL ||
|
||||
!(newpkg->name->flags & APK_NAME_REINSTALL)))
|
||||
return 0;
|
||||
if ((oldpkg != newpkg) ||
|
||||
(newpkg != NULL && (newpkg->name->flags & APK_NAME_REINSTALL))) {
|
||||
/* Track change */
|
||||
r = apk_state_add_change(state, oldpkg, newpkg);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Track change */
|
||||
r = apk_state_add_change(state, oldpkg, newpkg);
|
||||
if (r != 0)
|
||||
return r;
|
||||
/* Check all reverse install_if's */
|
||||
if (newpkg != NULL) {
|
||||
for (i = 0; i < newpkg->name->rinstall_if->num; i++)
|
||||
apk_state_autolock_name(state, newpkg->name->rinstall_if->item[i], TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -809,6 +845,23 @@ static int apk_state_autoclean(struct apk_state *state,
|
|||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pkg->name->rinstall_if->num; i++) {
|
||||
struct apk_name *n = pkg->name->rinstall_if->item[i];
|
||||
|
||||
if (ns_locked(state->name[n->id]))
|
||||
continue;
|
||||
if (n->flags & APK_NAME_TOPLEVEL)
|
||||
continue;
|
||||
|
||||
r = apk_state_autolock_name(state, n, TRUE);
|
||||
if (r == -2) {
|
||||
r = apk_state_lock_name(state, n, NULL);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue