]>
Commit | Line | Data |
---|---|---|
076654e7 RC |
1 | /* |
2 | * Copyright (c) 2002, Robert Collins. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * A copy of the GNU General Public License can be found at | |
10 | * http://www.gnu.org/ | |
11 | * | |
12 | * Written by Robert Collins <rbtcollins@hotmail.com> | |
13 | * | |
14 | */ | |
15 | ||
16 | #include "IniDBBuilderPackage.h" | |
2b734ec7 MB |
17 | |
18 | #include "csu_util/version_compare.h" | |
19 | ||
20 | #include "setup_version.h" | |
21 | ||
67829ce0 | 22 | #include "IniParseFeedback.h" |
076654e7 RC |
23 | #include "package_db.h" |
24 | #include "package_meta.h" | |
25 | #include "package_version.h" | |
26 | #include "cygpackage.h" | |
42c65340 | 27 | #include "ini.h" |
076654e7 RC |
28 | // for strtoul |
29 | #include <string.h> | |
aa1e3b4d RC |
30 | #include "LogSingleton.h" |
31 | #include "PackageSpecification.h" | |
3c196821 | 32 | #include <algorithm> |
076654e7 | 33 | |
6625e635 RC |
34 | using namespace std; |
35 | ||
67829ce0 | 36 | IniDBBuilderPackage::IniDBBuilderPackage (IniParseFeedback const &aFeedback) : |
3c196821 | 37 | cp (0), cbpv (), cspv (), currentSpec (0), currentOrList (0), currentAndList (0), trust (0), _feedback (aFeedback){} |
67829ce0 | 38 | |
3a87705e RC |
39 | IniDBBuilderPackage::~IniDBBuilderPackage() |
40 | { | |
3a87705e RC |
41 | } |
42 | ||
076654e7 | 43 | void |
9b0876b3 | 44 | IniDBBuilderPackage::buildTimestamp (const std::string& time) |
076654e7 | 45 | { |
d2a3615c | 46 | timestamp = strtoul (time.c_str(), 0, 0); |
076654e7 RC |
47 | } |
48 | ||
49 | void | |
9b0876b3 | 50 | IniDBBuilderPackage::buildVersion (const std::string& aVersion) |
076654e7 RC |
51 | { |
52 | version = aVersion; | |
67829ce0 RC |
53 | if (version.size()) |
54 | { | |
2b734ec7 | 55 | if (version_compare(setup_version, version) < 0) |
42c65340 CV |
56 | { |
57 | char old_vers[256]; | |
58 | snprintf (old_vers, sizeof old_vers, | |
59 | "The current ini file is from a newer version of setup-%s.exe. " | |
60 | "If you have any trouble installing, please download a fresh " | |
61 | "version from http://www.cygwin.com/setup-%s.exe", | |
62 | is_64bit ? "x86_64" : "x86", | |
63 | is_64bit ? "x86_64" : "x86"); | |
64 | _feedback.warning(old_vers); | |
65 | } | |
67829ce0 | 66 | } |
076654e7 RC |
67 | } |
68 | ||
69 | void | |
9b0876b3 | 70 | IniDBBuilderPackage::buildPackage (const std::string& name) |
076654e7 | 71 | { |
7f2b9277 RC |
72 | #if DEBUG |
73 | if (cp) | |
74 | { | |
157dc2b8 | 75 | Log (LOG_BABBLE) << "Finished with package " << cp->name << endLog; |
7f2b9277 RC |
76 | if (cbpv) |
77 | { | |
157dc2b8 AG |
78 | Log (LOG_BABBLE) << "Version " << cbpv.Canonical_version() << endLog; |
79 | Log (LOG_BABBLE) << "Depends:" << endLog; | |
80 | dumpAndList (cbpv.depends(), Log (LOG_BABBLE)); | |
7f2b9277 RC |
81 | } |
82 | } | |
83 | #endif | |
076654e7 | 84 | packagedb db; |
cfae3b8d RC |
85 | cp = db.findBinary (PackageSpecification(name)); |
86 | if (!cp) | |
87 | { | |
88 | cp = new packagemeta (name); | |
263157cb | 89 | db.packages.insert (packagedb::packagecollection::value_type(cp->name,cp)); |
cfae3b8d | 90 | } |
846e099d | 91 | cbpv = cygpackage::createInstance (name, package_binary); |
3c196821 | 92 | cspv = packageversion (); |
aa1e3b4d | 93 | currentSpec = NULL; |
7f2b9277 RC |
94 | currentOrList = NULL; |
95 | currentAndList = NULL; | |
076654e7 | 96 | trust = TRUST_CURR; |
3c196821 | 97 | #if DEBUG |
157dc2b8 | 98 | Log (LOG_BABBLE) << "Created package " << name << endLog; |
3c196821 | 99 | #endif |
076654e7 RC |
100 | } |
101 | ||
102 | void | |
9b0876b3 | 103 | IniDBBuilderPackage::buildPackageVersion (const std::string& version) |
076654e7 | 104 | { |
3c196821 | 105 | cbpv.setCanonicalVersion (version); |
076654e7 RC |
106 | add_correct_version(); |
107 | } | |
108 | ||
109 | void | |
9b0876b3 | 110 | IniDBBuilderPackage::buildPackageSDesc (const std::string& theDesc) |
076654e7 | 111 | { |
3c196821 | 112 | cbpv.set_sdesc(theDesc); |
076654e7 RC |
113 | } |
114 | ||
115 | void | |
9b0876b3 | 116 | IniDBBuilderPackage::buildPackageLDesc (const std::string& theDesc) |
076654e7 | 117 | { |
3c196821 | 118 | cbpv.set_ldesc(theDesc); |
076654e7 RC |
119 | } |
120 | ||
121 | void | |
9b0876b3 | 122 | IniDBBuilderPackage::buildPackageInstall (const std::string& path) |
076654e7 | 123 | { |
3c196821 | 124 | process_src (*cbpv.source(), path); |
076654e7 | 125 | } |
3c196821 | 126 | |
076654e7 | 127 | void |
9b0876b3 MB |
128 | IniDBBuilderPackage::buildPackageSource (const std::string& path, |
129 | const std::string& size) | |
076654e7 | 130 | { |
3c196821 RC |
131 | packagedb db; |
132 | /* get an appropriate metadata */ | |
133 | csp = db.findSource (PackageSpecification (cbpv.Name())); | |
134 | if (!csp) | |
135 | { | |
136 | /* Copy the existing meta data to a new source package */ | |
137 | csp = new packagemeta (*cp); | |
138 | /* delete versions information */ | |
139 | csp->versions.clear(); | |
64cd7f94 RC |
140 | csp->desired = packageversion(); |
141 | csp->installed = packageversion(); | |
64cd7f94 RC |
142 | csp->curr = packageversion(); |
143 | csp->exp = packageversion(); | |
263157cb | 144 | db.sourcePackages.insert (packagedb::packagecollection::value_type(csp->name,csp)); |
3c196821 RC |
145 | } |
146 | /* create a source packageversion */ | |
846e099d | 147 | cspv = cygpackage::createInstance (cbpv.Name(), package_source); |
3c196821 RC |
148 | cspv.setCanonicalVersion (cbpv.Canonical_version()); |
149 | set<packageversion>::iterator i=find (csp->versions.begin(), | |
150 | csp->versions.end(), cspv); | |
151 | if (i == csp->versions.end()) | |
152 | { | |
153 | csp->add_version (cspv); | |
154 | } | |
155 | else | |
156 | cspv = *i; | |
157 | ||
158 | if (!cspv.source()->Canonical()) | |
d2a3615c | 159 | cspv.source()->set_canonical (path.c_str()); |
3f34f364 | 160 | cspv.source()->sites.push_back(site(parse_mirror)); |
3c196821 | 161 | |
5ef77c46 | 162 | /* creates the relationship between binary and source packageversions */ |
3c196821 | 163 | cbpv.setSourcePackageSpecification (PackageSpecification (cspv.Name())); |
5ef77c46 BD |
164 | PackageSpecification &spec = cbpv.sourcePackageSpecification(); |
165 | spec.setOperator (PackageSpecification::Equals); | |
166 | spec.setVersion (cbpv.Canonical_version()); | |
3c196821 | 167 | |
3c196821 | 168 | setSourceSize (*cspv.source(), size); |
076654e7 RC |
169 | } |
170 | ||
171 | void | |
172 | IniDBBuilderPackage::buildPackageTrust (int newtrust) | |
173 | { | |
174 | trust = newtrust; | |
175 | if (newtrust != TRUST_UNKNOWN) | |
3c196821 | 176 | { |
846e099d | 177 | cbpv = cygpackage::createInstance (cp->name, package_binary); |
3c196821 RC |
178 | cspv = packageversion (); |
179 | } | |
076654e7 RC |
180 | } |
181 | ||
182 | void | |
9b0876b3 | 183 | IniDBBuilderPackage::buildPackageCategory (const std::string& name) |
076654e7 | 184 | { |
0cf68afd | 185 | cp->add_category (name); |
076654e7 RC |
186 | } |
187 | ||
aa1e3b4d RC |
188 | void |
189 | IniDBBuilderPackage::buildBeginDepends () | |
190 | { | |
191 | #if DEBUG | |
157dc2b8 | 192 | Log (LOG_BABBLE) << "Beginning of a depends statement for " << cp->name |
7f2b9277 | 193 | << endLog; |
157dc2b8 | 194 | dumpAndList (currentAndList, Log (LOG_BABBLE)); |
aa1e3b4d RC |
195 | #endif |
196 | currentSpec = NULL; | |
197 | currentOrList = NULL; /* set by the build AndListNode */ | |
3c196821 | 198 | currentAndList = cbpv.depends(); |
aa1e3b4d RC |
199 | } |
200 | ||
aa1e3b4d | 201 | void |
be13ef43 | 202 | IniDBBuilderPackage::buildInstallSize (const std::string &size) |
aa1e3b4d | 203 | { |
3c196821 | 204 | setSourceSize (*cbpv.source(), size); |
aa1e3b4d RC |
205 | } |
206 | ||
207 | void | |
99f33a3b | 208 | IniDBBuilderPackage::buildInstallSHA512 (unsigned char const *sha512) |
be13ef43 | 209 | { |
e9c1444d | 210 | if (sha512 && !cbpv.source()->sha512_isSet) { |
99f33a3b | 211 | memcpy (cbpv.source()->sha512sum, sha512, sizeof cbpv.source()->sha512sum); |
e9c1444d AG |
212 | cbpv.source()->sha512_isSet = true; |
213 | } | |
be13ef43 CV |
214 | } |
215 | ||
216 | void | |
99f33a3b | 217 | IniDBBuilderPackage::buildSourceSHA512 (unsigned char const *sha512) |
be13ef43 | 218 | { |
ab9c4c1a | 219 | if (sha512 && !cspv.source()->sha512_isSet) { |
99f33a3b | 220 | memcpy (cspv.source()->sha512sum, sha512, sizeof cspv.source()->sha512sum); |
ab9c4c1a | 221 | cspv.source()->sha512_isSet = true; |
e9c1444d | 222 | } |
be13ef43 CV |
223 | } |
224 | ||
225 | void | |
226 | IniDBBuilderPackage::buildInstallMD5 (unsigned char const *md5) | |
aa1e3b4d | 227 | { |
3c196821 RC |
228 | if (md5 && !cbpv.source()->md5.isSet()) |
229 | cbpv.source()->md5.set(md5); | |
aa1e3b4d RC |
230 | } |
231 | ||
232 | void | |
be13ef43 | 233 | IniDBBuilderPackage::buildSourceMD5 (unsigned char const *md5) |
aa1e3b4d | 234 | { |
3c196821 RC |
235 | if (md5 && !cspv.source()->md5.isSet()) |
236 | cspv.source()->md5.set(md5); | |
aa1e3b4d RC |
237 | } |
238 | ||
b1ff53ed RC |
239 | void |
240 | IniDBBuilderPackage::buildBeginBuildDepends () | |
241 | { | |
242 | #if DEBUG | |
157dc2b8 AG |
243 | Log (LOG_BABBLE) << "Beginning of a Build-Depends statement" << endLog; |
244 | dumpAndList (currentAndList, Log (LOG_BABBLE)); | |
b1ff53ed RC |
245 | #endif |
246 | currentSpec = NULL; | |
247 | currentOrList = NULL; /* set by the build AndListNode */ | |
248 | currentAndList = cspv.depends (); | |
249 | } | |
250 | ||
157dc2b8 | 251 | void |
9b0876b3 | 252 | IniDBBuilderPackage::buildSourceName (const std::string& name) |
aa1e3b4d | 253 | { |
3c196821 | 254 | if (cbpv) |
aa1e3b4d | 255 | { |
3c196821 | 256 | cbpv.setSourcePackageSpecification (PackageSpecification (name)); |
aa1e3b4d | 257 | #if DEBUG |
157dc2b8 | 258 | Log (LOG_BABBLE) << "\"" << cbpv.sourcePackageSpecification() << |
aa1e3b4d RC |
259 | "\" is the source package for " << cp->name << "." << endLog; |
260 | #endif | |
261 | } | |
262 | else | |
9b0876b3 MB |
263 | _feedback.warning ((std::string ("Attempt to set source for package") |
264 | + std::string(cp->name) | |
d2a3615c | 265 | + "before creation of a version.").c_str()); |
aa1e3b4d RC |
266 | } |
267 | ||
268 | void | |
9b0876b3 | 269 | IniDBBuilderPackage::buildSourceNameVersion (const std::string& version) |
aa1e3b4d | 270 | { |
3c196821 | 271 | if (cbpv) |
aa1e3b4d | 272 | { |
3c196821 RC |
273 | cbpv.sourcePackageSpecification().setOperator (PackageSpecification::Equals); |
274 | cbpv.sourcePackageSpecification().setVersion (version); | |
aa1e3b4d | 275 | #if DEBUG |
157dc2b8 | 276 | Log (LOG_BABBLE) << "The source version needed for " << cp->name << |
aa1e3b4d RC |
277 | " is " << version << "." << endLog; |
278 | #endif | |
279 | } | |
280 | else | |
9b0876b3 MB |
281 | _feedback.warning ((std::string ("Attempt to set source version for package") |
282 | + std::string(cp->name) | |
d2a3615c | 283 | + "before creation of a version.").c_str()); |
aa1e3b4d RC |
284 | } |
285 | ||
286 | void | |
287 | IniDBBuilderPackage::buildPackageListAndNode () | |
288 | { | |
289 | if (currentAndList) | |
290 | { | |
291 | #if DEBUG | |
157dc2b8 | 292 | Log (LOG_BABBLE) << "New AND node for a package list" << endLog; |
aa1e3b4d RC |
293 | if (currentOrList) |
294 | { | |
157dc2b8 | 295 | ostream &os = Log (LOG_BABBLE); |
aa1e3b4d | 296 | os << "Current OR list is :"; |
157dc2b8 | 297 | for (vector<PackageSpecification *>::const_iterator i= currentOrList->begin(); |
aa1e3b4d RC |
298 | i != currentOrList->end(); ++i) |
299 | os << endl << **i; | |
300 | os << endLog; | |
301 | } | |
302 | #endif | |
303 | currentSpec = NULL; | |
304 | currentOrList = new vector<PackageSpecification *>; | |
305 | currentAndList->push_back (currentOrList); | |
306 | } | |
307 | else | |
9b0876b3 | 308 | _feedback.warning ((std::string ("Attempt to add And node when no AndList" |
aa1e3b4d | 309 | " present for package ") |
9b0876b3 | 310 | + std::string(cp->name)).c_str()); |
aa1e3b4d RC |
311 | } |
312 | ||
313 | void | |
9b0876b3 | 314 | IniDBBuilderPackage::buildPackageListOrNode (const std::string& packageName) |
aa1e3b4d RC |
315 | { |
316 | if (currentOrList) | |
317 | { | |
318 | currentSpec = new PackageSpecification (packageName); | |
319 | currentOrList->push_back (currentSpec); | |
320 | #if DEBUG | |
157dc2b8 | 321 | Log (LOG_BABBLE) << "New OR node in a package list refers to \"" << |
aa1e3b4d RC |
322 | *currentSpec << "\"." << endLog; |
323 | #endif | |
324 | } | |
325 | else | |
9b0876b3 MB |
326 | _feedback.warning ((std::string ("Attempt to set specification for package ") |
327 | + std::string(cp->name) | |
d2a3615c | 328 | + " before creation of a version.").c_str()); |
aa1e3b4d RC |
329 | } |
330 | ||
331 | void | |
332 | IniDBBuilderPackage::buildPackageListOperator (PackageSpecification::_operators const &_operator) | |
333 | { | |
334 | if (currentSpec) | |
335 | { | |
336 | currentSpec->setOperator (_operator); | |
337 | #if DEBUG | |
157dc2b8 | 338 | Log (LOG_BABBLE) << "Current specification is " << *currentSpec << "." << |
aa1e3b4d RC |
339 | endLog; |
340 | #endif | |
341 | } | |
342 | else | |
9b0876b3 MB |
343 | _feedback.warning ((std::string ("Attempt to set an operator for package ") |
344 | + std::string(cp->name) | |
d2a3615c | 345 | + " with no current specification.").c_str()); |
aa1e3b4d RC |
346 | } |
347 | ||
348 | ||
349 | void | |
9b0876b3 | 350 | IniDBBuilderPackage::buildPackageListOperatorVersion (const std::string& aVersion) |
aa1e3b4d RC |
351 | { |
352 | if (currentSpec) | |
353 | { | |
354 | currentSpec->setVersion (aVersion); | |
355 | #if DEBUG | |
157dc2b8 | 356 | Log (LOG_BABBLE) << "Current specification is " << *currentSpec << "." << |
aa1e3b4d RC |
357 | endLog; |
358 | #endif | |
359 | } | |
360 | else | |
9b0876b3 MB |
361 | _feedback.warning ((std::string ("Attempt to set an operator version for package ") |
362 | + std::string(cp->name) | |
d2a3615c | 363 | + " with no current specification.").c_str()); |
aa1e3b4d RC |
364 | } |
365 | ||
366 | /* privates */ | |
367 | ||
076654e7 RC |
368 | void |
369 | IniDBBuilderPackage::add_correct_version() | |
370 | { | |
371 | int merged = 0; | |
3c196821 RC |
372 | for (set<packageversion>::iterator n = cp->versions.begin(); |
373 | !merged && n != cp->versions.end(); ++n) | |
374 | if (*n == cbpv ) | |
076654e7 | 375 | { |
3c196821 | 376 | packageversion ver = *n; |
076654e7 RC |
377 | /* ASSUMPTIONS: |
378 | categories and requires are consistent for the same version across | |
379 | all mirrors | |
380 | */ | |
e15fb0ab JT |
381 | /* |
382 | XXX: if the versions are equal but the size/md5sum are different, | |
383 | we should alert the user, as they may not be getting what they expect... | |
384 | */ | |
076654e7 | 385 | /* Copy the binary mirror across if this site claims to have an install */ |
3f34f364 RC |
386 | if (cbpv.source()->sites.size() ) |
387 | ver.source()->sites.push_back(site (cbpv.source()->sites.begin()->key)); | |
076654e7 | 388 | /* Copy the descriptions across */ |
3c196821 RC |
389 | if (cbpv.SDesc ().size() && !n->SDesc ().size()) |
390 | ver.set_sdesc (cbpv.SDesc ()); | |
391 | if (cbpv.LDesc ().size() && !n->LDesc ().size()) | |
392 | ver.set_ldesc (cbpv.LDesc ()); | |
7f2b9277 RC |
393 | if (cbpv.depends()->size() && !ver.depends ()->size()) |
394 | *ver.depends() = *cbpv.depends(); | |
395 | /* TODO: other package lists */ | |
396 | /* Prevent dangling references */ | |
397 | currentOrList = NULL; | |
398 | currentAndList = NULL; | |
399 | currentSpec = NULL; | |
3c196821 | 400 | cbpv = *n; |
076654e7 | 401 | merged = 1; |
e15fb0ab | 402 | #if DEBUG |
157dc2b8 | 403 | Log (LOG_BABBLE) << cp->name << " merged with an existing version " << cbpv.Canonical_version() << endLog; |
e15fb0ab | 404 | #endif |
076654e7 | 405 | } |
e15fb0ab | 406 | |
7f2b9277 | 407 | if (!merged) |
e15fb0ab JT |
408 | { |
409 | cp->add_version (cbpv); | |
410 | #if DEBUG | |
157dc2b8 | 411 | Log (LOG_BABBLE) << cp->name << " version " << cbpv.Canonical_version() << " added" << endLog; |
e15fb0ab JT |
412 | #endif |
413 | } | |
414 | ||
415 | /* | |
416 | Should this version be the one selected for this package at a given | |
417 | stability/trust setting? After merging potentially multiple package | |
418 | databases, we should pick the one with the highest version number. | |
419 | */ | |
420 | packageversion *v = NULL; | |
076654e7 RC |
421 | switch (trust) |
422 | { | |
423 | case TRUST_CURR: | |
e15fb0ab | 424 | v = &(cp->curr); |
076654e7 | 425 | break; |
076654e7 | 426 | case TRUST_TEST: |
e15fb0ab | 427 | v = &(cp->exp); |
076654e7 RC |
428 | break; |
429 | } | |
e15fb0ab JT |
430 | |
431 | if (v) | |
432 | { | |
433 | int comparison = packageversion::compareVersions(cbpv, *v); | |
434 | ||
435 | if ((bool)(*v)) | |
157dc2b8 | 436 | Log (LOG_BABBLE) << "package " << cp->name << " comparing versions " << cbpv.Canonical_version() << " and " << v->Canonical_version() << ", result was " << comparison << endLog; |
e15fb0ab JT |
437 | |
438 | if (comparison > 0) | |
439 | { | |
440 | *v = cbpv; | |
441 | } | |
442 | } | |
076654e7 RC |
443 | } |
444 | ||
445 | void | |
9b0876b3 | 446 | IniDBBuilderPackage::process_src (packagesource &src, const std::string& path) |
076654e7 | 447 | { |
3c196821 | 448 | if (!src.Canonical()) |
d2a3615c | 449 | src.set_canonical (path.c_str()); |
3f34f364 | 450 | src.sites.push_back(site(parse_mirror)); |
076654e7 | 451 | } |
aa1e3b4d RC |
452 | |
453 | void | |
9b0876b3 | 454 | IniDBBuilderPackage::setSourceSize (packagesource &src, const std::string& size) |
aa1e3b4d RC |
455 | { |
456 | if (!src.size) | |
d2a3615c | 457 | src.size = atoi(size.c_str()); |
aa1e3b4d | 458 | } |
f38044ff CF |
459 | |
460 | void | |
461 | IniDBBuilderPackage::buildMessage (const std::string& message_id, const std::string& message) | |
462 | { | |
463 | cp->set_message (message_id, message); | |
464 | } |