]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debversion.cc
* try harder to get the correct language code
[apt.git] / apt-pkg / deb / debversion.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz Exp $
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>
22 #include <ctype.h>
23 /*}}}*/
24
25 debVersioningSystem debVS;
26
27 // debVS::debVersioningSystem - Constructor /*{{{*/
28 // ---------------------------------------------------------------------
29 /* */
30 debVersioningSystem::debVersioningSystem()
31 {
32 Label = "Standard .deb";
33 }
34 /*}}}*/
35
36 // debVS::CmpFragment - Compare versions /*{{{*/
37 // ---------------------------------------------------------------------
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)
45 int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
46 const char *B,const char *BEnd)
47 {
48 if (A >= AEnd && B >= BEnd)
49 return 0;
50 if (A >= AEnd)
51 {
52 if (*B == '~') return 1;
53 return -1;
54 }
55 if (B >= BEnd)
56 {
57 if (*A == '~') return -1;
58 return 1;
59 }
60
61 /* Iterate over the whole string
62 What this does is to spilt the whole string into groups of
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 {
72 int first_diff = 0;
73
74 while (lhs != AEnd && rhs != BEnd &&
75 (!isdigit(*lhs) || !isdigit(*rhs)))
76 {
77 int vc = order(*lhs);
78 int rc = order(*rhs);
79 if (vc != rc)
80 return vc - rc;
81 lhs++; rhs++;
82 }
83
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++;
94 }
95
96 if (isdigit(*lhs))
97 return 1;
98 if (isdigit(*rhs))
99 return -1;
100 if (first_diff)
101 return first_diff;
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)
110 {
111 if (*rhs == '~') return 1;
112 return -1;
113 }
114
115 // rhs is shorter
116 if (rhs == BEnd)
117 {
118 if (*lhs == '~') return -1;
119 return 1;
120 }
121
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. */
130 int 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. */
184 bool 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 */
233 string 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 /*}}}*/