debversion.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz Exp $
  4. /* ######################################################################
  5. Debian Version - Versioning system for Debian
  6. This implements the standard Debian versioning system.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #include <config.h>
  11. #include <apt-pkg/debversion.h>
  12. #include <apt-pkg/pkgcache.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <ctype.h>
  16. /*}}}*/
  17. debVersioningSystem debVS;
  18. // debVS::debVersioningSystem - Constructor /*{{{*/
  19. // ---------------------------------------------------------------------
  20. /* */
  21. debVersioningSystem::debVersioningSystem()
  22. {
  23. Label = "Standard .deb";
  24. }
  25. /*}}}*/
  26. // debVS::CmpFragment - Compare versions /*{{{*/
  27. // ---------------------------------------------------------------------
  28. /* This compares a fragment of the version. This is a slightly adapted
  29. version of what dpkg uses in dpkg/lib/dpkg/version.c.
  30. In particular, the a | b = NULL check is removed as we check this in the
  31. caller, we use an explicit end for a | b strings and we check ~ explicit. */
  32. static int order(char c)
  33. {
  34. if (isdigit(c))
  35. return 0;
  36. else if (isalpha(c))
  37. return c;
  38. else if (c == '~')
  39. return -1;
  40. else if (c)
  41. return c + 256;
  42. else
  43. return 0;
  44. }
  45. int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
  46. const char *B,const char *BEnd)
  47. {
  48. /* Iterate over the whole string
  49. What this does is to split the whole string into groups of
  50. numeric and non numeric portions. For instance:
  51. a67bhgs89
  52. Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
  53. 2.7.2-linux-1
  54. Has '2', '.', '7', '.' ,'-linux-','1' */
  55. const char *lhs = A;
  56. const char *rhs = B;
  57. while (lhs != AEnd && rhs != BEnd)
  58. {
  59. int first_diff = 0;
  60. while (lhs != AEnd && rhs != BEnd &&
  61. (!isdigit(*lhs) || !isdigit(*rhs)))
  62. {
  63. int vc = order(*lhs);
  64. int rc = order(*rhs);
  65. if (vc != rc)
  66. return vc - rc;
  67. ++lhs; ++rhs;
  68. }
  69. while (*lhs == '0')
  70. ++lhs;
  71. while (*rhs == '0')
  72. ++rhs;
  73. while (isdigit(*lhs) && isdigit(*rhs))
  74. {
  75. if (!first_diff)
  76. first_diff = *lhs - *rhs;
  77. ++lhs;
  78. ++rhs;
  79. }
  80. if (isdigit(*lhs))
  81. return 1;
  82. if (isdigit(*rhs))
  83. return -1;
  84. if (first_diff)
  85. return first_diff;
  86. }
  87. // The strings must be equal
  88. if (lhs == AEnd && rhs == BEnd)
  89. return 0;
  90. // lhs is shorter
  91. if (lhs == AEnd)
  92. {
  93. if (*rhs == '~') return 1;
  94. return -1;
  95. }
  96. // rhs is shorter
  97. if (rhs == BEnd)
  98. {
  99. if (*lhs == '~') return -1;
  100. return 1;
  101. }
  102. // Shouldn't happen
  103. return 1;
  104. }
  105. /*}}}*/
  106. // debVS::CmpVersion - Comparison for versions /*{{{*/
  107. // ---------------------------------------------------------------------
  108. /* This fragments the version into E:V-R triples and compares each
  109. portion separately. */
  110. int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
  111. const char *B,const char *BEnd)
  112. {
  113. // Strip off the epoch and compare it
  114. const char *lhs = (const char*) memchr(A, ':', AEnd - A);
  115. const char *rhs = (const char*) memchr(B, ':', BEnd - B);
  116. if (lhs == NULL)
  117. lhs = A;
  118. if (rhs == NULL)
  119. rhs = B;
  120. // Special case: a zero epoch is the same as no epoch,
  121. // so remove it.
  122. if (lhs != A)
  123. {
  124. for (; *A == '0'; ++A);
  125. if (A == lhs)
  126. {
  127. ++A;
  128. ++lhs;
  129. }
  130. }
  131. if (rhs != B)
  132. {
  133. for (; *B == '0'; ++B);
  134. if (B == rhs)
  135. {
  136. ++B;
  137. ++rhs;
  138. }
  139. }
  140. // Compare the epoch
  141. int Res = CmpFragment(A,lhs,B,rhs);
  142. if (Res != 0)
  143. return Res;
  144. // Skip the :
  145. if (lhs != A)
  146. lhs++;
  147. if (rhs != B)
  148. rhs++;
  149. // Find the last -
  150. const char *dlhs = (const char*) memrchr(lhs, '-', AEnd - lhs);
  151. const char *drhs = (const char*) memrchr(rhs, '-', BEnd - rhs);
  152. if (dlhs == NULL)
  153. dlhs = AEnd;
  154. if (drhs == NULL)
  155. drhs = BEnd;
  156. // Compare the main version
  157. Res = CmpFragment(lhs,dlhs,rhs,drhs);
  158. if (Res != 0)
  159. return Res;
  160. // Skip the -
  161. if (dlhs != lhs)
  162. dlhs++;
  163. if (drhs != rhs)
  164. drhs++;
  165. // no debian revision need to be treated like -0
  166. if (*(dlhs-1) == '-' && *(drhs-1) == '-')
  167. return CmpFragment(dlhs,AEnd,drhs,BEnd);
  168. else if (*(dlhs-1) == '-')
  169. {
  170. const char* null = "0";
  171. return CmpFragment(dlhs,AEnd,null, null+1);
  172. }
  173. else if (*(drhs-1) == '-')
  174. {
  175. const char* null = "0";
  176. return CmpFragment(null, null+1, drhs, BEnd);
  177. }
  178. else
  179. return 0;
  180. }
  181. /*}}}*/
  182. // debVS::CheckDep - Check a single dependency /*{{{*/
  183. // ---------------------------------------------------------------------
  184. /* This simply preforms the version comparison and switch based on
  185. operator. If DepVer is 0 then we are comparing against a provides
  186. with no version. */
  187. bool debVersioningSystem::CheckDep(const char *PkgVer,
  188. int Op,const char *DepVer)
  189. {
  190. if (DepVer == 0 || DepVer[0] == 0)
  191. return true;
  192. if (PkgVer == 0 || PkgVer[0] == 0)
  193. return false;
  194. Op &= 0x0F;
  195. // fast track for (equal) strings [by location] which are by definition equal versions
  196. if (PkgVer == DepVer)
  197. return Op == pkgCache::Dep::Equals || Op == pkgCache::Dep::LessEq || Op == pkgCache::Dep::GreaterEq;
  198. // Perform the actual comparison.
  199. int const Res = CmpVersion(PkgVer, DepVer);
  200. switch (Op)
  201. {
  202. case pkgCache::Dep::LessEq:
  203. if (Res <= 0)
  204. return true;
  205. break;
  206. case pkgCache::Dep::GreaterEq:
  207. if (Res >= 0)
  208. return true;
  209. break;
  210. case pkgCache::Dep::Less:
  211. if (Res < 0)
  212. return true;
  213. break;
  214. case pkgCache::Dep::Greater:
  215. if (Res > 0)
  216. return true;
  217. break;
  218. case pkgCache::Dep::Equals:
  219. if (Res == 0)
  220. return true;
  221. break;
  222. case pkgCache::Dep::NotEquals:
  223. if (Res != 0)
  224. return true;
  225. break;
  226. }
  227. return false;
  228. }
  229. /*}}}*/
  230. // debVS::UpstreamVersion - Return the upstream version string /*{{{*/
  231. // ---------------------------------------------------------------------
  232. /* This strips all the debian specific information from the version number */
  233. std::string debVersioningSystem::UpstreamVersion(const char *Ver)
  234. {
  235. // Strip off the bit before the first colon
  236. const char *I = Ver;
  237. for (; *I != 0 && *I != ':'; I++);
  238. if (*I == ':')
  239. Ver = I + 1;
  240. // Chop off the trailing -
  241. I = Ver;
  242. unsigned Last = strlen(Ver);
  243. for (; *I != 0; I++)
  244. if (*I == '-')
  245. Last = I - Ver;
  246. return std::string(Ver,Last);
  247. }
  248. /*}}}*/