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