]> cygwin.com Git - cygwin-apps/setup.git/blame_incremental - package_meta.cc
Added dpiAwareness element to manifest
[cygwin-apps/setup.git] / package_meta.cc
... / ...
CommitLineData
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
48static StringArrayOption DeletePackageOption ('x', "remove-packages", IDS_HELPTEXT_REMOVE_PACKAGES);
49static StringArrayOption DeleteCategoryOption ('c', "remove-categories", IDS_HELPTEXT_REMOVE_CATEGORIES);
50static StringArrayOption PackageOption ('P', "packages", IDS_HELPTEXT_PACKAGES);
51static StringArrayOption CategoryOption ('C', "categories", IDS_HELPTEXT_CATEGORIES);
52bool hasManualSelections = 0;
53
54/*****************/
55
56/* Return an appropriate category caption given the action */
57unsigned int
58packagemeta::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
75packagemeta::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
86template<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
98packagemeta::~packagemeta()
99{
100 for_each (categories.begin (), categories.end (), removeCategory<std::string> (this));
101 categories.clear ();
102 versions.clear ();
103}
104
105SolvableVersion
106packagemeta::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
219const packageversion *
220packagemeta::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
233bool
234packagemeta::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
247void
248packagemeta::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
262void
263packagemeta::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
272struct 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
286const std::string
287packagemeta::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
296static void
297parseNames (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
317static void
318validatePackageNames (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
332bool 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
430bool 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
481const std::string
482packagemeta::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
493static bool
494hasLDesc(packageversion const &pkg)
495{
496 return pkg.LDesc().size();
497}
498
499const std::string
500packagemeta::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. */
509std::wstring
510packagemeta::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
531void
532packagemeta::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)
565void
566packagemeta::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
584ActionList *
585packagemeta::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.
618void
619packagemeta::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
699bool
700packagemeta::picked () const
701{
702 return _picked;
703}
704
705void
706packagemeta::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
715bool
716packagemeta::srcpicked () const
717{
718 return _srcpicked;
719}
720
721void
722packagemeta::srcpick (bool picked)
723{
724 _srcpicked = picked;
725}
726
727bool
728packagemeta::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
737bool
738packagemeta::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
751bool
752packagemeta::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
762void
763packagemeta::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
797std::string
798packagemeta::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
807void
808packagemeta::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 */
835bool
836packagemeta::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
861void
862packagemeta::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
909void
910packagemeta::addToCategoryBase()
911{
912 add_category ("Base");
913}
914
915bool
916packagemeta::hasNoCategories() const
917{
918 return categories.size() == 0;
919}
920
921void
922packagemeta::setDefaultCategories()
923{
924 add_category ("Orphaned");
925}
926
927void
928packagemeta::addToCategoryAll()
929{
930 add_category ("All");
931}
932
933void
934packagemeta::addScript(Script const &aScript)
935{
936 scripts_.push_back(aScript);
937}
938
939std::vector <Script> &
940packagemeta::scripts()
941{
942 return scripts_;
943}
This page took 0.030399 seconds and 6 git commands to generate.