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