Add sanity checking
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Mon, 21 Dec 2009 05:20:57 +0000 (00:20 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Tue, 22 Dec 2009 03:28:24 +0000 (22:28 -0500)
We should not attempt to both install and remove packages or remove
essential packages.

Signed-off-by: Michael Spang <mspang@csclub.uwaterloo.ca>
inapt.cc
parser.rl

index 71af2d1..f263b18 100644 (file)
--- a/inapt.cc
+++ b/inapt.cc
@@ -235,6 +235,33 @@ static void dump_actions(pkgCacheFile &cache) {
     }
 }
 
+static bool sanity_check(std::vector<inapt_package *> *final_actions, pkgCacheFile &cache) {
+    bool okay = true;
+    std::map<std::string, inapt_package *> packages;
+
+    for (vector<inapt_package *>::iterator i = final_actions->begin(); i != final_actions->end(); i++) {
+        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;
+        }
+        packages[(*i)->pkg.Name()] = *i;
+    }
+
+    for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
+        if (cache[i].Delete() && (i->Flags & pkgCache::Flag::Essential || i->Flags & pkgCache::Flag::Important)) {
+            _error->Error("Removing essential package %s", i.Name());
+            okay = false;
+        }
+    }
+
+    return okay;
+}
+
 static void show_breakage(pkgCacheFile &cache) {
     fprintf(stderr, "fatal: Unable to solve dependencies\n");
     fprintf(stderr, "The following packages are broken:");
@@ -329,6 +356,9 @@ static void exec_actions(std::vector<inapt_package *> *final_actions) {
     cache->MarkAndSweep();
     run_autoremove(cache);
 
+    if (!sanity_check(final_actions, cache))
+        return;
+
     if (_config->FindB("Inapt::Simulate", false)) {
         pkgSimulate PM (cache);
         PM.DoInstall(-1);
@@ -375,8 +405,6 @@ static void set_option(char *opt) {
     std::string option (opt, eq - opt);
     std::string value (eq + 1);
 
-    debug("setting '%s'='%s'", option.c_str(), value.c_str());
-
     _config->Set(option, value);
 }
 
index 58d6441..6e763a2 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -28,7 +28,7 @@ using namespace std;
         inapt_package *tmp_package = new inapt_package;
         tmp_package->alternates.swap(alternates);
         tmp_package->action = tmp_action->action;
-        tmp_package->linenum = curline;
+        tmp_package->linenum = curline - (*p == '\n');
         tmp_package->filename = curfile;
         tmp_package->predicates.swap(pkg_predicates);
         tmp_action->packages.push_back(tmp_package);
@@ -120,7 +120,7 @@ using namespace std;
     pkg_predicate = '@' ('!'? profile) >strstart %pkg_predicate whitespace+;
     cmd_predicate = '@' ('!'? profile) >strstart %cmd_predicate whitespace+;
     package_alternates = package_name >strstart %add_alternate ('/' package_name >strstart %add_alternate)*;
-    package_list = ((whitespace+ pkg_predicate? package_alternates)+ %add_package whitespace*);
+    package_list = ((whitespace+ pkg_predicate* package_alternates)+ %add_package whitespace*);
     profile_list = (whitespace+ profile >strstart %profile)* whitespace*;
     cmd_install = ('install' @start_install package_list ';');
     cmd_remove = ('remove' @start_remove package_list ';');
@@ -129,7 +129,7 @@ using namespace std;
     end_block = '}' @end_block;
     cmd_if = 'if' whitespace+ profile >strstart %start_conditional whitespace* start_block whitespace*
              ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
-    cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove | cmd_profiles) | cmd_if);
+    cmd = whitespace* (cmd_predicate* (cmd_install | cmd_remove | cmd_profiles) | cmd_if);
     cmd_list = cmd* whitespace* end_block?;
     main := cmd_list;
 }%%