opkg: run pre-install check before listing upgradable packages to ensure all
[project/opkg-lede.git] / libopkg / opkg_remove.c
index 8bf1d2a547aec176cb4003ebbc1d10dcde0561b5..c8cfb5524f7202c54af29bb2a08bd61870d01e72 100644 (file)
@@ -1,4 +1,4 @@
-/* opkg_remove.c - the itsy package management system
+/* opkg_remove.c - the opkg package management system
 
    Carl D. Worth
 
    General Public License for more details.
 */
 
-#include "opkg.h"
+#include "includes.h"
 #include "opkg_message.h"
 
 #include <glob.h>
 
 #include "opkg_remove.h"
+#include "opkg_error.h"
+#include "opkg_state.h"
 
 #include "file_util.h"
 #include "sprintf_alloc.h"
 #include "str_util.h"
 
-#include "opkg_cmd.h"
-
 /*
  * Returns number of the number of packages depending on the packages provided by this package.
  * Every package implicitly provides itself.
@@ -161,6 +161,63 @@ 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
+   */
+
+  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 = malloc (strlen (d_str) + 1);
+    if (!buffer)
+    {
+      fprintf(stderr,"%s Unable to allocate memory.\n", __FUNCTION__);
+      return -1;
+    }
+
+    while (d_str[x] != '\0' && d_str[x] != ' ')
+    {
+      buffer[x] = d_str[x];
+      ++x;
+    }
+    buffer[x] = '\0';
+    buffer = realloc (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);
+    }
+    free (buffer);
+  }
+
+  return 0;
+}
+
 int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
 {
 /* Actually, when "message == 1" I have been called from an upgrade, and not from a normal remove
@@ -170,9 +227,6 @@ int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
      int err;
      abstract_pkg_t *parent_pkg = NULL;
 
-     if (conf->autoremove)
-       printf ("autoremove is enabled, but not yet implemented\n");
-
      if (pkg->essential && !message) {
          if (conf->force_removal_of_essential_packages) {
               fprintf(stderr, "WARNING: Removing essential package %s under your coercion.\n"
@@ -217,10 +271,13 @@ int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
               free(dependents);
               if (err) return err;
          }
+          if (dependents)
+              free(dependents);
      }
 
      if ( message==0 ){
-         printf("Removing package %s from %s...\n", pkg->name, pkg->dest->name);
+         opkg_message (conf, OPKG_NOTICE,
+                      "Removing package %s from %s...\n", pkg->name, pkg->dest->name);
          fflush(stdout);
      }
      pkg->state_flag |= SF_FILELIST_CHANGED;
@@ -252,6 +309,13 @@ int opkg_remove_pkg(opkg_conf_t *conf, pkg_t *pkg,int message)
      if (parent_pkg) 
          parent_pkg->state_status = SS_NOT_INSTALLED;
 
+
+     /* remove autoinstalled packages that are orphaned by the removal of this one */
+     if (conf->autoremove)
+       remove_autoinstalled (conf, pkg);
+
+
+
      return 0;
 }
 
@@ -290,7 +354,8 @@ int remove_data_files_and_list(opkg_conf_t *conf, pkg_t *pkg)
                  this seems like a better thing to do to conserve
                  space. */
               if (conffile_has_been_modified(conf, conffile)) {
-                   printf("  not deleting modified conffile %s\n", file_name);
+                   opkg_message (conf, OPKG_NOTICE,
+                                 "  not deleting modified conffile %s\n", file_name);
                    fflush(stdout);
                    continue;
               }