Should fix rhbz#896090 while NOT breaking rhbz#730887

-- 
vda

diff -x '*.po' -d -urpN libreport.0/src/lib/parse_release.c 
libreport.1/src/lib/parse_release.c
--- libreport.0/src/lib/parse_release.c 2013-01-10 14:18:05.000000000 +0100
+++ libreport.1/src/lib/parse_release.c 2013-01-23 16:32:46.558850018 +0100
@@ -18,8 +18,34 @@
 */
 #include "internal_libreport.h"

+/* Houston, we have a problem.
+ *
+ * Mapping from OS release string to (product,version) string tuple
+ * in different bug databases is non-trivial, and differs from DB to DB.
+ * OTOH, it does have a lot of similarities too, making it worthwhile
+ * to use a common function for parsing.
+ *
+ * To accomodate this, parse_release() takes a flag parameter
+ * with two types of bits:
+ *
+ * - some bits indicate a specific tweak to parsing algorithm (such as
+ *   "remove everything after numeric version").
+ *
+ * - if there is a bug DB which requires a quirk not easily describable
+ *   by a combination of aforementioned bits, it gets its own bit
+ *   "parse OS release for bug database XYZ" (so far we have none).
+ *
+ * In order to not torture API users with the need to know these bits,
+ * we have convenience functions parse_release_for_XYZ()
+ * which call parse_release() with correct bits.
+ */
+enum {
+    APPEND_MAJOR_VER_TO_RHEL_PRODUCT = 1 << 0,
+    RETAIN_ALPHA_BETA_TAIL_IN_VER    = 1 << 1,
+};
+
 // caller is reposible for freeing *product* and *version*
-static void parse_release(const char *release, char** product, char** version, 
bool append_rhel_version)
+static void parse_release(const char *release, char** product, char** version, 
int flags)
 {
     if (strstr(release, "Rawhide"))
     {
@@ -29,21 +55,29 @@ static void parse_release(const char *re
         return;
     }

+    bool it_is_rhel = false;
+
     struct strbuf *buf_product = strbuf_new();
     if (strstr(release, "Fedora"))
+    {
         strbuf_append_str(buf_product, "Fedora");
+    }
     else if (strstr(release, "Red Hat Enterprise Linux"))
+    {
         strbuf_append_str(buf_product, "Red Hat Enterprise Linux");
+        it_is_rhel = true;
+    }
     else
     {
         /* TODO: add logic for parsing other distros' names here */
         strbuf_append_str(buf_product, release);
     }

-    /* examples of release strings:
-     * installed system: Red Hat Enterprise Linux Server release 6.2 Beta 
(Santiago)
-     * anaconda: Red Hat Enterprise Linux 6.2
+    /* Examples of release strings:
+     * installed system: "Red Hat Enterprise Linux Server release 6.2 Beta 
(Santiago)"
+     * anaconda: "Red Hat Enterprise Linux 6.2"
      */
+    struct strbuf *buf_version = strbuf_new();
     const char *r = strstr(release, "release");
     const char *space = r ? strchr(r, ' ') : NULL;
     if (!space)
@@ -57,25 +91,48 @@ static void parse_release(const char *re
             space++;
         }
     }
-
-    struct strbuf *buf_version = strbuf_new();
     if (space)
     {
         space++;
         /* observed also: "Fedora F16-Alpha" rhbz#730887 */
-        while (isdigit(*space) || *space == '.')
+        while ((*space >= '0' && *space <= '9') || *space == '.')
         {
             /* Eat string like "5.2" */
             strbuf_append_char(buf_version, *space);
-            if (append_rhel_version
-             && strcmp(buf_product->buf, "Red Hat Enterprise Linux") == 0
-            ) {
-                strbuf_append_char(buf_product, ' ');
-                strbuf_append_char(buf_product, *space);
-            }
-            append_rhel_version = false;
             space++;
         }
+
+        if (flags & RETAIN_ALPHA_BETA_TAIL_IN_VER)
+        {
+            /* Example: "... 6.2 [Beta ](Santiago)".
+             * 'space' variable points to non-digit char after "2".
+             * We assume that non-parenthesized text is "Alpha"/"Beta"/etc.
+             * If this text is only whitespace, we won't append it.
+             */
+            const char *to_append = space;
+            while (*space && *space != '(') /* go to '(' */
+                space++;
+            while (space > to_append && space[-1] == ' ') /* back to 1st 
non-space */
+                space--;
+            strbuf_append_strf(buf_version, "%.*s", (int)(space - to_append), 
to_append);
+        }
+    }
+
+    if ((flags & APPEND_MAJOR_VER_TO_RHEL_PRODUCT) && it_is_rhel)
+    {
+        char *v = buf_version->buf;
+
+        /* Append "integer part" of version to product:
+         * "10.2<anything>" -> append " 10"
+         * "10 <anything>"  -> append " 10"
+         * "10"             -> append " 10"
+         * "10abcde"        -> append ?????
+         */
+        unsigned idx_dot = strchrnul(v, '.') - v;
+        unsigned idx_space = strchrnul(v, ' ') - v;
+        strbuf_append_strf(buf_product, " %.*s",
+                        (idx_dot < idx_space ? idx_dot : idx_space), v
+        );
     }

     *version = strbuf_free_nobuf(buf_version);
@@ -86,12 +143,43 @@ static void parse_release(const char *re

 void parse_release_for_bz(const char *release, char** product, char** version)
 {
-    /* Fedora/RH bugzilla uses "Red Hat Enterprise Linux N" product RHEL */
-    parse_release(release, product, version, /*append_rhel_version:*/ true);
+    /* Fedora/RH bugzilla uses "Red Hat Enterprise Linux N" product for RHEL */
+    parse_release(release, product, version, 0
+        | APPEND_MAJOR_VER_TO_RHEL_PRODUCT
+    );
 }

+/*
+ * Note to developers: you can use
+ * curl --silent -u $USER:$PASS 
"https://api.access.redhat.com/rs/products/Red%20Hat%20Enterprise%20Linux/versions";
 | xmllint --format -
+ * to query RHTS for valid set of versions. Currently (2013-01) I get:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * <versions xmlns="http://www.redhat.com/gss/strata";>
+ *   <version>3 - ELS</version>
+ *   <version>4</version>
+ *   <version>4 - ELS</version>
+ *   <version>5.0</version>
+ *   <version>5.1</version>
+ *   <version>5.2</version>
+ *   <version>5.3</version>
+ *   <version>5.4</version>
+ *   <version>5.5</version>
+ *   <version>5.6</version>
+ *   <version>5.7</version>
+ *   <version>5.8</version>
+ *   <version>5.9</version>
+ *   <version>6.0</version>
+ *   <version>6.1</version>
+ *   <version>6.2</version>
+ *   <version>6.3</version>
+ *   <version>6.4 Beta</version>
+ *   <version>7.0 Alpha-2</version>
+ *   <version>Unknown</version>
+ * </versions>
+ */
 void parse_release_for_rhts(const char *release, char** product, char** 
version)
 {
-    /* RHTS uses "Red Hat Enterprise Linux" product for RHEL */
-    parse_release(release, product, version, /*append_rhel_version:*/ false);
+    parse_release(release, product, version, 0
+        | RETAIN_ALPHA_BETA_TAIL_IN_VER
+    );
 }
diff -x '*.po' -d -urpN libreport.0/tests/osrelease.at 
libreport.1/tests/osrelease.at
--- libreport.0/tests/osrelease.at      2013-01-10 14:18:05.000000000 +0100
+++ libreport.1/tests/osrelease.at      2013-01-23 16:52:05.136844531 +0100
@@ -113,7 +113,8 @@ int main(void)
 {
     char *releases_good[7][3] =
     {
-        {"Red Hat Enterprise Linux Server release 6.2 Beta (Santiago)", "Red 
Hat Enterprise Linux", "6.2"},
+        {"Red Hat Enterprise Linux Server release 6.2 Beta (Santiago)", "Red 
Hat Enterprise Linux", "6.2 Beta"},
+        {"Red Hat Enterprise Linux Server release 6.2 (Santiago)", "Red Hat 
Enterprise Linux", "6.2"},
         {"Red Hat Enterprise Linux 6.2", "Red Hat Enterprise Linux", "6.2"},
     };

Reply via email to