- use correct defaults for rpm5, put tmpspace in extra struct
[platform/upstream/libsolv.git] / src / evr.c
index ee5ec15..302c9c2 100644 (file)
--- a/src/evr.c
+++ b/src/evr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Novell Inc.
+ * Copyright (c) 2007-2009, Novell Inc.
  *
  * This program is licensed under the BSD license, read LICENSE.BSD
  * for further information
 #include "evr.h"
 #include "pool.h"
 
+
+
+#if defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
+
+#ifdef MULTI_SEMANTICS
+# define vercmp vercmp_deb
+#endif
+
+/* debian type version compare */
+int
+vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
+{
+  int r, c1, c2;
+  while (1)
+    {
+      c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
+      c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
+      if ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
+       {
+         while (c1 == '0')
+            c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
+         while (c2 == '0')
+            c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
+         r = 0;
+         while ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
+           {
+             if (!r)
+               r = c1 - c2;
+              c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
+              c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
+           }
+         if (c1 >= '0' && c1 <= '9')
+           return 1;
+         if (c2 >= '0' && c2 <= '9')
+           return -1;
+         if (r)
+           return r < 0 ? -1 : 1;
+       }
+      c1 = c1 == '~' ? -1 : !c1 || (c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'Z') || (c1 >= 'a' && c1 <= 'z')  ? c1 : c1 + 256;
+      c2 = c2 == '~' ? -1 : !c2 || (c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'Z') || (c2 >= 'a' && c2 <= 'z')  ? c2 : c2 + 256;
+      r = c1 - c2;
+      if (r)
+       return r < 0 ? -1 : 1;
+      if (!c1)
+       return 0;
+    }
+}
+
+#ifdef MULTI_SEMANTICS
+# undef vercmp
+#endif
+
+#endif
+
+#if !defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
+
+/* rpm type version compare */
+/* note: the code assumes that *q1 and *q2 are not alphanumeric! */
+
 int
 vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
 {
@@ -40,7 +99,7 @@ vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
            e1++;
          for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
            e2++;
-         r = e1 - s1 - (e2 - s2);
+         r = (e1 - s1) - (e2 - s2);
           if (!r)
            r = strncmp(s1, s2, e1 - s1);
           if (r)
@@ -52,7 +111,7 @@ vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
            e1++;
          for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
            e2++;
-         r = e1 - s1 - (e2 - s2);
+         r = (e1 - s1) - (e2 - s2);
           if (r > 0)
            {
              r = strncmp(s1, s2, e2 - s2);
@@ -73,28 +132,40 @@ vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
   return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
 }
 
+#endif
+
+#if defined(MULTI_SEMANTICS)
+# define vercmp (*(pool->disttype == DISTTYPE_DEB ? &vercmp_deb : &ver##cmp))
+#endif
 
-// edition (e:v-r) compare
+/* edition (e:v-r) compare */
 int
-evrcmp(Pool *pool, Id evr1id, Id evr2id)
+evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode)
 {
   int r;
-  const char *evr1, *evr2;
   const char *s1, *s2;
   const char *r1, *r2;
 
-  if (evr1id == evr2id)
+  if (evr1 == evr2)
     return 0;
-  evr1 = id2str(pool, evr1id);
-  evr2 = id2str(pool, evr2id);
 
 #if 0
-  POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s\n", evr1, evr2);
+  POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s mode=%d\n", evr1, evr2, mode);
 #endif
   for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
     ;
   for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
     ;
+  if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
+    {
+      /* empty epoch, skip epoch check */
+      if (*s1 == ':')
+       evr1 = s1 + 1;
+      if (*s2 == ':')
+       evr2 = s2 + 1;
+      s1 = evr1;
+      s2 = evr2;
+    }
   if (s1 == evr1 || *s1 != ':')
     s1 = 0;
   if (s2 == evr2 || *s2 != ':')
@@ -132,9 +203,22 @@ evrcmp(Pool *pool, Id evr1id, Id evr2id)
   for (s2 = evr2, r2 = 0; *s2; s2++)
     if (*s2 == '-')
       r2 = s2;
-  r = vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
+
+  r = 0;
+  if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
+    r = vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
   if (r)
     return r;
+
+  if (mode == EVRCMP_COMPARE)
+    {
+      if (!r1 && r2)
+       return -1;
+      if (r1 && !r2)
+       return 1;
+    }
+  if (mode == EVRCMP_COMPARE_EVONLY)
+    return 0;
   if (r1 && r2)
     {
       if (s1 != ++r1 && s2 != ++r2)
@@ -143,4 +227,63 @@ evrcmp(Pool *pool, Id evr1id, Id evr2id)
   return r;
 }
 
+int
+evrcmp(const Pool *pool, Id evr1id, Id evr2id, int mode)
+{
+  const char *evr1, *evr2;
+  if (evr1id == evr2id)
+    return 0;
+  evr1 = id2str(pool, evr1id);
+  evr2 = id2str(pool, evr2id);
+  return evrcmp_str(pool, evr1, evr2, mode);
+}
+
+int
+evrmatch(const Pool *pool, Id evrid, const char *epoch, const char *version, const char *release)
+{
+  const char *evr1;
+  const char *s1;
+  const char *r1;
+  int r;
+
+  evr1 = id2str(pool, evrid);
+  for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
+    ;
+  if (s1 != evr1 && *s1 == ':')
+    {
+      if (epoch)
+       {
+         r = vercmp(evr1, s1, epoch, epoch + strlen(epoch));
+         if (r)
+           return r;
+       }
+      evr1 = s1 + 1;
+    }
+  else if (epoch)
+    {
+      while (*epoch == '0')
+       epoch++;
+      if (*epoch)
+       return -1;
+    }
+  for (s1 = evr1, r1 = 0; *s1; s1++)
+    if (*s1 == '-')
+      r1 = s1;
+  if (version)
+    {
+      r = vercmp(evr1, r1 ? r1 : s1, version, version + strlen(version));
+      if (r)
+       return r;
+    }
+  if (release)
+    {
+      if (!r1)
+       return -1;
+      r = vercmp(r1 + 1, s1, release, release + strlen(release));
+      if (r)
+       return r;
+    }
+  return 0;
+}
+
 // EOF