debversion.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: debversion.cc,v 1.4 2002/11/22 06:59:35 doogie Exp $
  4. /* ######################################################################
  5. Debian Version - Versioning system for Debian
  6. This implements the standard Debian versioning system.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #define APT_COMPATIBILITY 986
  11. #ifdef __GNUG__
  12. #pragma implementation "apt-pkg/debversion.h"
  13. #endif
  14. #include <apt-pkg/debversion.h>
  15. #include <apt-pkg/pkgcache.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. /*}}}*/
  19. debVersioningSystem debVS;
  20. // debVS::debVersioningSystem - Constructor /*{{{*/
  21. // ---------------------------------------------------------------------
  22. /* */
  23. debVersioningSystem::debVersioningSystem()
  24. {
  25. Label = "Standard .deb";
  26. }
  27. /*}}}*/
  28. // StrToLong - Convert the string between two iterators to a long /*{{{*/
  29. // ---------------------------------------------------------------------
  30. /* */
  31. static unsigned long StrToLong(const char *begin,const char *end)
  32. {
  33. char S[40];
  34. char *I = S;
  35. for (; begin != end && I < S + 40;)
  36. *I++ = *begin++;
  37. *I = 0;
  38. return strtoul(S,0,10);
  39. }
  40. /*}}}*/
  41. #define order(x) ((x) == '~' ? -1 \
  42. : isdigit((x)) ? 0 \
  43. : !(x) ? 0 \
  44. : isalpha((x)) ? (x) \
  45. : (x) + 256)
  46. // debVS::CmpFragment - Compare versions /*{{{*/
  47. // ---------------------------------------------------------------------
  48. /* This compares a fragment of the version. Dpkg has a really short
  49. version of this, but it is uh.. interesting to grok. */
  50. int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
  51. const char *B,const char *BEnd)
  52. {
  53. if (A >= AEnd && B >= BEnd)
  54. return 0;
  55. if (A >= AEnd)
  56. return -1;
  57. if (B >= BEnd)
  58. return 1;
  59. /* Iterate over the whole string
  60. What this does is to spilt the whole string into groups of
  61. numeric and non numeric portions. For instance:
  62. a67bhgs89
  63. Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
  64. 2.7.2-linux-1
  65. Has '2', '.', '7', '.' ,'-linux-','1' */
  66. const char *lhs = A;
  67. const char *rhs = B;
  68. while (lhs != AEnd && rhs != BEnd)
  69. {
  70. // Starting points
  71. const char *Slhs = lhs;
  72. const char *Srhs = rhs;
  73. int first_diff = 0;
  74. while ( (lhs != AEnd && !isdigit(*lhs)) || (rhs != BEnd && !isdigit(*rhs)) ) {
  75. int vc= order(*lhs), rc= order(*rhs);
  76. if (vc != rc) return vc - rc;
  77. lhs++; rhs++;
  78. }
  79. while ( *lhs == '0' ) lhs++;
  80. while ( *rhs == '0' ) rhs++;
  81. while (isdigit(*lhs) && isdigit(*rhs)) {
  82. if (!first_diff) first_diff= *lhs - *rhs;
  83. lhs++; rhs++;
  84. }
  85. if (isdigit(*lhs)) return 1;
  86. if (isdigit(*rhs)) return -1;
  87. if (first_diff) return first_diff;
  88. }
  89. // The strings must be equal
  90. if (lhs == AEnd && rhs == BEnd)
  91. return 0;
  92. // lhs is shorter
  93. if (lhs == AEnd)
  94. return -1;
  95. // rhs is shorter
  96. if (rhs == BEnd)
  97. return 1;
  98. // Shouldnt happen
  99. return 1;
  100. }
  101. /*}}}*/
  102. // debVS::CmpVersion - Comparison for versions /*{{{*/
  103. // ---------------------------------------------------------------------
  104. /* This fragments the version into E:V-R triples and compares each
  105. portion separately. */
  106. int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
  107. const char *B,const char *BEnd)
  108. {
  109. // Strip off the epoch and compare it
  110. const char *lhs = A;
  111. const char *rhs = B;
  112. for (;lhs != AEnd && *lhs != ':'; lhs++);
  113. for (;rhs != BEnd && *rhs != ':'; rhs++);
  114. if (lhs == AEnd)
  115. lhs = A;
  116. if (rhs == BEnd)
  117. rhs = B;
  118. // Compare the epoch
  119. int Res = CmpFragment(A,lhs,B,rhs);
  120. if (Res != 0)
  121. return Res;
  122. // Skip the :
  123. if (lhs != A)
  124. lhs++;
  125. if (rhs != B)
  126. rhs++;
  127. // Find the last -
  128. const char *dlhs = AEnd-1;
  129. const char *drhs = BEnd-1;
  130. for (;dlhs > lhs && *dlhs != '-'; dlhs--);
  131. for (;drhs > rhs && *drhs != '-'; drhs--);
  132. if (dlhs == lhs)
  133. dlhs = AEnd;
  134. if (drhs == rhs)
  135. drhs = BEnd;
  136. // Compare the main version
  137. Res = CmpFragment(lhs,dlhs,rhs,drhs);
  138. if (Res != 0)
  139. return Res;
  140. // Skip the -
  141. if (dlhs != lhs)
  142. dlhs++;
  143. if (drhs != rhs)
  144. drhs++;
  145. return CmpFragment(dlhs,AEnd,drhs,BEnd);
  146. }
  147. /*}}}*/
  148. // debVS::CheckDep - Check a single dependency /*{{{*/
  149. // ---------------------------------------------------------------------
  150. /* This simply preforms the version comparison and switch based on
  151. operator. If DepVer is 0 then we are comparing against a provides
  152. with no version. */
  153. bool debVersioningSystem::CheckDep(const char *PkgVer,
  154. int Op,const char *DepVer)
  155. {
  156. if (DepVer == 0 || DepVer[0] == 0)
  157. return true;
  158. if (PkgVer == 0 || PkgVer[0] == 0)
  159. return false;
  160. // Perform the actual comparision.
  161. int Res = CmpVersion(PkgVer,DepVer);
  162. switch (Op & 0x0F)
  163. {
  164. case pkgCache::Dep::LessEq:
  165. if (Res <= 0)
  166. return true;
  167. break;
  168. case pkgCache::Dep::GreaterEq:
  169. if (Res >= 0)
  170. return true;
  171. break;
  172. case pkgCache::Dep::Less:
  173. if (Res < 0)
  174. return true;
  175. break;
  176. case pkgCache::Dep::Greater:
  177. if (Res > 0)
  178. return true;
  179. break;
  180. case pkgCache::Dep::Equals:
  181. if (Res == 0)
  182. return true;
  183. break;
  184. case pkgCache::Dep::NotEquals:
  185. if (Res != 0)
  186. return true;
  187. break;
  188. }
  189. return false;
  190. }
  191. /*}}}*/
  192. // debVS::UpstreamVersion - Return the upstream version string /*{{{*/
  193. // ---------------------------------------------------------------------
  194. /* This strips all the debian specific information from the version number */
  195. string debVersioningSystem::UpstreamVersion(const char *Ver)
  196. {
  197. // Strip off the bit before the first colon
  198. const char *I = Ver;
  199. for (; *I != 0 && *I != ':'; I++);
  200. if (*I == ':')
  201. Ver = I + 1;
  202. // Chop off the trailing -
  203. I = Ver;
  204. unsigned Last = strlen(Ver);
  205. for (; *I != 0; I++)
  206. if (*I == '-')
  207. Last = I - Ver;
  208. return string(Ver,Last);
  209. }
  210. /*}}}*/