Clean up pkg_remove_orphan_dependent() and remove_autoinstalled().
authorgraham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Fri, 20 Nov 2009 01:20:24 +0000 (01:20 +0000)
committergraham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Fri, 20 Nov 2009 01:20:24 +0000 (01:20 +0000)
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

libopkg/opkg_install.c
libopkg/opkg_remove.c

index 5e8596bfea1c83c22ab5fbb2dd3e0ee26a6b1028..e28f6b49be240850b9d36c5356d19280dba6d960 100644 (file)
@@ -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 
index 6de97a91b18c9e8a432505a573f5f8963ba67f3b..3e90836dbd49b0da4c55d944eef26ebbc4d78870 100644 (file)
@@ -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)