summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-19 20:20:24 (EST)
committer graham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-19 20:20:24 (EST)
commita6d79aecf9bb27c27e3f9fbef544e190592f24b7 (patch)
tree77307e55d3121a84a8700f406374222110290ebd
parentb6c404659768c0be9d4d7b93a8d475c76ee26380 (diff)
Clean up pkg_remove_orphan_dependent() and remove_autoinstalled().
This is motivated by a desire to remove usage of depends_str, but fixes real problems with these functions as a side effect. pkg_remove_orphan_dependent() works as advertised now. git-svn-id: http://opkg.googlecode.com/svn/trunk@341 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358
-rw-r--r--libopkg/opkg_install.c128
-rw-r--r--libopkg/opkg_remove.c100
2 files changed, 128 insertions, 100 deletions
diff --git a/libopkg/opkg_install.c b/libopkg/opkg_install.c
index 5e8596b..e28f6b4 100644
--- a/libopkg/opkg_install.c
+++ b/libopkg/opkg_install.c
@@ -573,56 +573,83 @@ static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg)
return 0;
}
-static int pkg_remove_orphan_dependent(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
+/*
+ * Remove packages which were auto_installed due to a dependency by old_pkg,
+ * which are no longer a dependency in the new (upgraded) pkg.
+ */
+static int
+pkg_remove_orphan_dependent(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg)
{
- int i, j, found;
- char *buf, *d_str;
- pkg_t *p;
-
- if (!old_pkg)
- return 0;
-
- if (old_pkg->depends_count == 0)
- return 0;
-
- for (i=0;i<old_pkg->depends_count;i++) {
- found = 0;
- for (j=0;j<pkg->depends_count;j++) {
- if (!strcmp(old_pkg->depends_str[i], pkg->depends_str[j])) {
- found = 1;
- break;
- }
- }
- if (found)
- continue;
- d_str = old_pkg->depends_str[i];
- buf = xcalloc(1, strlen (d_str) + 1);
- j=0;
- while (d_str[j] != '\0' && d_str[j] != ' ') {
- buf[j]=d_str[j];
- ++j;
- }
- buf[j]='\0';
- buf = xrealloc (buf, strlen (buf) + 1);
- p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash, buf);
- if (!p) {
- fprintf(stderr, "The pkg %s had been removed!!\n", buf);
- free(buf);
- continue;
- }
- if (p->auto_installed) {
- int deps;
- abstract_pkg_t **dependents;
- deps = pkg_has_installed_dependents(conf, NULL, p, &dependents);
- if (deps == 0) {
- opkg_message (conf, OPKG_NOTICE,"%s was autoinstalled but is now orphaned, remove it.\n", buf);
- opkg_remove_pkg(conf, p, 0);
- } else
- opkg_message (conf, OPKG_INFO, "%s was autoinstalled and is still required by %d installed packages\n", buf, deps);
- }
- free(buf);
- }
- return 0;
+ int i, j, k, l, found;
+ int n_deps;
+ pkg_t *p;
+ struct compound_depend *cd0, *cd1;
+ abstract_pkg_t **dependents;
+
+ for (i=0; i<old_pkg->depends_count; i++) {
+ cd0 = &old_pkg->depends[i];
+ if (cd0->type != DEPEND)
+ continue;
+ for (j=0; j<cd0->possibility_count; j++) {
+
+ found = 0;
+
+ for (k=0; k<pkg->depends_count; k++) {
+ cd1 = &pkg->depends[i];
+ if (cd1->type != DEPEND)
+ continue;
+ for (l=0; l<cd1->possibility_count; l++) {
+ if (cd0->possibilities[j]
+ == cd1->possibilities[l]) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ if (found)
+ continue;
+
+ /*
+ * old_pkg has a dependency that pkg does not.
+ */
+ p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash,
+ cd0->possibilities[j]->pkg->name);
+
+ if (!p)
+ continue;
+
+ if (!p->auto_installed)
+ continue;
+
+ n_deps = pkg_has_installed_dependents(conf, NULL, p,
+ &dependents);
+ n_deps--; /* don't count old_pkg */
+
+ if (n_deps == 0) {
+ opkg_message (conf, OPKG_NOTICE,
+ "%s was autoinstalled and is "
+ "now orphaned, removing.\n",
+ p->name);
+
+ /* p has one installed dependency (old_pkg),
+ * which we need to ignore during removal. */
+ p->state_flag |= SF_REPLACE;
+
+ opkg_remove_pkg(conf, p, 0);
+ } else
+ opkg_message(conf, OPKG_INFO,
+ "%s was autoinstalled and is "
+ "still required by %d "
+ "installed packages.\n",
+ p->name, n_deps);
+
+ }
+ }
+
+ return 0;
}
/* returns number of installed replacees */
@@ -923,7 +950,8 @@ int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
opkg_state_changed++;
pkg->state_flag |= SF_FILELIST_CHANGED;
- pkg_remove_orphan_dependent(conf, pkg, old_pkg);
+ if (old_pkg)
+ pkg_remove_orphan_dependent(conf, pkg, old_pkg);
/* XXX: BUG: we really should treat replacement more like an upgrade
* Instead, we're going to remove the replacees
diff --git a/libopkg/opkg_remove.c b/libopkg/opkg_remove.c
index 6de97a9..3e90836 100644
--- a/libopkg/opkg_remove.c
+++ b/libopkg/opkg_remove.c
@@ -163,58 +163,58 @@ static int user_prefers_removing_dependents(opkg_conf_t *conf, abstract_pkg_t *a
return 0;
}
-static int remove_autoinstalled (opkg_conf_t *conf, pkg_t *pkg)
+/*
+ * Find and remove packages that were autoinstalled and are orphaned
+ * by the removal of pkg.
+ */
+static int
+remove_autoinstalled(opkg_conf_t *conf, pkg_t *pkg)
{
- /*
- * find and remove packages that were autoinstalled and are orphaned by the removal of pkg
- */
-
- char *buffer, *d_str;
- int i;
-
- for (i = 0; i < pkg->depends_count; ++i)
- {
- int x = 0;
- pkg_t *p;
- d_str = pkg->depends_str[i];
- buffer = xcalloc(1, strlen (d_str) + 1);
-
- while (d_str[x] != '\0' && d_str[x] != ' ')
- {
- buffer[x] = d_str[x];
- ++x;
- }
- buffer[x] = '\0';
- buffer = xrealloc (buffer, strlen (buffer) + 1);
- p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash, buffer);
-
- /* if the package is not installed, this could have been a circular
- * depenancy and the package has already been removed */
- if (!p)
- return -1;
-
- if (p->auto_installed)
- {
- int deps;
- abstract_pkg_t **dependents;
-
- deps = pkg_has_installed_dependents(conf, NULL, p, &dependents);
- if (deps == 0)
- {
- opkg_message (conf, OPKG_INFO,
- "%s was autoinstalled but is now orphaned\n", buffer);
- opkg_remove_pkg(conf, p,0);
- }
- else
- opkg_message (conf, OPKG_INFO, "%s was autoinstalled and is still required by "
- "%d installed packages\n", buffer, deps);
- if (dependents)
- free(dependents);
- }
- free (buffer);
- }
+ int i, j;
+ int n_deps;
+ pkg_t *p;
+ struct compound_depend *cdep;
+ abstract_pkg_t **dependents;
+
+ for (i=0; i<pkg->depends_count; i++) {
+ cdep = &pkg->depends[i];
+ if (cdep->type != DEPEND)
+ continue;
+ for (j=0; j<cdep->possibility_count; j++) {
+ p = pkg_hash_fetch_installed_by_name (&conf->pkg_hash,
+ cdep->possibilities[j]->pkg->name);
+
+ /* If the package is not installed, this could have
+ * been a circular dependency and the package has
+ * already been removed.
+ */
+ if (!p)
+ return -1;
+
+ if (!p->auto_installed)
+ continue;
+
+ n_deps = pkg_has_installed_dependents(conf, NULL, p,
+ &dependents);
+ if (n_deps == 0) {
+ opkg_message(conf, OPKG_NOTICE,
+ "%s was autoinstalled and is "
+ "now orphaned, removing\n",
+ p->name);
+ opkg_remove_pkg(conf, p, 0);
+ } else
+ opkg_message(conf, OPKG_INFO,
+ "%s was autoinstalled and is "
+ "still required by %d "
+ "installed packages.\n",
+ p->name, n_deps);
+
+ if (dependents)
+ free(dependents);
+ }
+ }
- return 0;
+ return 0;
}
int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)