]> cygwin.com Git - cygwin-apps/setup.git/blob - package_version.cc
2002-11-04 Max Bowsher <maxb@ukf.net>
[cygwin-apps/setup.git] / package_version.cc
1 /*
2 * Copyright (c) 2001, 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 /* this is the parent class for all package operations.
17 */
18
19 #if 0
20 static const char *cvsid =
21 "\n%%% $Id$\n";
22 #endif
23
24 #include "package_version.h"
25 #include "package_db.h"
26 #include "package_meta.h"
27 #include "state.h"
28 #include "resource.h"
29 #include <algorithm>
30
31 using namespace std;
32
33 /* a default class to avoid special casing empty packageversions */
34
35 /* TODO place into the class header */
36 class _defaultversion : public _packageversion
37 {
38 public:
39 _defaultversion()
40 {
41 // never try to free me!
42 ++references;
43 }
44 String const Name(){return String();}
45 String const Vendor_version() {return String();}
46 String const Package_version() {return String();}
47 String const Canonical_version() {return String();}
48 void setCanonicalVersion (String const &) {}
49 package_status_t Status (){return package_notinstalled;}
50 package_type_t Type () {return package_binary;}
51 String const getfirstfile () {return String();}
52 String const getnextfile () {return String();}
53 String const SDesc () {return String();}
54 void set_sdesc (String const &) {}
55 String const LDesc () {return String();}
56 void set_ldesc (String const &) {}
57 void uninstall (){}
58 };
59 static _defaultversion defaultversion;
60
61 /* the wrapper class */
62 packageversion::packageversion() : data (&defaultversion)
63 {
64 ++data->references;
65 }
66
67 /* Create from an actual package */
68 packageversion::packageversion (_packageversion *pkg)
69 {
70 if (pkg)
71 data = pkg;
72 else
73 data = &defaultversion;
74 ++data->references;
75 }
76
77 packageversion::packageversion (packageversion const &existing) :
78 data(existing.data)
79 {
80 ++data->references;
81 }
82
83 packageversion::~packageversion()
84 {
85 if (--data->references == 0)
86 delete data;
87 }
88
89 packageversion &
90 packageversion::operator= (packageversion const &rhs)
91 {
92 ++rhs.data->references;
93 if (--data->references == 0)
94 delete data;
95 data = rhs.data;
96 return *this;
97 }
98
99 bool
100 packageversion::operator ! () const
101 {
102 return !data->Name().size();
103 }
104
105 packageversion::operator bool () const
106 {
107 return data->Name().size();
108 }
109
110 bool
111 packageversion::operator == (packageversion const &rhs) const
112 {
113 if (this == &rhs || data == rhs.data)
114 return true;
115 else
116 return data->Name () == rhs.data->Name() && data->Canonical_version () == rhs.data->Canonical_version();
117 }
118
119 bool
120 packageversion::operator != (packageversion const &rhs) const
121 {
122 return ! (*this == rhs);
123 }
124
125 bool
126 packageversion::operator < (packageversion const &rhs) const
127 {
128 int t = data->Name ().casecompare (rhs.data->Name());
129 if (t < 0)
130 return true;
131 else if (t > 0)
132 return false;
133 else if (data->Canonical_version().casecompare (rhs.data->Canonical_version()) < 0)
134 return true;
135 return false;
136 }
137
138 String const
139 packageversion::Name () const
140 {
141 return data->Name ();
142 }
143
144 String const
145 packageversion::Canonical_version() const
146 {
147 return data->Canonical_version();
148 }
149
150 void
151 packageversion::setCanonicalVersion (String const &ver)
152 {
153 data->setCanonicalVersion (ver);
154 }
155
156 String const
157 packageversion::getfirstfile ()
158 {
159 return data->getfirstfile ();
160 }
161
162 String const
163 packageversion::getnextfile ()
164 {
165 return data->getnextfile ();
166 }
167
168 String const
169 packageversion::SDesc () const
170 {
171 return data->SDesc ();
172 }
173
174 void
175 packageversion::set_sdesc (String const &sdesc)
176 {
177 data->set_sdesc (sdesc);
178 }
179
180 String const
181 packageversion::LDesc () const
182 {
183 return data->LDesc ();
184 }
185
186 void
187 packageversion::set_ldesc (String const &ldesc)
188 {
189 data->set_ldesc (ldesc);
190 }
191
192 packageversion
193 packageversion::sourcePackage()
194 {
195 return data->sourcePackage();
196 }
197
198 PackageSpecification &
199 packageversion::sourcePackageSpecification ()
200 {
201 return data->sourcePackageSpecification ();
202 }
203
204 void
205 packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
206 {
207 data->setSourcePackageSpecification(spec);
208 }
209
210 vector <vector <PackageSpecification *> *> *
211 packageversion::depends()
212 {
213 return &data->depends;
214 }
215
216 vector <vector <PackageSpecification *> *> *
217 packageversion::predepends()
218 {
219 return &data->predepends;
220 }
221
222 vector <vector <PackageSpecification *> *> *
223 packageversion::recommends()
224 {
225 return &data->recommends;
226 }
227
228 vector <vector <PackageSpecification *> *> *
229 packageversion::suggests()
230 {
231 return &data->suggests;
232 }
233
234 vector <vector <PackageSpecification *> *> *
235 packageversion::replaces()
236 {
237 return &data->replaces;
238 }
239
240 vector <vector <PackageSpecification *> *> *
241 packageversion::conflicts()
242 {
243 return &data->conflicts;
244 }
245
246 vector <vector <PackageSpecification *> *> *
247 packageversion::provides()
248 {
249 return &data->provides;
250 }
251
252 vector <vector <PackageSpecification *> *> *
253 packageversion::binaries()
254 {
255 return &data->binaries;
256 }
257
258 bool
259 packageversion::picked () const
260 {
261 return data->picked;
262 }
263
264 void
265 packageversion::pick (bool aBool)
266 {
267 data->picked = aBool;
268 }
269
270 bool
271 packageversion::changeRequested () const
272 {
273 return data->changeRequested ();
274 }
275
276 void
277 packageversion::uninstall ()
278 {
279 data->uninstall ();
280 }
281
282 packagesource *
283 packageversion::source ()
284 {
285 if (!data->sources.size())
286 data->sources.push_back (packagesource());
287 return &data->sources[0];
288 }
289
290 vector<packagesource> *
291 packageversion::sources ()
292 {
293 return &data->sources;
294 }
295
296 bool
297 packageversion::accessible() const
298 {
299 return data->accessible();
300 }
301
302 static bool
303 checkForInstalled (PackageSpecification *spec)
304 {
305 packagedb db;
306 packagemeta *required = db.findBinary (*spec);
307 if (!required)
308 return false;
309 if (spec->satisfies (required->installed)
310 && required->desired == required->installed )
311 /* done, found a satisfactory installed version that will remain
312 installed */
313 return true;
314 return false;
315 }
316
317 static bool
318 checkForUpgradeable (PackageSpecification *spec)
319 {
320 packagedb db;
321 packagemeta *required = db.findBinary (*spec);
322 if (!required || !required->installed)
323 return false;
324 for (set <packageversion>::iterator i = required->versions.begin();
325 i != required->versions.end(); ++i)
326 if (spec->satisfies (*i))
327 return true;
328 return false;
329 }
330
331 static bool
332 checkForSatisfiable (PackageSpecification *spec)
333 {
334 packagedb db;
335 packagemeta *required = db.findBinary (*spec);
336 if (!required)
337 return false;
338 for (set <packageversion>::iterator i = required->versions.begin();
339 i != required->versions.end(); ++i)
340 if (spec->satisfies (*i))
341 return true;
342 return false;
343 }
344
345 static int
346 processOneDependency(trusts deftrust, size_t depth, PackageSpecification *spec)
347 {
348 /* TODO: add this to a set of packages to be offered to meet the
349 requirement. For now, simply set the install to the first
350 satisfactory version. The user can step through the list if
351 desired */
352 packagedb db;
353 packagemeta *required = db.findBinary (*spec);
354 set <packageversion>::iterator v;
355 for (v = required->versions.begin();
356 v != required->versions.end() && !spec->satisfies (*v); ++v);
357 if (v != required->versions.end())
358 {
359 /* preserve source */
360 bool sourceticked = required->desired.sourcePackage().picked();
361 /* install this version */
362 required->desired = *v;
363 required->desired.pick (required->installed != required->desired);
364 required->desired.sourcePackage().pick (sourceticked);
365 /* does this requirement have requirements? */
366 return required->set_requirements (deftrust, depth + 1);
367 }
368 /* else assert !! */
369 return 0;
370 }
371
372 int
373 packageversion::set_requirements (trusts deftrust, size_t depth)
374 {
375 int changed = 0;
376 vector <vector <PackageSpecification *> *>::iterator dp = depends ()->begin();
377 /* cheap test for too much recursion */
378 if (depth > 5)
379 return changed;
380 /* walk through each and clause */
381 while (dp != depends ()->end())
382 {
383 /* three step:
384 1) is a satisfactory or clause installed?
385 2) is an unsatisfactory version of an or clause which has
386 a satisfactory version available installed?
387 3) is a satisfactory package available?
388 */
389 /* check each or clause for an installed match */
390 vector <PackageSpecification *>::iterator i =
391 find_if ((*dp)->begin(), (*dp)->end(), checkForInstalled);
392 if (i != (*dp)->end())
393 {
394 /* we found an installed ok package */
395 /* next and clause */
396 ++dp;
397 continue;
398 }
399 /* check each or clause for an upgradeable version */
400 i = find_if ((*dp)->begin(), (*dp)->end(), checkForUpgradeable);
401 if (i != (*dp)->end())
402 {
403 /* we found a package that can be up/downgraded to meet the
404 requirement. (*i is the packagespec that can be satisfied.)
405 */
406 ++dp;
407 changed += processOneDependency (deftrust, depth, *i) + 1;
408 continue;
409 }
410 /* check each or clause for an installable version */
411 i = find_if ((*dp)->begin(), (*dp)->end(), checkForSatisfiable);
412 if (i != (*dp)->end())
413 {
414 /* we found a package that can be installed to meet the requirement */
415 ++dp;
416 changed += processOneDependency (deftrust, depth, *i) + 1;
417 continue;
418 }
419 ++dp;
420 }
421 return changed;
422 }
423
424 /* the parent data class */
425
426 _packageversion::_packageversion ():picked (false), references (0)
427 {
428 }
429
430 _packageversion::~_packageversion ()
431 {
432 }
433
434 PackageSpecification &
435 _packageversion::sourcePackageSpecification ()
436 {
437 return _sourcePackage;
438 }
439
440 void
441 _packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
442 {
443 _sourcePackage = spec;
444 }
445
446 packageversion
447 _packageversion::sourcePackage ()
448 {
449 if (!sourceVersion)
450 {
451 packagedb db;
452 packagemeta * pkg;
453 pkg = db.findSource (_sourcePackage);
454 /* no valid source meta available, just return the default
455 (blank) package version
456 */
457 if (!pkg)
458 return sourceVersion;
459 set<packageversion>::iterator i=pkg->versions.begin();
460 while (i != pkg->versions.end())
461 {
462 packageversion const & ver = * i;
463 if (_sourcePackage.satisfies (ver))
464 sourceVersion = ver;
465 ++i;
466 }
467 }
468 return sourceVersion;
469 }
470
471 bool
472 _packageversion::accessible() const
473 {
474 bool cached = true;
475 for (vector<packagesource>::const_iterator i = sources.begin();
476 i!=sources.end(); ++i)
477 if (!i->Cached ())
478 cached = false;
479 if (cached)
480 return true;
481 if (::source == IDC_SOURCE_CWD)
482 return false;
483 unsigned int retrievable = 0;
484 for (vector<packagesource>::const_iterator i = sources.begin();
485 i!=sources.end(); ++i)
486 if (i->sites.size() || i->Cached ())
487 retrievable += 1;
488 return retrievable == sources.size();
489 }
490
491 bool
492 _packageversion::changeRequested ()
493 {
494 return (picked || sourcePackage().picked());
495 }
This page took 0.061042 seconds and 5 git commands to generate.