]> cygwin.com Git - cygwin-apps/setup.git/blob - package_meta.cc
Simplify uninstall-only warning
[cygwin-apps/setup.git] / package_meta.cc
1 /*
2 * Copyright (c) 2001, 2003 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 "package_meta.h"
17
18 #include <string>
19 #include <set>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <strings.h>
25 #include "getopt++/StringArrayOption.h"
26
27 #include "io_stream.h"
28 #include "compress.h"
29
30 #include "filemanip.h"
31 #include "LogSingleton.h"
32 /* io_stream needs a bit of tweaking to get rid of this. TODO */
33 #include "mount.h"
34 /* this goes at the same time */
35 #include "win32.h"
36
37 #include "script.h"
38 #include "package_db.h"
39
40 #include <algorithm>
41 #include "Generic.h"
42 #include "download.h"
43 #include "Exception.h"
44 #include "resource.h"
45
46 static StringArrayOption DeletePackageOption ('x', "remove-packages", "Specify packages to uninstall");
47 static StringArrayOption DeleteCategoryOption ('c', "remove-categories", "Specify categories to uninstall");
48 static StringArrayOption PackageOption ('P', "packages", "Specify packages to install");
49 static StringArrayOption CategoryOption ('C', "categories", "Specify entire categories to install");
50 bool hasManualSelections = 0;
51
52 /*****************/
53
54 /* Return an appropriate category caption given the action */
55 unsigned int
56 packagemeta::action_caption (_actions _value)
57 {
58 switch (_value)
59 {
60 case NoChange_action:
61 return IDS_ACTION_DEFAULT;
62 case Install_action:
63 return IDS_ACTION_INSTALL;
64 case Reinstall_action:
65 return IDS_ACTION_REINSTALL;
66 case Uninstall_action:
67 return IDS_ACTION_UNINSTALL;
68 }
69
70 return IDS_ACTION_UNKNOWN;
71 }
72
73 packagemeta::packagemeta (packagemeta const &rhs) :
74 name (rhs.name),
75 categories (rhs.categories), versions (rhs.versions),
76 installed (rhs.installed),
77 curr (rhs.curr),
78 exp (rhs.exp),
79 desired (rhs.desired)
80 {
81
82 }
83
84 template<class T> struct removeCategory : public std::unary_function<T, void>
85 {
86 removeCategory(packagemeta *pkg) : _pkg (pkg) {}
87 void operator() (T x)
88 {
89 std::vector <packagemeta *> &aList = packagedb::categories[x];
90 aList.erase (find (aList.begin(), aList.end(), _pkg));
91 }
92 packagemeta *_pkg;
93 };
94
95
96 packagemeta::~packagemeta()
97 {
98 for_each (categories.begin (), categories.end (), removeCategory<std::string> (this));
99 categories.clear ();
100 versions.clear ();
101 }
102
103 SolvableVersion
104 packagemeta::add_version (const SolverPool::addPackageData &inpkgdata)
105 {
106 SolverPool::addPackageData pkgdata = inpkgdata;
107
108 packageversion *v = NULL;
109 switch (pkgdata.stability)
110 {
111 case TRUST_CURR:
112 v = &(this->curr);
113 break;
114 case TRUST_TEST:
115 v = &(this->exp);
116 break;
117 default:
118 break;
119 }
120
121 /*
122 If a packageversion for the same version number is already present, allow
123 this version to replace it.
124
125 There is a problem where multiple repos provide a package. It's never been
126 clear which repo should win. With this implementation, the last one added
127 will win.
128
129 We rely on this by adding packages from installed.db last.
130 */
131
132 for (std::set <packageversion>::iterator i = versions.begin();
133 i != versions.end();
134 i++)
135 {
136 if (i->Canonical_version() != pkgdata.version)
137 continue;
138
139 if (pkgdata.vendor == i->Vendor())
140 {
141 /* Merge the site-list from any existing packageversion with the same
142 repository 'release:' label */
143 pkgdata.archive.sites.insert(pkgdata.archive.sites.end(),
144 i->source()->sites.begin(),
145 i->source()->sites.end());
146
147 /* Installed packages do not supersede repo packages */
148 if (pkgdata.reponame != "_installed")
149 {
150 /* Ensure a stability level doesn't point to a version we're about
151 to remove */
152 if (v && (*v == *i))
153 *v = packageversion();
154
155 i->remove();
156 }
157 }
158 else
159 {
160 /* Otherwise... if we had a way to set repo priorities, that could be
161 used to control which packageversion the solver picks. For the
162 moment, just warn that you might not be getting what you think you
163 should...
164
165 (suppress this for installed packages, as we are only guessing the
166 vendor, currently)
167 */
168 if (pkgdata.reponame != "_installed")
169 {
170 Log (LOG_PLAIN) << "Version " << pkgdata.version << " of package " <<
171 name << " is present in releases labelled " << pkgdata.vendor <<
172 " and " << i->Vendor() << endLog;
173 }
174 }
175
176 versions.erase(i);
177
178 break;
179 }
180
181 /* Create the SolvableVersion */
182 packagedb db;
183 SolvableVersion thepkg = db.solver.addPackage(name, pkgdata);
184
185 /* Add the version */
186 std::pair<std::set <packageversion>::iterator, bool> result = versions.insert (thepkg);
187
188 if (!result.second)
189 Log (LOG_PLAIN) << "Failed to add version " << thepkg.Canonical_version() << " in package " << name << endLog;
190 #ifdef DEBUG
191 else
192 Log (LOG_PLAIN) << "Added version " << thepkg.Canonical_version() << " in package " << name << endLog;
193 #endif
194
195 /* Record the highest version at a given stability level */
196 if (v)
197 {
198 /* Any version is always greater than no version */
199 int comparison = 1;
200 if (*v)
201 comparison = SolvableVersion::compareVersions(thepkg, *v);
202
203 #ifdef DEBUG
204 if ((bool)(*v))
205 Log (LOG_BABBLE) << "package " << thepkg.Name() << " comparing versions " << thepkg.Canonical_version() << " and " << v->Canonical_version() << ", result was " << comparison << endLog;
206 #endif
207
208 if (comparison >= 0)
209 {
210 *v = thepkg;
211 }
212 }
213
214 return thepkg;
215 }
216
217 const packageversion *
218 packagemeta::findVersion(std::string &version) const
219 {
220 for (std::set <packageversion>::iterator i = versions.begin();
221 i != versions.end();
222 i++)
223 {
224 if (i->Canonical_version() == version)
225 return &(*i);
226 }
227
228 return NULL;
229 }
230
231 bool
232 packagemeta::isBlacklisted(const packageversion &version) const
233 {
234 for (std::set<std::string>::iterator i = version_blacklist.begin();
235 i != version_blacklist.end();
236 i++)
237 {
238 if (i->compare(version.Canonical_version()) == 0)
239 return true;
240 }
241
242 return false;
243 }
244
245 void
246 packagemeta::set_installed_version (const std::string &version)
247 {
248 for (std::set<packageversion>::iterator i = versions.begin(); i != versions.end(); i++)
249 {
250 if (version.compare(i->Canonical_version()) == 0)
251 {
252 installed = *i;
253
254 /* and mark as Keep */
255 desired = installed;
256 }
257 }
258 }
259
260 void
261 packagemeta::add_category (const std::string& cat)
262 {
263 if (categories.find (cat) != categories.end())
264 return;
265 /* add a new record for the package list */
266 packagedb::categories[cat].push_back (this);
267 categories.insert (cat);
268 }
269
270 struct StringConcatenator : public std::unary_function<const std::string, void>{
271 StringConcatenator(std::string aString) : gap(aString){}
272 void operator()(const std::string& aString)
273 {
274 if (result.size() != 0)
275 result += gap;
276 result += aString;
277 }
278 std::string result;
279 std::string gap;
280 };
281
282 const std::string
283 packagemeta::getReadableCategoryList () const
284 {
285 return for_each(categories.begin(), categories.end(),
286 visit_if (
287 StringConcatenator(", "), bind1st(std::not_equal_to<std::string>(), "All"))
288 ).visitor.result;
289 }
290
291 static void
292 parseNames (std::set<std::string> &parsed, std::string &option)
293 {
294 std::string tname;
295
296 /* Split up the packages listed in the option. */
297 std::string::size_type loc = option.find (",", 0);
298 while (loc != std::string::npos)
299 {
300 tname = option.substr (0, loc);
301 option = option.substr (loc + 1);
302 parsed.insert (tname);
303 loc = option.find (",", 0);
304 }
305
306 /* At this point, no "," exists in option. Don't add
307 an empty string if the entire option was empty. */
308 if (option.length ())
309 parsed.insert (option);
310 }
311
312 static void
313 validatePackageNames (std::set<std::string> &names)
314 {
315 packagedb db;
316 for (std::set<std::string>::iterator n = names.begin();
317 n != names.end();
318 ++n)
319 {
320 if (db.packages.find(*n) == db.packages.end())
321 {
322 Log(LOG_PLAIN) << "Package '" << *n << "' not found." << endLog;
323 }
324 }
325 }
326
327 bool packagemeta::isManuallyWanted(packageversion &version) const
328 {
329 static bool parsed_yet = false;
330 static std::map<std::string, std::string> parsed_names;
331 hasManualSelections |= parsed_names.size ();
332 static std::set<std::string> parsed_categories;
333 hasManualSelections |= parsed_categories.size ();
334 bool bReturn = false;
335
336 /* First time through, we parse all the names out from the
337 option string and store them away in an STL set. */
338 if (!parsed_yet)
339 {
340 std::vector<std::string> packages_options = PackageOption;
341 std::vector<std::string> categories_options = CategoryOption;
342
343 std::set<std::string> items;
344 for (std::vector<std::string>::iterator n = packages_options.begin ();
345 n != packages_options.end (); ++n)
346 {
347 parseNames (items, *n);
348 }
349
350 std::set<std::string> packages;
351 /* Separate any 'package=version' into package and version parts */
352 for (std::set<std::string>::iterator n = items.begin();
353 n != items.end();
354 ++n)
355 {
356 std::string package;
357 std::string version;
358 std::string::size_type loc = n->find ("=", 0);
359 if (loc != std::string::npos)
360 {
361 package = n->substr(0, loc);
362 version = n->substr(loc+1);
363 }
364 else
365 {
366 package = *n;
367 version = "";
368 }
369 Log (LOG_BABBLE) << "package: " << package << " version: " << version << endLog;
370 parsed_names[package] = version;
371 packages.insert(package);
372 }
373
374 validatePackageNames (packages);
375
376 for (std::vector<std::string>::iterator n = categories_options.begin ();
377 n != categories_options.end (); ++n)
378 {
379 parseNames (parsed_categories, *n);
380 }
381 parsed_yet = true;
382 }
383
384 /* Once we've already parsed the option string, just do
385 a lookup in the cache of already-parsed names. */
386 std::map<std::string, std::string>::iterator i = parsed_names.find(name);
387 if (i != parsed_names.end())
388 {
389 bReturn = true;
390
391 /* Wanted version is unspecified */
392 version = packageversion();
393
394 /* ... unless a version was explicitly specified */
395 std::string v = i->second;
396 if (!v.empty())
397 {
398 const packageversion *pv = findVersion(v);
399 if (pv)
400 version = *pv;
401 else
402 Log (LOG_PLAIN) << "package: " << name << " version: " << v << " not found" << endLog;
403 }
404 }
405
406 /* If we didn't select the package manually, did we select any
407 of the categories it is in? */
408 if (!bReturn && parsed_categories.size ())
409 {
410 std::set<std::string, casecompare_lt_op>::iterator curcat;
411 for (curcat = categories.begin (); curcat != categories.end (); curcat++)
412 if (parsed_categories.find (*curcat) != parsed_categories.end ())
413 {
414 Log (LOG_BABBLE) << "Found category " << *curcat << " in package " << name << endLog;
415 version = packageversion();
416 bReturn = true;
417 }
418 }
419
420 if (bReturn)
421 Log (LOG_BABBLE) << "Added manual package " << name << endLog;
422 return bReturn;
423 }
424
425 bool packagemeta::isManuallyDeleted() const
426 {
427 static bool parsed_yet = false;
428 static std::set<std::string> parsed_delete;
429 hasManualSelections |= parsed_delete.size ();
430 static std::set<std::string> parsed_delete_categories;
431 hasManualSelections |= parsed_delete_categories.size ();
432 bool bReturn = false;
433
434 /* First time through, we parse all the names out from the
435 option string and store them away in an STL set. */
436 if (!parsed_yet)
437 {
438 std::vector<std::string> delete_options = DeletePackageOption;
439 std::vector<std::string> categories_options = DeleteCategoryOption;
440 for (std::vector<std::string>::iterator n = delete_options.begin ();
441 n != delete_options.end (); ++n)
442 {
443 parseNames (parsed_delete, *n);
444 }
445 validatePackageNames (parsed_delete);
446 for (std::vector<std::string>::iterator n = categories_options.begin ();
447 n != categories_options.end (); ++n)
448 {
449 parseNames (parsed_delete_categories, *n);
450 }
451 parsed_yet = true;
452 }
453
454 /* Once we've already parsed the option string, just do
455 a lookup in the cache of already-parsed names. */
456 bReturn = parsed_delete.find(name) != parsed_delete.end();
457
458 /* If we didn't select the package manually, did we select any
459 of the categories it is in? */
460 if (!bReturn && parsed_delete_categories.size ())
461 {
462 std::set<std::string, casecompare_lt_op>::iterator curcat;
463 for (curcat = categories.begin (); curcat != categories.end (); curcat++)
464 if (parsed_delete_categories.find (*curcat) != parsed_delete_categories.end ())
465 {
466 Log (LOG_BABBLE) << "Found category " << *curcat << " in package " << name << endLog;
467 bReturn = true;
468 }
469 }
470
471 if (bReturn)
472 Log (LOG_BABBLE) << "Deleted manual package " << name << endLog;
473 return bReturn;
474 }
475
476 const std::string
477 packagemeta::SDesc () const
478 {
479 for (std::set<packageversion>::iterator i = versions.begin(); i != versions.end(); i++)
480 {
481 if (i->SDesc().size())
482 return i->SDesc ();
483 }
484
485 return std::string();
486 }
487
488 static bool
489 hasLDesc(packageversion const &pkg)
490 {
491 return pkg.LDesc().size();
492 }
493
494 const std::string
495 packagemeta::LDesc () const
496 {
497 std::set<packageversion>::iterator i = find_if (versions.begin(), versions.end(), hasLDesc);
498 if (i == versions.end())
499 return std::string();
500 return i->LDesc ();
501 };
502
503 /* Return an appropriate caption given the current action. */
504 std::wstring
505 packagemeta::action_caption () const
506 {
507 switch (_action)
508 {
509 case Uninstall_action:
510 return LoadStringW(IDS_ACTION_UNINSTALL);
511 case NoChange_action:
512 if (!desired)
513 return LoadStringW(IDS_ACTION_SKIP);
514 if (desired.sourcePackage() && srcpicked())
515 /* FIXME: Redo source should come up if the tarball is already present locally */
516 return LoadStringW(IDS_ACTION_SOURCE);
517 return LoadStringW(IDS_ACTION_KEEP);
518 case Reinstall_action:
519 return LoadStringW(packagedb::task == PackageDB_Install ? IDS_ACTION_REINSTALL : IDS_ACTION_RETRIEVE);
520 case Install_action:
521 return string_to_wstring(desired.Canonical_version());
522 }
523 return LoadStringW(IDS_ACTION_UNKNOWN);
524 }
525
526 void
527 packagemeta::select_action (int id, trusts const deftrust)
528 {
529 if (id <= 0)
530 {
531 // Install a specific version
532 std::set<packageversion>::iterator i = versions.begin ();
533 for (int j = -id; j > 0; j--)
534 i++;
535
536 set_action(Install_action, *i, true);
537 }
538 else
539 {
540 if (id == packagemeta::NoChange_action)
541 set_action((packagemeta::_actions)id, installed);
542 else
543 set_action((packagemeta::_actions)id, trustp (true, deftrust), true);
544 }
545 }
546
547 // toggle between the currently installed version (or uninstalled, if not
548 // installed), and the naively preferred version (the highest non-test version)
549 void
550 packagemeta::toggle_action ()
551 {
552 if (desired != installed)
553 {
554 set_action(NoChange_action, installed);
555 }
556 else
557 {
558 packageversion naively_preferred;
559 std::set<packageversion>::iterator i = versions.begin ();
560 for (i = versions.begin (); i != versions.end (); ++i)
561 if (!packagedb::solver.is_test_package(*i))
562 naively_preferred = *i;
563
564 set_action(Install_action, naively_preferred, true);
565 }
566 }
567
568 ActionList *
569 packagemeta::list_actions(trusts const trust)
570 {
571 // build the list of possible actions
572 ActionList *al = new ActionList();
573
574 al->add(IDS_ACTION_UNINSTALL, (int)Uninstall_action, (_action == Uninstall_action), bool(installed));
575 al->add(IDS_ACTION_SKIP, (int)NoChange_action, (_action == NoChange_action) && !installed, !installed);
576
577 std::set<packageversion>::iterator i;
578 for (i = versions.begin (); i != versions.end (); ++i)
579 {
580 if (*i == installed)
581 {
582 al->add(IDS_ACTION_KEEP, (int)NoChange_action, (_action == NoChange_action), TRUE);
583 al->add(packagedb::task == PackageDB_Install ? IDS_ACTION_REINSTALL : IDS_ACTION_RETRIEVE,
584 (int)Reinstall_action, (_action == Reinstall_action), TRUE);
585 }
586 else
587 {
588 std::wstring label = string_to_wstring(i->Canonical_version());
589 if (packagedb::solver.is_test_package(*i))
590 label += L" (Test)";
591 al->add(label,
592 -std::distance(versions.begin (), i),
593 (_action == Install_action) && (*i == desired),
594 TRUE);
595 }
596 }
597
598 return al;
599 }
600
601 // Set a particular type of action.
602 void
603 packagemeta::set_action (_actions action, packageversion const &default_version,
604 bool useraction)
605 {
606 if (action == NoChange_action)
607 {
608 // if installed, keep
609 if (installed
610 || categories.find ("Base") != categories.end ()
611 || categories.find ("Orphaned") != categories.end ())
612 {
613 desired = default_version;
614 if (desired)
615 {
616 pick (desired != installed);
617 srcpick (false);
618 }
619 }
620 else
621 {
622 // else, if not installed, skip
623 desired = packageversion ();
624 pick(false);
625 }
626 }
627 else if (action == Install_action)
628 {
629 desired = default_version;
630 if (desired)
631 {
632 if (desired != installed)
633 if (desired.accessible ())
634 {
635 /* Memorize the fact that the user picked to install this package at least once. */
636 if (useraction)
637 user_picked = true;
638
639 pick (true);
640 srcpick (false);
641 }
642 else
643 {
644 pick (false);
645 srcpick (true);
646 }
647 else
648 {
649 action = NoChange_action;
650 pick (false);
651 srcpick (false);
652 }
653 }
654 }
655 else if (action == Reinstall_action)
656 {
657 desired = installed;
658 if (desired)
659 {
660 pick (true);
661 srcpick (false);
662 }
663 else
664 {
665 action = NoChange_action;
666 pick (false);
667 srcpick (false);
668 }
669 }
670 else if (action == Uninstall_action)
671 {
672 desired = packageversion ();
673 }
674
675 _action = action;
676 }
677
678 bool
679 packagemeta::picked () const
680 {
681 return _picked;
682 }
683
684 void
685 packagemeta::pick (bool picked)
686 {
687 _picked = picked;
688
689 // side effect: display message when picked (if not already seen)
690 if (picked)
691 this->message.display ();
692 }
693
694 bool
695 packagemeta::srcpicked () const
696 {
697 return _srcpicked;
698 }
699
700 void
701 packagemeta::srcpick (bool picked)
702 {
703 _srcpicked = picked;
704 }
705
706 bool
707 packagemeta::accessible () const
708 {
709 for (std::set<packageversion>::iterator i=versions.begin();
710 i != versions.end(); ++i)
711 if (i->accessible())
712 return true;
713 return false;
714 }
715
716 bool
717 packagemeta::sourceAccessible () const
718 {
719 for (std::set<packageversion>::iterator i=versions.begin();
720 i != versions.end(); ++i)
721 {
722 packageversion bin=*i;
723 if (bin.sourcePackage().accessible())
724 return true;
725 }
726
727 return false;
728 }
729
730 bool
731 packagemeta::isBinary () const
732 {
733 for (std::set<packageversion>::iterator i=versions.begin();
734 i != versions.end(); ++i)
735 if ((i->Type() == package_binary) && (i->accessible() || (*i == installed)))
736 return true;
737
738 return false;
739 }
740
741 void
742 packagemeta::logAllVersions () const
743 {
744 for (std::set<packageversion>::iterator i = versions.begin();
745 i != versions.end(); ++i)
746 {
747 Log (LOG_BABBLE) << " [" << trustLabel(*i) <<
748 "] ver=" << i->Canonical_version() << endLog;
749 std::ostream & logger = Log (LOG_BABBLE);
750 logger << " depends=";
751 dumpPackageDepends(i->depends(), logger);
752 logger << endLog;
753 }
754 #if 0
755 Log (LOG_BABBLE) << " inst=" << i->
756 /* FIXME: Reinstate this code, but spit out all mirror sites */
757
758 for (int t = 1; t < NTRUST; t++)
759 {
760 if (pkg->info[t].install)
761 Log (LOG_BABBLE) << " [%s] ver=%s\n"
762 " inst=%s %d exists=%s\n"
763 " src=%s %d exists=%s",
764 infos[t],
765 pkg->info[t].version ? : "(none)",
766 pkg->info[t].install ? : "(none)",
767 pkg->info[t].install_size,
768 (pkg->info[t].install_exists) ? "yes" : "no",
769 pkg->info[t].source ? : "(none)",
770 pkg->info[t].source_size,
771 (pkg->info[t].source_exists) ? "yes" : "no");
772 }
773 #endif
774 }
775
776 std::string
777 packagemeta::trustLabel(packageversion const &aVersion) const
778 {
779 if (aVersion == curr)
780 return "Curr";
781 if (aVersion == exp)
782 return "Test";
783 return "Unknown";
784 }
785
786 void
787 packagemeta::logSelectionStatus() const
788 {
789 packagemeta const & pkg = *this;
790 const char *trust = ((pkg.desired == pkg.curr) ? "curr"
791 : (pkg.desired == pkg.exp) ? "test" : "unknown");
792 const std::string installed =
793 pkg.installed ? pkg.installed.Canonical_version () : "none";
794
795 Log (LOG_BABBLE) << "[" << pkg.name << "] action=" << _action << " trust=" << trust << " installed=" << installed << " src?=" << (pkg.desired && srcpicked() ? "yes" : "no") << endLog;
796 if (pkg.categories.size ())
797 Log (LOG_BABBLE) << " categories=" << for_each(pkg.categories.begin(), pkg.categories.end(), StringConcatenator(", ")).result << endLog;
798 #if 0
799 if (pkg.desired.required())
800 {
801 /* List other packages this package depends on */
802 Dependency *dp = pkg.desired->required;
803 std::string requires = dp->package.serialise ();
804 for (dp = dp->next; dp; dp = dp->next)
805 requires += std::string (", ") + dp->package.serialise ();
806
807 Log (LOG_BABBLE) << " requires=" << requires;
808 }
809 #endif
810 pkg.logAllVersions();
811 }
812
813 /* scan for local copies of package */
814 bool
815 packagemeta::scan (const packageversion &pkg, bool mirror_mode)
816 {
817 /* empty version */
818 if (!pkg)
819 return false;
820
821 try
822 {
823 if (!check_for_cached (*(pkg.source ()), NULL, mirror_mode, false)
824 && ::source == IDC_SOURCE_LOCALDIR)
825 return false;
826 }
827 catch (Exception * e)
828 {
829 // We can ignore these, since we're clearing the source list anyway
830 if (e->errNo () == APPERR_CORRUPT_PACKAGE)
831 return false;
832
833 // Unexpected exception.
834 throw e;
835 }
836
837 return true;
838 }
839
840 void
841 packagemeta::ScanDownloadedFiles (bool mirror_mode)
842 {
843 /* Look at every known package, in all the known mirror dirs,
844 * and fill in the Cached attribute if it exists.
845 */
846 packagedb db;
847 for (packagedb::packagecollection::iterator n = db.packages.begin ();
848 n != db.packages.end (); ++n)
849 {
850 packagemeta & pkg = *(n->second);
851 std::set<packageversion>::iterator i = pkg.versions.begin ();
852 while (i != pkg.versions.end ())
853 {
854 /* scan doesn't alter operator == for packageversions */
855 bool lazy_scan = mirror_mode
856 && (*i != pkg.installed
857 || pkg.installed == pkg.curr
858 || pkg.installed == pkg.exp);
859 bool accessible = scan (*i, lazy_scan);
860 packageversion foo = *i;
861 packageversion pkgsrcver = foo.sourcePackage ();
862 bool src_accessible = scan (pkgsrcver, lazy_scan);
863
864 /* For local installs, if there is no src and no bin, the version
865 * is unavailable
866 */
867 if (!accessible && !src_accessible
868 && *i != pkg.installed)
869 {
870 if (pkg.curr == *i)
871 pkg.curr = packageversion ();
872 if (pkg.exp == *i)
873 pkg.exp = packageversion ();
874
875 i->remove();
876 pkg.versions.erase (i++);
877
878 /* For now, leave the source version alone */
879 }
880 else
881 ++i;
882 }
883 }
884 /* Don't explicity iterate through sources - any sources that aren't
885 referenced are unselectable anyway. */
886 }
887
888 void
889 packagemeta::addToCategoryBase()
890 {
891 add_category ("Base");
892 }
893
894 bool
895 packagemeta::hasNoCategories() const
896 {
897 return categories.size() == 0;
898 }
899
900 void
901 packagemeta::setDefaultCategories()
902 {
903 add_category ("Orphaned");
904 }
905
906 void
907 packagemeta::addToCategoryAll()
908 {
909 add_category ("All");
910 }
911
912 void
913 packagemeta::addScript(Script const &aScript)
914 {
915 scripts_.push_back(aScript);
916 }
917
918 std::vector <Script> &
919 packagemeta::scripts()
920 {
921 return scripts_;
922 }
This page took 0.076684 seconds and 5 git commands to generate.