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