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