removing unused / non-existant header
[mspang/inapt.git] / inapt.cc
index f33a5b4..7a6c056 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -8,7 +8,6 @@
 #include <set>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cachefile.h>
-#include <apt-pkg/dpkgdb.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/error.h>
 
 #include "inapt.h"
 #include "util.h"
-#include "acqprogress.h"
+#include "contrib/acqprogress.h"
 
 char *prog = NULL;
 
 static struct option opts[] = {
+    { "help", 0, NULL, 'h' },
     { "simulate", 0, NULL, 's' },
-    { "purge", 0, NULL, 'u' },
+    { "profile", 0, NULL, 'p' },
+    { "update", 0, NULL, 'l' },
+    { "upgrade", 0, NULL, 'u' },
+    { "check", 0, NULL, 'c' },
+    { "purge", 0, NULL, '!' },
+    { "clean", 0, NULL, 'e' },
+    { "option", 0, NULL, 'o' },
+    { "strict", 0, NULL, 't' },
     { NULL, 0, NULL, '\0' },
 };
 
-bool run_install(pkgCacheFile &cache) {
+static bool run_install(pkgCacheFile &cache) {
    if (_config->FindB("Inapt::Purge", false))
       for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++)
          if (!i.Purge() && cache[i].Mode == pkgDepCache::ModeDelete)
@@ -49,9 +56,11 @@ bool run_install(pkgCacheFile &cache) {
    if (_error->PendingError())
        return _error->Error("Unable to lock the download directory");
 
+   pkgAcquire Fetcher;
+
    unsigned int width = 80;
    AcqTextStatus status (width, 0);
-   pkgAcquire Fetcher (&status);
+   Fetcher.Setup(&status);
 
    pkgSourceList List;
    if (List.ReadMainList() == false)
@@ -67,11 +76,8 @@ bool run_install(pkgCacheFile &cache) {
 
   bool Failed = false;
   for (pkgAcquire::ItemIterator i = Fetcher.ItemsBegin(); i != Fetcher.ItemsEnd(); i++) {
-     if ((*i)->Status != pkgAcquire::Item::StatDone || (*i)->Complete != true) {
-         fprintf(stderr,("Failed to fetch %s  %s\n"),(*i)->DescURI().c_str(),
-                 (*i)->ErrorText.c_str());
+     if ((*i)->Status != pkgAcquire::Item::StatDone || (*i)->Complete != true)
          Failed = true;
-     }
   }
 
   if (Failed)
@@ -86,7 +92,7 @@ bool run_install(pkgCacheFile &cache) {
   return false;
 }
 
-void run_autoremove(pkgCacheFile &cache) {
+static void run_autoremove(pkgCacheFile &cache) {
     bool purge = _config->FindB("Inapt::Purge", false);
 
     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
@@ -105,9 +111,29 @@ static void usage() {
     exit(2);
 }
 
-static bool test_profile(const char *profile, std::set<std::string> *defines) {
-    return (*profile != '!' && defines->find(profile) != defines->end())
-            || (*profile == '!' && defines->find(profile + 1) == defines->end());
+static bool test_profile(const char *profile, std::set<std::string> *profiles) {
+    return (*profile != '!' && profiles->find(profile) != profiles->end())
+            || (*profile == '!' && profiles->find(profile + 1) == profiles->end());
+}
+
+static bool test_anyprofile(std::string &profile, std::set<std::string> *profiles) {
+    char *s = xstrdup(profile.c_str());
+    const char *c = strtok(s, "/");
+
+    if (test_profile(c, profiles)) {
+        free(s);
+        return true;
+    }
+
+    while ((c = strtok(NULL, "/")) != NULL) {
+        if (test_profile(c, profiles)) {
+            free(s);
+            return true;
+        }
+    }
+
+    free(s);
+    return false;
 }
 
 static pkgCache::PkgIterator eval_pkg(inapt_package *package, pkgCacheFile &cache) {
@@ -147,25 +173,30 @@ static pkgCache::PkgIterator eval_pkg(inapt_package *package, pkgCacheFile &cach
 
     if (pkg.end()) {
         if (package->alternates.size() == 1) {
-            _error->Error("%s:%d: No such package: %s", package->filename, package->linenum, package->alternates[0].c_str());
+           if (_config->FindB("Inapt::Strict", false))
+                   _error->Error("%s:%d: No such package: %s", package->filename, package->linenum, package->alternates[0].c_str());
+           else
+                   _error->Warning("%s:%d: No such package: %s", package->filename, package->linenum, package->alternates[0].c_str());
         } else {
             std::vector<std::string>::iterator i = package->alternates.begin();
             std::string message = *(i++);
             while (i != package->alternates.end()) {
-                message.append(", ");
-                message.append(*(i++));
+                message.append(", ").append(*(i++));
             }
-            _error->Error("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
+           if (_config->FindB("Inapt::Strict", false))
+                   _error->Error("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
+           else
+                   _error->Warning("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
         }
     }
 
     return pkg;
 }
 
-static bool test_profiles(vector<std::string> *profiles, std::set<std::string> *defines) {
+static bool test_profiles(vector<std::string> *test_profiles, std::set<std::string> *profiles) {
     bool ok = true;
-    for (vector<std::string>::iterator j = profiles->begin(); j < profiles->end(); j++) {
-        if (!test_profile((*j).c_str(), defines)) {
+    for (vector<std::string>::iterator j = test_profiles->begin(); j < test_profiles->end(); j++) {
+        if (!test_anyprofile(*j, profiles)) {
             ok = false;
             break;
         }
@@ -173,43 +204,43 @@ static bool test_profiles(vector<std::string> *profiles, std::set<std::string> *
     return ok;
 }
 
-static void eval_action(inapt_action *action, std::set<std::string> *defines, std::vector<inapt_package *> *final_actions) {
+static void eval_action(inapt_action *action, std::set<std::string> *profiles, std::vector<inapt_package *> *final_actions) {
     for (vector<inapt_package *>::iterator i = action->packages.begin(); i < action->packages.end(); i++) {
-        if (test_profiles(&(*i)->predicates, defines))
+        if (test_profiles(&(*i)->predicates, profiles))
             final_actions->push_back(*i);
     }
 }
 
-static void eval_block(inapt_block *block, std::set<std::string> *defines, std::vector<inapt_package *> *final_actions) {
+static void eval_block(inapt_block *block, std::set<std::string> *profiles, std::vector<inapt_package *> *final_actions) {
     if (!block)
         return;
 
     for (vector<inapt_action *>::iterator i = block->actions.begin(); i < block->actions.end(); i++)
-        if (test_profiles(&(*i)->predicates, defines))
-            eval_action(*i, defines, final_actions);
+        if (test_profiles(&(*i)->predicates, profiles))
+            eval_action(*i, profiles, final_actions);
 
     for (vector<inapt_conditional *>::iterator i = block->children.begin(); i < block->children.end(); i++) {
-        if (test_profiles(&(*i)->predicates, defines))
-            eval_block((*i)->then_block, defines, final_actions);
+        if (test_profiles(&(*i)->predicates, profiles))
+            eval_block((*i)->then_block, profiles, final_actions);
         else
-            eval_block((*i)->else_block, defines, final_actions);
+            eval_block((*i)->else_block, profiles, final_actions);
     }
 }
 
-static void eval_profiles(inapt_block *block, std::set<std::string> *defines) {
+static void eval_profiles(inapt_block *block, std::set<std::string> *profiles) {
     if (!block)
         return;
 
     for (vector<inapt_profiles *>::iterator i = block->profiles.begin(); i < block->profiles.end(); i++)
-        if (test_profiles(&(*i)->predicates, defines))
+        if (test_profiles(&(*i)->predicates, profiles))
             for (vector<std::string>::iterator j = (*i)->profiles.begin(); j != (*i)->profiles.end(); j++)
-                defines->insert(*j);
+                profiles->insert(*j);
 
     for (vector<inapt_conditional *>::iterator i = block->children.begin(); i < block->children.end(); i++) {
-        if (test_profiles(&(*i)->predicates, defines))
-            eval_profiles((*i)->then_block, defines);
+        if (test_profiles(&(*i)->predicates, profiles))
+            eval_profiles((*i)->then_block, profiles);
         else
-            eval_profiles((*i)->else_block, defines);
+            eval_profiles((*i)->else_block, profiles);
     }
 }
 
@@ -221,8 +252,8 @@ static void dump_nondownloadable(pkgCacheFile &cache) {
 
 static void dump_actions(pkgCacheFile &cache) {
     debug("inst %lu del %lu keep %lu broken %lu bad %lu",
-                   cache->InstCount(), cache->DelCount(), cache->KeepCount(),
-                   cache->BrokenCount(), cache->BadCount());
+            cache->InstCount(), cache->DelCount(), cache->KeepCount(),
+            cache->BrokenCount(), cache->BadCount());
     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
        if (cache[i].Install())
          debug("installing %s", i.Name());
@@ -240,12 +271,13 @@ static bool sanity_check(std::vector<inapt_package *> *final_actions, pkgCacheFi
     std::map<std::string, inapt_package *> packages;
 
     for (vector<inapt_package *>::iterator i = final_actions->begin(); i != final_actions->end(); i++) {
+       if ((*i)->pkg.end())
+               continue;
         if (packages.find((*i)->pkg.Name()) != packages.end()) {
             inapt_package *first = packages[(*i)->pkg.Name()];
             inapt_package *current = *i;
             _error->Error("Multiple directives for package %s at %s:%d and %s:%d",
                     (*i)->pkg.Name(), first->filename, first->linenum, current->filename, current->linenum);
-            debug("foo %s", (*i)->pkg.Name());
             okay = false;
             continue;
         }
@@ -263,13 +295,12 @@ static bool sanity_check(std::vector<inapt_package *> *final_actions, pkgCacheFi
 }
 
 static void show_breakage(pkgCacheFile &cache) {
-    fprintf(stderr, "fatal: Unable to solve dependencies\n");
-    fprintf(stderr, "The following packages are broken:");
+    std::string broken;
     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++)
         if (cache[i].NowBroken() || cache[i].InstBroken())
-            fprintf(stderr, " %s", i.Name());
-    fprintf(stderr, "\n");
-    exit(1);
+            broken.append(" ").append(i.Name());
+
+    _error->Error("Broken packages:%s", broken.c_str());
 }
 
 static void exec_actions(std::vector<inapt_package *> *final_actions) {
@@ -282,7 +313,7 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
     OpTextProgress prog;
     pkgCacheFile cache;
 
-    if (cache.Open(prog) == false)
+    if (cache.Open(&prog, true) == false)
         return;
 
     pkgDepCache::ActionGroup group (cache);
@@ -292,10 +323,13 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
 
     if (_error->PendingError())
         return;
+    _error->DumpErrors();
 
     // preliminary loop (auto-installs, includes recommends - could do this manually)
     for (vector<inapt_package *>::iterator i = final_actions->begin(); i < final_actions->end(); i++) {
         pkgCache::PkgIterator k = (*i)->pkg;
+       if (k.end())
+               continue;
         switch ((*i)->action) {
             case inapt_action::INSTALL:
                 if (!k.CurrentVer() || cache[k].Delete()) {
@@ -313,6 +347,8 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
     // secondary loop (removes package and reinstalls auto-removed packages)
     for (vector<inapt_package *>::iterator i = final_actions->begin(); i < final_actions->end(); i++) {
         pkgCache::PkgIterator k = (*i)->pkg;
+       if (k.end())
+               continue;
         switch ((*i)->action) {
             case inapt_action::INSTALL:
                 if ((!k.CurrentVer() && !cache[k].Install()) || cache[k].Delete()) {
@@ -349,8 +385,10 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
             fix.Protect((*i)->pkg);
         fix.Resolve();
 
-        if (cache->BrokenCount())
+        if (cache->BrokenCount()) {
             show_breakage(cache);
+            return;
+        }
     }
 
     cache->MarkAndSweep();
@@ -379,22 +417,22 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
     }
 }
 
-static void debug_profiles(std::set<std::string> *defines) {
-    std::string profiles = "profiles:";
+static void debug_profiles(std::set<std::string> *profiles) {
+    std::string s = "profiles:";
 
-    for (std::set<std::string>::iterator i = defines->begin(); i != defines->end(); i++) {
-        profiles.append(" ");
-        profiles.append(*i);
+    for (std::set<std::string>::iterator i = profiles->begin(); i != profiles->end(); i++) {
+        s.append(" ");
+        s.append(*i);
     }
 
-    debug("%s", profiles.c_str());
+    debug("%s", s.c_str());
 }
 
-static void auto_profiles(std::set<std::string> *defines) {
+static void auto_profiles(std::set<std::string> *profiles) {
     struct utsname uts;
     if (uname(&uts))
         fatalpe("uname");
-    defines->insert(uts.nodename);
+    profiles->insert(uts.nodename);
 }
 
 static void set_option(char *opt) {
@@ -411,25 +449,41 @@ static void set_option(char *opt) {
 int main(int argc, char *argv[]) {
     int opt;
 
-    std::set<std::string> defines;
+    std::set<std::string> profiles;
 
     prog = xstrdup(basename(argv[0]));
-    while ((opt = getopt_long(argc, argv, "p:o:sd", opts, NULL)) != -1) {
+    while ((opt = getopt_long(argc, argv, "?hp:slucedo:", opts, NULL)) != -1) {
         switch (opt) {
-            case 'p':
-                defines.insert(optarg);
-                break;
             case '?':
+            case 'h':
                 usage();
                 break;
+            case 'p':
+                profiles.insert(optarg);
+                break;
             case 's':
                 _config->Set("Inapt::Simulate", true);
                 break;
-            case 'u':
+            case '!':
                 _config->Set("Inapt::Purge", true);
                 break;
+            case 'l':
+                _config->Set("Inapt::Update", true);
+                break;
+            case 'u':
+                _config->Set("Inapt::Upgrade", true);
+                break;
+            case 'c':
+                _config->Set("Inapt::Check", true);
+                break;
+            case 'e':
+                _config->Set("Inapt::Clean", true);
+                break;
+            case 't':
+                _config->Set("Inapt::Strict", true);
+                break;
             case 'd':
-                debug_enabled = true;
+                debug_level++;
                 break;
             case 'o':
                 set_option(optarg);
@@ -450,14 +504,16 @@ int main(int argc, char *argv[]) {
     while (num_files--)
         parser(argv[optind++], &context);
 
-    auto_profiles(&defines);
-    eval_profiles(&context, &defines);
-    debug_profiles(&defines);
-    eval_block(&context, &defines, &final_actions);
+    auto_profiles(&profiles);
+    eval_profiles(&context, &profiles);
+    debug_profiles(&profiles);
+    eval_block(&context, &profiles, &final_actions);
     exec_actions(&final_actions);
 
     if (_error->PendingError()) {
-       _error->DumpErrors();
+        _error->DumpErrors();
         exit(1);
     }
+
+    return 0;
 }