commit 44c141d0d050f8cc3f9311c07ddc42a0baf69092
Author: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.it>
Date:   Wed Dec 3 22:55:07 2014 +0000

    Add preference for resolving conditional dependencies
    
    Previously when parsing "Depends: A | B | C" only
    a dependency on A would be registered. This patch
    makes it possible to pass an di_slist of packages
    to be skip on such a list, ie. if a was in the
    exclude list, b would be considered, and so on.
    If both A, B and C is on the exclude list, C
    would be used anyway.
    
    This doesn't implement complete exclude support,
    but support excluding packages in that are pulled
    in via conditional dependencies.
    
    I have knownily broken the ABI for di_packages_special_read_file(),
    since accordingly to codesearch.d.n it is only
    used internally.
    
    I also have a trivial patch for cdebootstrap ready.
    
    Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.it>

diff --git a/include/debian-installer/package_internal.h b/include/debian-installer/package_internal.h
index f6357d1..a98043a 100644
--- a/include/debian-installer/package_internal.h
+++ b/include/debian-installer/package_internal.h
@@ -64,6 +64,7 @@ struct internal_di_package_parser_data
   di_packages_allocator *allocator;                     /**< the used allocator */
   di_packages *packages;                                /**< the used packages struct */
   di_package *package;                                  /**< only used in the control file parser */
+  di_slist *exclude;                                    /**< the packages to avoid */
 };
 
 /** @} */
diff --git a/include/debian-installer/packages.h b/include/debian-installer/packages.h
index 055a5f1..51a7d93 100644
--- a/include/debian-installer/packages.h
+++ b/include/debian-installer/packages.h
@@ -94,8 +94,9 @@ di_parser_info *di_packages_status_parser_info (void);
  * Read a special Packages file
  *
  * @param file file to read
+ * @param exclude packages to avoid
  */
-di_packages *di_packages_special_read_file (const char *file, di_packages_allocator *allocator, di_parser_info *(info) (void));
+di_packages *di_packages_special_read_file (const char *file, di_packages_allocator *allocator, di_parser_info *(info) (void), di_slist *exclude);
 
 /**
  * Write a special Packages file
@@ -115,7 +116,19 @@ int di_packages_special_write_file (di_packages *packages, const char *file, di_
  */
 static inline di_packages *di_packages_read_file (const char *file, di_packages_allocator *allocator)
 {
-  return di_packages_special_read_file (file, allocator, di_packages_parser_info);
+  return di_packages_special_read_file (file, allocator, di_packages_parser_info, NULL);
+}
+
+/**
+ * Read a standard Packages file while avoid certain dependencies
+ *
+ * @param file file to read
+ * @param allocator the allocator for the packages structure
+ * @param exclude packages to avoid
+ */
+static inline di_packages *di_packages_read_file_exclude (const char *file, di_packages_allocator *allocator, di_slist *exclude)
+{
+  return di_packages_special_read_file (file, allocator, di_packages_parser_info, exclude);
 }
 
 /**
@@ -126,7 +139,19 @@ static inline di_packages *di_packages_read_file (const char *file, di_packages_
  */
 static inline di_packages *di_packages_minimal_read_file (const char *file, di_packages_allocator *allocator)
 {
-  return di_packages_special_read_file (file, allocator, di_packages_minimal_parser_info);
+  return di_packages_special_read_file (file, allocator, di_packages_minimal_parser_info, NULL);
+}
+
+/**
+ * Read a minimal Packages file while avoid certain dependencies
+ *
+ * @param file file to read
+ * @param allocator the allocator for the packages structure
+ * @param exclude packages to avoid
+ */
+static inline di_packages *di_packages_minimal_read_file_exclude (const char *file, di_packages_allocator *allocator, di_slist *exclude)
+{
+  return di_packages_special_read_file (file, allocator, di_packages_minimal_parser_info, exclude);
 }
 
 /**
@@ -137,7 +162,7 @@ static inline di_packages *di_packages_minimal_read_file (const char *file, di_p
  */
 static inline di_packages *di_packages_status_read_file (const char *file, di_packages_allocator *allocator)
 {
-  return di_packages_special_read_file (file, allocator, di_packages_status_parser_info);
+  return di_packages_special_read_file (file, allocator, di_packages_status_parser_info, NULL);
 }
 
 /**
diff --git a/include/debian-installer/system/packages.h b/include/debian-installer/system/packages.h
index ef5d6cd..1e8408e 100644
--- a/include/debian-installer/system/packages.h
+++ b/include/debian-installer/system/packages.h
@@ -75,7 +75,7 @@ static inline di_package *di_system_package_read_file (const char *file, di_pack
  */
 static inline di_packages *di_system_packages_read_file (const char *file, di_packages_allocator *allocator)
 {
-  return di_packages_special_read_file (file, allocator, di_system_packages_parser_info);
+  return di_packages_special_read_file (file, allocator, di_system_packages_parser_info, NULL);
 }
 
 /**
@@ -86,7 +86,7 @@ static inline di_packages *di_system_packages_read_file (const char *file, di_pa
  */
 static inline di_packages *di_system_packages_status_read_file (const char *file, di_packages_allocator *allocator)
 {
-  return di_packages_special_read_file (file, allocator, di_system_packages_status_parser_info);
+  return di_packages_special_read_file (file, allocator, di_system_packages_status_parser_info, NULL);
 }
 
 /**
diff --git a/src/package_parser.c b/src/package_parser.c
index 6d6a5e7..eefc3e7 100644
--- a/src/package_parser.c
+++ b/src/package_parser.c
@@ -263,11 +263,15 @@ void di_package_parser_read_dependency (
   void *user_data __attribute__ ((unused)))
 {
   internal_di_package_parser_data *parser_data = user_data;
+  di_slist *exclude = parser_data->exclude;
   di_package *p = *data, *q;
   char *cur = value->string, *end = value->string + value->size;
-  char *namebegin, *fieldend;
+  char *namebegin, *fieldend, *fieldpipe;
   size_t namelen;
   di_package_dependency *d, *d1;
+  di_slist_node *exnode;
+  char *exclusion_wish;
+  int got_excluded;
 
   /*
    * basic depends line parser. can ignore versioning
@@ -278,6 +282,27 @@ void di_package_parser_read_dependency (
     namebegin = cur;
     namelen = strcspn (cur, " \t\n(,|");
 
+    /* check if the package should be excluded */
+    if (exclude != NULL) {
+      got_excluded = 0;
+      for (exnode = exclude->head; exnode; exnode = exnode->next) {
+        exclusion_wish = exnode->data;
+        if (namelen == strlen(exclusion_wish)
+            && memcmp (cur, exclusion_wish, namelen) == 0) {
+          /* is there an alternative? */
+          fieldpipe = strchr (cur, '|');
+          fieldend = cur + strcspn (cur, "\n,");
+          if (fieldpipe != NULL && fieldpipe < fieldend) {
+            /* try using the alternative */
+            while (isspace(*++fieldpipe));
+            cur = fieldpipe;
+            got_excluded = 1; break;
+          }
+        }
+      }
+      if (got_excluded) continue; /* try the alternative */
+    }
+
     d = di_package_dependency_alloc (parser_data->allocator);
 
     if (parser_data->packages)
diff --git a/src/packages_parser.c b/src/packages_parser.c
index ac5c06b..a92d387 100644
--- a/src/packages_parser.c
+++ b/src/packages_parser.c
@@ -163,11 +163,12 @@ di_parser_info *di_packages_status_parser_info (void)
  *
  * @param file file to read
  * @param info parser info
+ * @param exclude list of packages to avoid
  */
-di_packages *di_packages_special_read_file (const char *file, di_packages_allocator *allocator, di_parser_info *(get_info) (void))
+di_packages *di_packages_special_read_file (const char *file, di_packages_allocator *allocator, di_parser_info *(get_info) (void), di_slist *exclude)
 {
   di_parser_info *info = get_info ();
-  internal_di_package_parser_data data = {allocator, NULL, NULL};
+  internal_di_package_parser_data data = {allocator, NULL, NULL, exclude};
 
   data.packages = di_packages_alloc ();
 
