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