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