2 * Copyright (c) 2007-2009, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
21 #if defined(DEBIAN) || defined(MULTI_SEMANTICS)
23 /* debian type version compare */
25 solv_vercmp_deb(const char *s1, const char *q1, const char *s2, const char *q2)
30 c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
31 c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
32 if ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
35 c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
37 c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
39 while ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
43 c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
44 c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
46 if (c1 >= '0' && c1 <= '9')
48 if (c2 >= '0' && c2 <= '9')
51 return r < 0 ? -1 : 1;
53 c1 = c1 == '~' ? -1 : !c1 || (c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'Z') || (c1 >= 'a' && c1 <= 'z') ? c1 : c1 + 256;
54 c2 = c2 == '~' ? -1 : !c2 || (c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'Z') || (c2 >= 'a' && c2 <= 'z') ? c2 : c2 + 256;
57 return r < 0 ? -1 : 1;
65 #if !defined(DEBIAN) || defined(MULTI_SEMANTICS)
67 /* rpm type version compare */
68 /* note: the code assumes that *q1 and *q2 are not alphanumeric! */
71 solv_vercmp_rpm(const char *s1, const char *q1, const char *s2, const char *q2)
78 while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') &&
79 !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z') && *s1 != '~')
81 while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') &&
82 !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z') && *s2 != '~')
84 if (s1 < q1 && *s1 == '~')
86 if (s2 < q2 && *s2 == '~')
94 if (s2 < q2 && *s2 == '~')
96 if (s1 >= q1 || s2 >= q2)
98 if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9'))
100 while (*s1 == '0' && s1[1] >= '0' && s1[1] <= '9')
102 while (*s2 == '0' && s2[1] >= '0' && s2[1] <= '9')
104 for (e1 = s1; *e1 >= '0' && *e1 <= '9'; )
106 for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
108 r = (e1 - s1) - (e2 - s2);
110 r = strncmp(s1, s2, e1 - s1);
112 return r > 0 ? 1 : -1;
116 for (e1 = s1; (*e1 >= 'a' && *e1 <= 'z') || (*e1 >= 'A' && *e1 <= 'Z'); )
118 for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
120 r = (e1 - s1) - (e2 - s2);
123 r = strncmp(s1, s2, e2 - s2);
124 return r >= 0 ? 1 : -1;
128 r = strncmp(s1, s2, e1 - s1);
129 return r <= 0 ? -1 : 1;
131 r = strncmp(s1, s2, e1 - s1);
133 return r > 0 ? 1 : -1;
138 return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
142 solv_vercmp_rpm_notilde(const char *s1, const char *q1, const char *s2, const char *q2)
147 while (s1 < q1 && s2 < q2)
149 while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') &&
150 !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z'))
152 while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') &&
153 !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z'))
155 if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9'))
157 while (*s1 == '0' && s1[1] >= '0' && s1[1] <= '9')
159 while (*s2 == '0' && s2[1] >= '0' && s2[1] <= '9')
161 for (e1 = s1; *e1 >= '0' && *e1 <= '9'; )
163 for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
165 r = (e1 - s1) - (e2 - s2);
167 r = strncmp(s1, s2, e1 - s1);
169 return r > 0 ? 1 : -1;
173 for (e1 = s1; (*e1 >= 'a' && *e1 <= 'z') || (*e1 >= 'A' && *e1 <= 'Z'); )
175 for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
177 r = (e1 - s1) - (e2 - s2);
180 r = strncmp(s1, s2, e2 - s2);
181 return r >= 0 ? 1 : -1;
185 r = strncmp(s1, s2, e1 - s1);
186 return r <= 0 ? -1 : 1;
188 r = strncmp(s1, s2, e1 - s1);
190 return r > 0 ? 1 : -1;
195 return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
202 * the solv_vercmp variant your system uses.
205 solv_vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
208 return solv_vercmp_deb(s1, q1, s2, q2);
209 #elif defined(ARCHLINUX)
210 return solv_vercmp_rpm_notilde(s1, q1, s2, q2);
212 return solv_vercmp_rpm(s1, q1, s2, q2);
216 #if defined(MULTI_SEMANTICS)
217 # define solv_vercmp (*(pool->disttype == DISTTYPE_DEB ? &solv_vercmp_deb : &solv_ver##cmp_rpm))
218 #elif defined(DEBIAN)
219 # define solv_vercmp solv_vercmp_deb
220 #elif defined(ARCHLINUX)
221 # define solv_vercmp solv_vercmp_rpm_notilde
223 # define solv_vercmp solv_vercmp_rpm
226 /* edition (e:v-r) compare */
228 pool_evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode)
238 POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s mode=%d\n", evr1, evr2, mode);
240 for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
242 for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
244 if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
246 /* empty epoch, skip epoch check */
255 /* compare the epoch */
256 if (s1 == evr1 || *s1 != ':')
258 if (s2 == evr2 || *s2 != ':')
262 r = solv_vercmp(evr1, s1, evr2, s2);
270 if (!pool->promoteepoch)
288 /* same epoch, now split into version/release */
289 for (s1 = evr1, r1 = 0; *s1; s1++)
292 for (s2 = evr2, r2 = 0; *s2; s2++)
297 if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
298 r = solv_vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
302 if (mode == EVRCMP_COMPARE)
309 if (mode == EVRCMP_COMPARE_EVONLY)
311 if (mode == EVRCMP_MATCH_RELEASE)
313 /* rpm treats empty releases as missing, i.e "foo = 4-" is the same as "foo = 4" */
314 if (r1 && r1 + 1 == s1)
316 if (r2 && r2 + 1 == s2)
323 if (mode != EVRCMP_MATCH || (s1 != r1 && s2 != r2))
325 if (pool->havedistepoch)
328 for (d1 = r1; d1 < s1; d1++)
331 for (d2 = r2; d2 < s2; d2++)
334 /* XXX: promote just in one direction? */
335 r = solv_vercmp(r1, d1 ? d1 : s1, r2, d2 ? d2 : s2);
336 if (r == 0 && d1 < s1 && d2 < s2)
337 r = solv_vercmp(d1 + 1, s1, d2 + 1, s2);
340 r = solv_vercmp(r1, s1, r2, s2);
343 else if (mode == EVRCMP_MATCH_RELEASE)
354 pool_evrcmp(const Pool *pool, Id evr1id, Id evr2id, int mode)
356 const char *evr1, *evr2;
357 if (evr1id == evr2id)
359 evr1 = pool_id2str(pool, evr1id);
360 evr2 = pool_id2str(pool, evr2id);
361 return pool_evrcmp_str(pool, evr1, evr2, mode);
365 pool_evrmatch(const Pool *pool, Id evrid, const char *epoch, const char *version, const char *release)
372 evr1 = pool_id2str(pool, evrid);
373 for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
375 if (s1 != evr1 && *s1 == ':')
379 r = solv_vercmp(evr1, s1, epoch, epoch + strlen(epoch));
387 while (*epoch == '0')
392 for (s1 = evr1, r1 = 0; *s1; s1++)
397 r = solv_vercmp(evr1, r1 ? r1 : s1, version, version + strlen(version));
405 r = solv_vercmp(r1 + 1, s1, release, release + strlen(release));