]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/debversion.cc
Missed one st_mtime.
[apt.git] / apt-pkg / deb / debversion.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
1e8167a6 3// $Id: debversion.cc,v 1.4 2002/11/22 06:59:35 doogie 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 /*}}}*/
35// StrToLong - Convert the string between two iterators to a long /*{{{*/
36// ---------------------------------------------------------------------
37/* */
38static unsigned long StrToLong(const char *begin,const char *end)
39{
40 char S[40];
41 char *I = S;
42 for (; begin != end && I < S + 40;)
43 *I++ = *begin++;
44 *I = 0;
45 return strtoul(S,0,10);
46}
47 /*}}}*/
1e8167a6
AL
48#define order(x) ((x) == '~' ? -1 \
49 : isdigit((x)) ? 0 \
50 : !(x) ? 0 \
51 : isalpha((x)) ? (x) \
52 : (x) + 256)
53
b2e465d6
AL
54// debVS::CmpFragment - Compare versions /*{{{*/
55// ---------------------------------------------------------------------
56/* This compares a fragment of the version. Dpkg has a really short
57 version of this, but it is uh.. interesting to grok. */
58int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
59 const char *B,const char *BEnd)
60{
61 if (A >= AEnd && B >= BEnd)
62 return 0;
63 if (A >= AEnd)
64 return -1;
65 if (B >= BEnd)
66 return 1;
67
68 /* Iterate over the whole string
69 What this does is to spilt the whole string into groups of
70 numeric and non numeric portions. For instance:
71 a67bhgs89
72 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
73 2.7.2-linux-1
74 Has '2', '.', '7', '.' ,'-linux-','1' */
75 const char *lhs = A;
76 const char *rhs = B;
77 while (lhs != AEnd && rhs != BEnd)
78 {
79 // Starting points
80 const char *Slhs = lhs;
81 const char *Srhs = rhs;
1e8167a6 82 int first_diff = 0;
b2e465d6 83
1e8167a6
AL
84 while ( (lhs != AEnd && !isdigit(*lhs)) || (rhs != BEnd && !isdigit(*rhs)) ) {
85 int vc= order(*lhs), rc= order(*rhs);
86 if (vc != rc) return vc - rc;
87 lhs++; rhs++;
b2e465d6 88 }
b2e465d6 89
1e8167a6
AL
90 while ( *lhs == '0' ) lhs++;
91 while ( *rhs == '0' ) rhs++;
92 while (isdigit(*lhs) && isdigit(*rhs)) {
93 if (!first_diff) first_diff= *lhs - *rhs;
94 lhs++; rhs++;
95 }
96 if (isdigit(*lhs)) return 1;
97 if (isdigit(*rhs)) return -1;
98 if (first_diff) 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)
107 return -1;
108
109 // rhs is shorter
110 if (rhs == BEnd)
111 return 1;
112
113 // Shouldnt happen
114 return 1;
115}
116 /*}}}*/
117// debVS::CmpVersion - Comparison for versions /*{{{*/
118// ---------------------------------------------------------------------
119/* This fragments the version into E:V-R triples and compares each
120 portion separately. */
121int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
122 const char *B,const char *BEnd)
123{
124 // Strip off the epoch and compare it
125 const char *lhs = A;
126 const char *rhs = B;
127 for (;lhs != AEnd && *lhs != ':'; lhs++);
128 for (;rhs != BEnd && *rhs != ':'; rhs++);
129 if (lhs == AEnd)
130 lhs = A;
131 if (rhs == BEnd)
132 rhs = B;
133
134 // Compare the epoch
135 int Res = CmpFragment(A,lhs,B,rhs);
136 if (Res != 0)
137 return Res;
138
139 // Skip the :
140 if (lhs != A)
141 lhs++;
142 if (rhs != B)
143 rhs++;
144
145 // Find the last -
146 const char *dlhs = AEnd-1;
147 const char *drhs = BEnd-1;
148 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
149 for (;drhs > rhs && *drhs != '-'; drhs--);
150
151 if (dlhs == lhs)
152 dlhs = AEnd;
153 if (drhs == rhs)
154 drhs = BEnd;
155
156 // Compare the main version
157 Res = CmpFragment(lhs,dlhs,rhs,drhs);
158 if (Res != 0)
159 return Res;
160
161 // Skip the -
162 if (dlhs != lhs)
163 dlhs++;
164 if (drhs != rhs)
165 drhs++;
166
167 return CmpFragment(dlhs,AEnd,drhs,BEnd);
168}
169 /*}}}*/
170// debVS::CheckDep - Check a single dependency /*{{{*/
171// ---------------------------------------------------------------------
172/* This simply preforms the version comparison and switch based on
173 operator. If DepVer is 0 then we are comparing against a provides
174 with no version. */
175bool debVersioningSystem::CheckDep(const char *PkgVer,
176 int Op,const char *DepVer)
177{
178 if (DepVer == 0 || DepVer[0] == 0)
179 return true;
180 if (PkgVer == 0 || PkgVer[0] == 0)
181 return false;
182
183 // Perform the actual comparision.
184 int Res = CmpVersion(PkgVer,DepVer);
185 switch (Op & 0x0F)
186 {
187 case pkgCache::Dep::LessEq:
188 if (Res <= 0)
189 return true;
190 break;
191
192 case pkgCache::Dep::GreaterEq:
193 if (Res >= 0)
194 return true;
195 break;
196
197 case pkgCache::Dep::Less:
198 if (Res < 0)
199 return true;
200 break;
201
202 case pkgCache::Dep::Greater:
203 if (Res > 0)
204 return true;
205 break;
206
207 case pkgCache::Dep::Equals:
208 if (Res == 0)
209 return true;
210 break;
211
212 case pkgCache::Dep::NotEquals:
213 if (Res != 0)
214 return true;
215 break;
216 }
217
218 return false;
219}
220 /*}}}*/
221// debVS::UpstreamVersion - Return the upstream version string /*{{{*/
222// ---------------------------------------------------------------------
223/* This strips all the debian specific information from the version number */
224string debVersioningSystem::UpstreamVersion(const char *Ver)
225{
226 // Strip off the bit before the first colon
227 const char *I = Ver;
228 for (; *I != 0 && *I != ':'; I++);
229 if (*I == ':')
230 Ver = I + 1;
231
232 // Chop off the trailing -
233 I = Ver;
234 unsigned Last = strlen(Ver);
235 for (; *I != 0; I++)
236 if (*I == '-')
237 Last = I - Ver;
238
239 return string(Ver,Last);
240}
241 /*}}}*/