Add support for simulating installation
[mspang/inapt.git] / inapt.cc
index 7ce0b01..984ca8a 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -29,28 +29,25 @@ static struct option opts[] = {
     { NULL, 0, NULL, '\0' },
 };
 
-bool run_install(pkgCacheFile &Cache,bool ShwKept = false,bool Ask = true,
-                     bool Safety = true)
-{
+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)
-            Cache->MarkDelete(i, true);
+      for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++)
+         if (!i.Purge() && cache[i].Mode == pkgDepCache::ModeDelete)
+            cache->MarkDelete(i, true);
 
-   if (Cache->BrokenCount())
+   if (cache->BrokenCount())
        fatal("broken packages during install");
 
-   if (!Cache->DelCount() && !Cache->InstCount() && !Cache->BadCount())
+   if (!cache->DelCount() && !cache->InstCount() && !cache->BadCount())
       return true;
 
-   pkgRecords Recs(Cache);
-
-   if (_error->PendingError() == true)
+   pkgRecords Recs (cache);
+   if (_error->PendingError())
       return false;
 
    FileFd Lock;
    Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-   if (_error->PendingError() == true)
+   if (_error->PendingError())
        return _error->Error(("Unable to lock the download directory"));
 
    unsigned int width = 80;
@@ -61,9 +58,9 @@ bool run_install(pkgCacheFile &Cache,bool ShwKept = false,bool Ask = true,
    if (List.ReadMainList() == false)
       return _error->Error(("The list of sources could not be read."));
 
-   SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
+   SPtr<pkgPackageManager> PM= _system->CreatePM(cache);
    if (PM->GetArchives(&Fetcher, &List, &Recs) == false ||
-       _error->PendingError() == true)
+       _error->PendingError())
       return false;
 
   if (Fetcher.Run() == pkgAcquire::Failed)
@@ -95,13 +92,13 @@ void run_autoremove(pkgCacheFile &cache)
 {
     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
         if (cache[i].Garbage) {
-            debug("garbage: %s", i.Name());
+            debug("autoremove: %s", i.Name());
             cache->MarkDelete(i, 0);
         }
     }
 
     if (cache->BrokenCount())
-        fatal("ogawd");
+        fatal("automatic removal broke packages");
 }
 
 static void usage() {
@@ -117,42 +114,41 @@ static bool test_macro(const char *macro, std::set<std::string> *defines) {
 static pkgCache::PkgIterator eval_pkg(inapt_package *package, pkgCacheFile &cache) {
     pkgCache::PkgIterator pkg;
 
-    if (!pkg.end()) fatal("omg"); /* TODO */
-
     for (std::vector<std::string>::iterator i = package->alternates.begin(); i != package->alternates.end(); i++) {
-        pkg = cache->FindPkg(*i);
+        pkgCache::PkgIterator tmp = cache->FindPkg(*i);
 
         /* no such package */
-        if (pkg.end())
+        if (tmp.end())
             continue;
 
         /* real package */
-        if (cache[pkg].CandidateVer)
+        if (cache[tmp].CandidateVer) {
+            pkg = tmp;
             break;
+        }
 
         /* virtual package */
-        if (pkg->ProvidesList) {
-            if (!pkg.ProvidesList()->NextProvides) {
-                pkgCache::PkgIterator tmp = pkg.ProvidesList().OwnerPkg();
+        if (tmp->ProvidesList) {
+            if (!tmp.ProvidesList()->NextProvides) {
+                pkgCache::PkgIterator provide = tmp.ProvidesList().OwnerPkg();
                 if (package->action == inapt_action::INSTALL) {
-                    debug("selecting %s instead of %s", tmp.Name(), pkg.Name());
-                    pkg = tmp;
+                    debug("selecting %s instead of %s", provide.Name(), tmp.Name());
+                    pkg = provide;
                     break;
                 } else {
-                    debug("will not remove %s instead of virtual package %s", tmp.Name(), pkg.Name());
+                    debug("will not remove %s instead of virtual package %s", provide.Name(), tmp.Name());
                 }
             } else {
-                debug("%s is a virtual package", pkg.Name());
+                debug("%s is a virtual package", tmp.Name());
             }
         } else {
-            debug("%s is a virtual packages with no provides", pkg.Name());
+            debug("%s is a virtual packages with no provides", tmp.Name());
         }
     }
 
     if (pkg.end()) {
-        /* todo: report all errors at the end */
         if (package->alternates.size() == 1) {
-            fatal("%s:%d: No such package: %s", package->filename, package->linenum, package->alternates[0].c_str());
+            _error->Error("%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++);
@@ -160,7 +156,7 @@ static pkgCache::PkgIterator eval_pkg(inapt_package *package, pkgCacheFile &cach
                 message.append(", ");
                 message.append(*(i++));
             }
-            fatal("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
+            _error->Error("%s:%d: No alternative available: %s", package->filename, package->linenum, message.c_str());
         }
     }
 
@@ -252,16 +248,17 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
     OpTextProgress prog;
     pkgCacheFile cache;
 
-    if (cache.Open(prog) == false) {
-       _error->DumpErrors();
-        exit(1);
-    }
+    if (cache.Open(prog) == false)
+        return;
 
     pkgDepCache::ActionGroup group (cache);
 
     for (vector<inapt_package *>::iterator i = final_actions->begin(); i != final_actions->end(); i++)
         (*i)->pkg = eval_pkg(*i, cache);
 
+    if (_error->PendingError())
+        return;
+
     for (vector<inapt_package *>::iterator i = final_actions->begin(); i < final_actions->end(); i++) {
         pkgCache::PkgIterator k = (*i)->pkg;
         switch ((*i)->action) {
@@ -312,6 +309,9 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
             fix.Protect((*i)->pkg);
         fix.Resolve();
 
+       if (_error->PendingError())
+          return;
+
         dump_actions(cache);
     }
 
@@ -320,11 +320,16 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
         run_autoremove(cache);
     }
 
-    if (!run_install(cache)) {
-       _error->DumpErrors();
-        fatal("errors");
+    if (_config->FindB("Inapt::Simulate", false)) {
+        pkgSimulate PM (cache);
+        PM.DoInstall(-1);
+        return;
     }
 
+    run_install(cache);
+    if (_error->PendingError())
+        return;
+
     if (marked) {
         if (_config->FindB("Inapt::Simulate", false)) {
             debug("marked %d packages", marked);
@@ -336,10 +341,14 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
 }
 
 static void debug_profiles(std::set<std::string> *defines) {
-    fprintf(stderr, "debug: defines: ");
-    for (std::set<std::string>::iterator i = defines->begin(); i != defines->end(); i++)
-        fprintf(stderr, "%s ", i->c_str());
-    fprintf(stderr, "\n");
+    std::string profiles = "profiles:";
+
+    for (std::set<std::string>::iterator i = defines->begin(); i != defines->end(); i++) {
+        profiles.append(" ");
+        profiles.append(*i);
+    }
+
+    debug("%s", profiles.c_str());
 }
 
 static void auto_profiles(std::set<std::string> *defines) {
@@ -355,7 +364,7 @@ int main(int argc, char *argv[]) {
     std::set<std::string> defines;
 
     prog = xstrdup(basename(argv[0]));
-    while ((opt = getopt_long(argc, argv, "p:", opts, NULL)) != -1) {
+    while ((opt = getopt_long(argc, argv, "p:s", opts, NULL)) != -1) {
         switch (opt) {
             case 'p':
                 defines.insert(optarg);
@@ -394,9 +403,7 @@ int main(int argc, char *argv[]) {
     eval_block(&context, &defines, &final_actions);
     exec_actions(&final_actions);
 
-    /* TODO: remove this */
     if (_error->PendingError()) {
-        warn("uncaught errors:");
        _error->DumpErrors();
         exit(1);
     }