]> git.saurik.com Git - apt.git/blob - apt-private/private-install.cc
44980ceeda6926c38dff0713ebc66839a762c35b
[apt.git] / apt-private / private-install.cc
1 // Include Files /*{{{*/
2 #include <config.h>
3
4 #include <apt-pkg/acquire.h>
5 #include <apt-pkg/acquire-item.h>
6 #include <apt-pkg/algorithms.h>
7 #include <apt-pkg/cachefile.h>
8 #include <apt-pkg/cacheset.h>
9 #include <apt-pkg/cmndline.h>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/error.h>
12 #include <apt-pkg/fileutl.h>
13 #include <apt-pkg/pkgrecords.h>
14 #include <apt-pkg/pkgsystem.h>
15 #include <apt-pkg/sptr.h>
16 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/cacheiterators.h>
18 #include <apt-pkg/configuration.h>
19 #include <apt-pkg/macros.h>
20 #include <apt-pkg/packagemanager.h>
21 #include <apt-pkg/pkgcache.h>
22 #include <apt-pkg/upgrade.h>
23 #include <apt-pkg/install-progress.h>
24 #include <apt-pkg/prettyprinters.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <algorithm>
29 #include <iostream>
30 #include <set>
31 #include <vector>
32 #include <map>
33
34 #include <apt-private/acqprogress.h>
35 #include <apt-private/private-install.h>
36 #include <apt-private/private-cachefile.h>
37 #include <apt-private/private-cacheset.h>
38 #include <apt-private/private-download.h>
39 #include <apt-private/private-output.h>
40
41 #include <apti18n.h>
42 /*}}}*/
43 class pkgSourceList;
44
45 bool CheckNothingBroken(CacheFile &Cache) /*{{{*/
46 {
47 // Now we check the state of the packages,
48 if (Cache->BrokenCount() == 0)
49 return true;
50
51 c1out <<
52 _("Some packages could not be installed. This may mean that you have\n"
53 "requested an impossible situation or if you are using the unstable\n"
54 "distribution that some required packages have not yet been created\n"
55 "or been moved out of Incoming.") << std::endl;
56 /*
57 if (Packages == 1)
58 {
59 c1out << std::endl;
60 c1out <<
61 _("Since you only requested a single operation it is extremely likely that\n"
62 "the package is simply not installable and a bug report against\n"
63 "that package should be filed.") << std::endl;
64 }
65 */
66
67 c1out << _("The following information may help to resolve the situation:") << std::endl;
68 c1out << std::endl;
69 ShowBroken(c1out,Cache,false);
70 if (_error->PendingError() == true)
71 return false;
72 else
73 return _error->Error(_("Broken packages"));
74 }
75 /*}}}*/
76 // InstallPackages - Actually download and install the packages /*{{{*/
77 // ---------------------------------------------------------------------
78 /* This displays the informative messages describing what is going to
79 happen and then calls the download routines */
80 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
81 {
82 if (_config->FindB("APT::Get::Purge",false) == true)
83 {
84 pkgCache::PkgIterator I = Cache->PkgBegin();
85 for (; I.end() == false; ++I)
86 {
87 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
88 Cache->MarkDelete(I,true);
89 }
90 }
91
92 bool Hold = false;
93 bool Downgrade = false;
94 bool Essential = false;
95
96 // Show all the various warning indicators
97 ShowDel(c1out,Cache);
98 ShowNew(c1out,Cache);
99 if (ShwKept == true)
100 ShowKept(c1out,Cache);
101 Hold = !ShowHold(c1out,Cache);
102 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
103 ShowUpgraded(c1out,Cache);
104 Downgrade = !ShowDowngraded(c1out,Cache);
105
106 if (_config->FindB("APT::Get::Download-Only",false) == false)
107 Essential = !ShowEssential(c1out,Cache);
108
109 // All kinds of failures
110 bool Fail = (Essential || Downgrade || Hold);
111
112 Stats(c1out,Cache);
113
114 // Sanity check
115 if (Cache->BrokenCount() != 0)
116 {
117 ShowBroken(c1out,Cache,false);
118 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
119 }
120
121 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
122 Cache->BadCount() == 0)
123 return true;
124
125 // No remove flag
126 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
127 return _error->Error(_("Packages need to be removed but remove is disabled."));
128
129 // Fail safe check
130 if (_config->FindI("quiet",0) >= 2 ||
131 _config->FindB("APT::Get::Assume-Yes",false) == true)
132 {
133 if (_config->FindB("APT::Get::Force-Yes",false) == true) {
134 _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead."));
135 }
136
137 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) {
138 if (Essential == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
139 return _error->Error(_("Essential packages were removed and -y was used without --allow-remove-essential."));
140 if (Downgrade == true && _config->FindB("APT::Get::allow-downgrades", false) == false)
141 return _error->Error(_("Packages were downgraded and -y was used without --allow-downgrades."));
142 if (Hold == true && _config->FindB("APT::Get::allow-change-held-packages", false) == false)
143 return _error->Error(_("Held packages were changed and -y was used without --allow-change-held-packages."));
144 }
145 }
146
147 // Run the simulator ..
148 if (_config->FindB("APT::Get::Simulate") == true)
149 {
150 pkgSimulate PM(Cache);
151
152 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
153 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
154 delete progress;
155
156 if (Res == pkgPackageManager::Failed)
157 return false;
158 if (Res != pkgPackageManager::Completed)
159 return _error->Error(_("Internal error, Ordering didn't finish"));
160 return true;
161 }
162
163 // Create the text record parser
164 pkgRecords Recs(Cache);
165 if (_error->PendingError() == true)
166 return false;
167
168 // Create the download object
169 aptAcquireWithTextStatus Fetcher;
170 if (_config->FindB("APT::Get::Print-URIs", false) == true)
171 {
172 // force a hashsum for compatibility reasons
173 _config->CndSet("Acquire::ForceHash", "md5sum");
174 }
175 else if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false)
176 return false;
177
178 // Read the source list
179 if (Cache.BuildSourceList() == false)
180 return false;
181 pkgSourceList *List = Cache.GetSourceList();
182
183 // Create the package manager and prepare to download
184 std::unique_ptr<pkgPackageManager> PM(_system->CreatePM(Cache));
185 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
186 _error->PendingError() == true)
187 return false;
188
189 // Display statistics
190 unsigned long long FetchBytes = Fetcher.FetchNeeded();
191 unsigned long long FetchPBytes = Fetcher.PartialPresent();
192 unsigned long long DebBytes = Fetcher.TotalNeeded();
193 if (DebBytes != Cache->DebSize())
194 {
195 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
196 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
197 }
198
199 // Number of bytes
200 if (DebBytes != FetchBytes)
201 //TRANSLATOR: The required space between number and unit is already included
202 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
203 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
204 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
205 else if (DebBytes != 0)
206 //TRANSLATOR: The required space between number and unit is already included
207 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
208 ioprintf(c1out,_("Need to get %sB of archives.\n"),
209 SizeToStr(DebBytes).c_str());
210
211 // Size delta
212 if (Cache->UsrSize() >= 0)
213 //TRANSLATOR: The required space between number and unit is already included
214 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
215 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
216 SizeToStr(Cache->UsrSize()).c_str());
217 else
218 //TRANSLATOR: The required space between number and unit is already included
219 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
220 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
221 SizeToStr(-1*Cache->UsrSize()).c_str());
222
223 if (_error->PendingError() == true)
224 return false;
225
226 if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false)
227 return false;
228
229 if (Essential == true && Safety == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
230 {
231 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
232 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
233
234 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
235 // careful with hard to type or special characters (like non-breaking spaces)
236 const char *Prompt = _("Yes, do as I say!");
237 std::string question;
238 strprintf(question,
239 _("You are about to do something potentially harmful.\n"
240 "To continue type in the phrase '%s'\n"
241 " ?] "),Prompt);
242 if (AnalPrompt(question, Prompt) == false)
243 {
244 c2out << _("Abort.") << std::endl;
245 exit(1);
246 }
247 }
248 else
249 {
250 // Prompt to continue
251 if (Ask == true || Fail == true)
252 {
253 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
254 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
255
256 if (_config->FindI("quiet",0) < 2 &&
257 _config->FindB("APT::Get::Assume-Yes",false) == false)
258 {
259 if (YnPrompt(_("Do you want to continue?")) == false)
260 {
261 c2out << _("Abort.") << std::endl;
262 exit(1);
263 }
264 }
265 }
266 }
267
268 // Just print out the uris an exit if the --print-uris flag was used
269 if (_config->FindB("APT::Get::Print-URIs") == true)
270 {
271 pkgAcquire::UriIterator I = Fetcher.UriBegin();
272 for (; I != Fetcher.UriEnd(); ++I)
273 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
274 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
275 return true;
276 }
277
278 if (!CheckAuth(Fetcher, true))
279 return false;
280
281 /* Unlock the dpkg lock if we are not going to be doing an install
282 after. */
283 if (_config->FindB("APT::Get::Download-Only",false) == true)
284 _system->UnLock();
285
286 // Run it
287 while (1)
288 {
289 bool Transient = false;
290 if (_config->FindB("APT::Get::Download",true) == false)
291 {
292 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
293 {
294 if ((*I)->Local == true)
295 {
296 ++I;
297 continue;
298 }
299
300 // Close the item and check if it was found in cache
301 (*I)->Finished();
302 if ((*I)->Complete == false)
303 Transient = true;
304
305 // Clear it out of the fetch list
306 delete *I;
307 I = Fetcher.ItemsBegin();
308 }
309 }
310
311 bool Failed = false;
312 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
313 return false;
314
315 /* If we are in no download mode and missing files and there were
316 'failures' then the user must specify -m. Furthermore, there
317 is no such thing as a transient error in no-download mode! */
318 if (Transient == true &&
319 _config->FindB("APT::Get::Download",true) == false)
320 {
321 Transient = false;
322 Failed = true;
323 }
324
325 if (_config->FindB("APT::Get::Download-Only",false) == true)
326 {
327 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
328 return _error->Error(_("Some files failed to download"));
329 c1out << _("Download complete and in download only mode") << std::endl;
330 return true;
331 }
332
333 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
334 {
335 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
336 }
337
338 if (Transient == true && Failed == true)
339 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
340
341 // Try to deal with missing package files
342 if (Failed == true && PM->FixMissing() == false)
343 {
344 c2out << _("Unable to correct missing packages.") << std::endl;
345 return _error->Error(_("Aborting install."));
346 }
347
348 _system->UnLock();
349
350 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
351 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
352 delete progress;
353
354 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
355 return false;
356 if (Res == pkgPackageManager::Completed)
357 break;
358
359 // Reload the fetcher object and loop again for media swapping
360 Fetcher.Shutdown();
361 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
362 return false;
363
364 _system->Lock();
365 }
366
367 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
368 if (disappearedPkgs.empty() == false)
369 {
370 ShowList(c1out, P_("The following package disappeared from your system as\n"
371 "all files have been overwritten by other packages:",
372 "The following packages disappeared from your system as\n"
373 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappearedPkgs,
374 [](std::string const &Pkg) { return Pkg.empty() == false; },
375 [](std::string const &Pkg) { return Pkg; },
376 [](std::string const &) { return std::string(); });
377 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
378 }
379
380 // cleanup downloaded debs
381 if (_config->FindB("APT::Keep-Downloaded-Packages", true) == false)
382 {
383 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
384 for (auto I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
385 {
386 if (flNotFile((*I)->DestFile) != archivedir || (*I)->Local)
387 continue;
388 RemoveFile("Keep-Downloaded-Packages=false", (*I)->DestFile);
389 }
390 }
391
392 return true;
393 }
394 /*}}}*/
395 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
396 // ---------------------------------------------------------------------
397 /* Remove unused automatic packages */
398 bool DoAutomaticRemove(CacheFile &Cache)
399 {
400 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
401 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
402 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
403
404 pkgDepCache::ActionGroup group(*Cache);
405 if(Debug)
406 std::cout << "DoAutomaticRemove()" << std::endl;
407
408 if (doAutoRemove == true &&
409 _config->FindB("APT::Get::Remove",true) == false)
410 {
411 c1out << _("We are not supposed to delete stuff, can't start "
412 "AutoRemover") << std::endl;
413 return false;
414 }
415
416 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
417 bool smallList = (hideAutoRemove == false &&
418 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
419
420 unsigned long autoRemoveCount = 0;
421 APT::PackageSet tooMuch;
422 SortedPackageUniverse Universe(Cache);
423 // look over the cache to see what can be removed
424 for (auto const &Pkg: Universe)
425 {
426 if (Cache[Pkg].Garbage)
427 {
428 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
429 if(Debug)
430 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
431
432 if (doAutoRemove)
433 {
434 if(Pkg.CurrentVer() != 0 &&
435 Pkg->CurrentState != pkgCache::State::ConfigFiles)
436 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
437 else
438 Cache->MarkKeep(Pkg, false, false);
439 }
440 else
441 {
442 // if the package is a new install and already garbage we don't need to
443 // install it in the first place, so nuke it instead of show it
444 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
445 {
446 tooMuch.insert(Pkg);
447 Cache->MarkDelete(Pkg, false, 0, false);
448 }
449 // only show stuff in the list that is not yet marked for removal
450 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
451 ++autoRemoveCount;
452 }
453 }
454 }
455
456 // we could have removed a new dependency of a garbage package,
457 // so check if a reverse depends is broken and if so install it again.
458 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
459 {
460 bool Changed;
461 do {
462 Changed = false;
463 for (APT::PackageSet::iterator Pkg = tooMuch.begin();
464 Pkg != tooMuch.end(); ++Pkg)
465 {
466 APT::PackageSet too;
467 too.insert(*Pkg);
468 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
469 Prv.end() == false; ++Prv)
470 too.insert(Prv.ParentPkg());
471 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
472 {
473 for (pkgCache::DepIterator R = P.RevDependsList();
474 R.end() == false; ++R)
475 {
476 if (R.IsNegative() == true ||
477 Cache->IsImportantDep(R) == false)
478 continue;
479 pkgCache::PkgIterator N = R.ParentPkg();
480 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
481 continue;
482 if (Debug == true)
483 std::clog << "Save " << APT::PrettyPkg(Cache, Pkg) << " as another installed garbage package depends on it" << std::endl;
484 Cache->MarkInstall(Pkg, false, 0, false);
485 if (hideAutoRemove == false)
486 ++autoRemoveCount;
487 tooMuch.erase(Pkg);
488 Changed = true;
489 break;
490 }
491 if (Changed == true)
492 break;
493 }
494 if (Changed == true)
495 break;
496 }
497 } while (Changed == true);
498 }
499
500 // Now see if we had destroyed anything (if we had done anything)
501 if (Cache->BrokenCount() != 0)
502 {
503 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
504 "shouldn't happen. Please file a bug report against apt.") << std::endl;
505 c1out << std::endl;
506 c1out << _("The following information may help to resolve the situation:") << std::endl;
507 c1out << std::endl;
508 ShowBroken(c1out,Cache,false);
509
510 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
511 }
512
513 // if we don't remove them, we should show them!
514 if (doAutoRemove == false && autoRemoveCount != 0)
515 {
516 if (smallList == false)
517 {
518 SortedPackageUniverse Universe(Cache);
519 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
520 "The following packages were automatically installed and are no longer required:",
521 autoRemoveCount), Universe,
522 [&Cache](pkgCache::PkgIterator const &Pkg) { return (*Cache)[Pkg].Garbage == true && (*Cache)[Pkg].Delete() == false; },
523 &PrettyFullName, CandidateVersion(&Cache));
524 }
525 else
526 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
527 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
528 std::string autocmd = "apt autoremove";
529 if (getenv("SUDO_USER") != NULL)
530 autocmd = "sudo " + autocmd;
531 ioprintf(c1out, P_("Use '%s' to remove it.", "Use '%s' to remove them.", autoRemoveCount), autocmd.c_str());
532 c1out << std::endl;
533 }
534 return true;
535 }
536 /*}}}*/
537 // DoCacheManipulationFromCommandLine /*{{{*/
538 static const unsigned short MOD_REMOVE = 1;
539 static const unsigned short MOD_INSTALL = 2;
540
541 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
542 {
543 std::vector<const char*> VolatileCmdL;
544 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
545 }
546 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
547 {
548 std::map<unsigned short, APT::VersionSet> verset;
549 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode);
550 }
551 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache,
552 std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
553 {
554 // Enter the special broken fixing mode if the user specified arguments
555 bool BrokenFix = false;
556 if (Cache->BrokenCount() != 0)
557 BrokenFix = true;
558
559 std::unique_ptr<pkgProblemResolver> Fix(nullptr);
560 if (_config->FindB("APT::Get::CallResolver", true) == true)
561 Fix.reset(new pkgProblemResolver(Cache));
562
563 unsigned short fallback = MOD_INSTALL;
564 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
565 fallback = MOD_REMOVE;
566 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
567 {
568 _config->Set("APT::Get::Purge", true);
569 fallback = MOD_REMOVE;
570 }
571 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0 ||
572 strcasecmp(CmdL.FileList[0], "auto-remove") == 0)
573 {
574 _config->Set("APT::Get::AutomaticRemove", "true");
575 fallback = MOD_REMOVE;
576 }
577
578 std::list<APT::VersionSet::Modifier> mods;
579 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
580 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::CANDIDATE));
581 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
582 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::NEWEST));
583 CacheSetHelperAPTGet helper(c0out);
584 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
585 CmdL.FileList + 1, mods, fallback, helper);
586
587 for (auto const &I: VolatileCmdL)
588 {
589 pkgCache::PkgIterator const P = Cache->FindPkg(I);
590 if (P.end())
591 continue;
592
593 // Set any version providing the .deb as the candidate.
594 for (auto Prv = P.ProvidesList(); Prv.end() == false; Prv++)
595 Cache.GetDepCache()->SetCandidateVersion(Prv.OwnerVer());
596
597 // via cacheset to have our usual virtual handling
598 APT::VersionContainerInterface::FromPackage(&(verset[MOD_INSTALL]), Cache, P, APT::CacheSetHelper::CANDIDATE, helper);
599 }
600
601 if (_error->PendingError() == true)
602 {
603 helper.showVirtualPackageErrors(Cache);
604 return false;
605 }
606
607
608 TryToInstall InstallAction(Cache, Fix.get(), BrokenFix);
609 TryToRemove RemoveAction(Cache, Fix.get());
610
611 // new scope for the ActionGroup
612 {
613 pkgDepCache::ActionGroup group(Cache);
614 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
615
616 for (unsigned short i = 0; order[i] != 0; ++i)
617 {
618 if (order[i] == MOD_INSTALL)
619 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
620 else if (order[i] == MOD_REMOVE)
621 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
622 }
623
624 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
625 {
626 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
627 InstallAction.doAutoInstall();
628 }
629
630 if (_error->PendingError() == true)
631 {
632 return false;
633 }
634
635 /* If we are in the Broken fixing mode we do not attempt to fix the
636 problems. This is if the user invoked install without -f and gave
637 packages */
638 if (BrokenFix == true && Cache->BrokenCount() != 0)
639 {
640 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
641 ShowBroken(c1out,Cache,false);
642 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
643 }
644
645 if (Fix != NULL)
646 {
647 // Call the scored problem resolver
648 OpTextProgress Progress(*_config);
649 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
650
651 bool resolver_fail = false;
652 if (distUpgradeMode == true || UpgradeMode != APT::Upgrade::ALLOW_EVERYTHING)
653 resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
654 else
655 resolver_fail = Fix->Resolve(true, &Progress);
656
657 if (resolver_fail == false && Cache->BrokenCount() == 0)
658 return false;
659 }
660
661 if (CheckNothingBroken(Cache) == false)
662 return false;
663 }
664 if (!DoAutomaticRemove(Cache))
665 return false;
666
667 // if nothing changed in the cache, but only the automark information
668 // we write the StateFile here, otherwise it will be written in
669 // cache.commit()
670 if (InstallAction.AutoMarkChanged > 0 &&
671 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
672 Cache->BadCount() == 0 &&
673 _config->FindB("APT::Get::Simulate",false) == false)
674 Cache->writeStateFile(NULL);
675
676 return true;
677 }
678 /*}}}*/
679 // DoInstall - Install packages from the command line /*{{{*/
680 // ---------------------------------------------------------------------
681 /* Install named packages */
682 struct PkgIsExtraInstalled {
683 pkgCacheFile * const Cache;
684 APT::VersionSet const * const verset;
685 PkgIsExtraInstalled(pkgCacheFile * const Cache, APT::VersionSet const * const Container) : Cache(Cache), verset(Container) {}
686 bool operator() (pkgCache::PkgIterator const &Pkg)
687 {
688 if ((*Cache)[Pkg].Install() == false)
689 return false;
690 pkgCache::VerIterator const Cand = (*Cache)[Pkg].CandidateVerIter(*Cache);
691 return verset->find(Cand) == verset->end();
692 }
693 };
694 bool DoInstall(CommandLine &CmdL)
695 {
696 CacheFile Cache;
697 std::vector<char const *> VolatileCmdL;
698 Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
699
700 // then open the cache
701 if (Cache.OpenForInstall() == false ||
702 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
703 return false;
704
705 std::map<unsigned short, APT::VersionSet> verset;
706 if(!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, 0))
707 return false;
708
709 /* Print out a list of packages that are going to be installed extra
710 to what the user asked */
711 SortedPackageUniverse Universe(Cache);
712 if (Cache->InstCount() != verset[MOD_INSTALL].size())
713 ShowList(c1out, _("The following additional packages will be installed:"), Universe,
714 PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]),
715 &PrettyFullName, CandidateVersion(&Cache));
716
717 /* Print out a list of suggested and recommended packages */
718 {
719 std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
720 for (auto const &Pkg: Universe)
721 {
722 /* Just look at the ones we want to install */
723 if ((*Cache)[Pkg].Install() == false)
724 continue;
725
726 // get the recommends/suggests for the candidate ver
727 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
728 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
729 {
730 pkgCache::DepIterator Start;
731 pkgCache::DepIterator End;
732 D.GlobOr(Start,End); // advances D
733 if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
734 continue;
735
736 {
737 // Skip if we already saw this
738 std::string target;
739 for (pkgCache::DepIterator I = Start; I != D; ++I)
740 {
741 if (target.empty() == false)
742 target.append(" | ");
743 target.append(I.TargetPkg().FullName(true));
744 }
745 std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests;
746 if (std::find(Type.begin(), Type.end(), target) != Type.end())
747 continue;
748 Type.push_back(target);
749 }
750
751 std::list<std::string> OrList;
752 bool foundInstalledInOrGroup = false;
753 for (pkgCache::DepIterator I = Start; I != D; ++I)
754 {
755 {
756 // satisfying package is installed and not marked for deletion
757 APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED);
758 if (std::find_if(installed.begin(), installed.end(),
759 [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end())
760 {
761 foundInstalledInOrGroup = true;
762 break;
763 }
764 }
765
766 {
767 // satisfying package is upgraded to/new install
768 APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE);
769 if (std::find_if(upgrades.begin(), upgrades.end(),
770 [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end())
771 {
772 foundInstalledInOrGroup = true;
773 break;
774 }
775 }
776
777 if (OrList.empty())
778 OrList.push_back(I.TargetPkg().FullName(true));
779 else
780 OrList.push_back("| " + I.TargetPkg().FullName(true));
781 }
782
783 if(foundInstalledInOrGroup == false)
784 {
785 std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
786 std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
787 }
788 }
789 }
790 auto always_true = [](std::string const&) { return true; };
791 auto string_ident = [](std::string const&str) { return str; };
792 auto verbose_show_candidate =
793 [&Cache](std::string str)
794 {
795 if (APT::String::Startswith(str, "| "))
796 str.erase(0, 2);
797 pkgCache::PkgIterator const Pkg = Cache->FindPkg(str);
798 if (Pkg.end() == true)
799 return "";
800 return (*Cache)[Pkg].CandVersion;
801 };
802 ShowList(c1out,_("Suggested packages:"), Suggests,
803 always_true, string_ident, verbose_show_candidate);
804 ShowList(c1out,_("Recommended packages:"), Recommends,
805 always_true, string_ident, verbose_show_candidate);
806 }
807
808 // See if we need to prompt
809 // FIXME: check if really the packages in the set are going to be installed
810 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
811 return InstallPackages(Cache,false,false);
812
813 return InstallPackages(Cache,false);
814 }
815 /*}}}*/
816
817 // TryToInstall - Mark a package for installation /*{{{*/
818 void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
819 if (unlikely(Ver.end()))
820 {
821 _error->Fatal("The given version to TryToInstall is invalid!");
822 return;
823 }
824 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
825 if (unlikely(Pkg.end()))
826 {
827 _error->Fatal("The given version to TryToInstall has an invalid parent package!");
828 return;
829 }
830
831 Cache->GetDepCache()->SetCandidateVersion(Ver);
832 pkgDepCache::StateCache &State = (*Cache)[Pkg];
833
834 // Handle the no-upgrade case
835 if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
836 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
837 Pkg.FullName(true).c_str());
838 // Ignore request for install if package would be new
839 else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
840 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
841 Pkg.FullName(true).c_str());
842 else {
843 if (Fix != NULL) {
844 Fix->Clear(Pkg);
845 Fix->Protect(Pkg);
846 }
847 Cache->GetDepCache()->MarkInstall(Pkg,false);
848
849 if (State.Install() == false) {
850 if (_config->FindB("APT::Get::ReInstall",false) == true) {
851 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
852 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
853 Pkg.FullName(true).c_str());
854 else
855 Cache->GetDepCache()->SetReInstall(Pkg, true);
856 } else
857 // TRANSLATORS: First string is package name, second is version
858 ioprintf(c1out,_("%s is already the newest version (%s).\n"),
859 Pkg.FullName(true).c_str(), Pkg.CurrentVer().VerStr());
860 }
861
862 // Install it with autoinstalling enabled (if we not respect the minial
863 // required deps or the policy)
864 if (FixBroken == false)
865 doAutoInstallLater.insert(Pkg);
866 }
867
868 // see if we need to fix the auto-mark flag
869 // e.g. apt-get install foo
870 // where foo is marked automatic
871 if (State.Install() == false &&
872 (State.Flags & pkgCache::Flag::Auto) &&
873 _config->FindB("APT::Get::ReInstall",false) == false &&
874 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
875 _config->FindB("APT::Get::Download-Only",false) == false)
876 {
877 ioprintf(c1out,_("%s set to manually installed.\n"),
878 Pkg.FullName(true).c_str());
879 Cache->GetDepCache()->MarkAuto(Pkg,false);
880 AutoMarkChanged++;
881 }
882 }
883 /*}}}*/
884 bool TryToInstall::propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out)/*{{{*/
885 {
886 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
887 s != start.end(); ++s)
888 Cache->GetDepCache()->SetCandidateVersion(s->first);
889
890 bool Success = true;
891 // the Changed list contains:
892 // first: "new version"
893 // second: "what-caused the change"
894 std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
895 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
896 s != start.end(); ++s)
897 {
898 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
899 // We continue here even if it failed to enhance the ShowBroken output
900 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
901 }
902 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
903 c != Changed.end(); ++c)
904 {
905 if (c->second.end() == true)
906 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
907 c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
908 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
909 {
910 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
911 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
912 V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
913 }
914 }
915 return Success;
916 }
917 /*}}}*/
918 void TryToInstall::doAutoInstall() { /*{{{*/
919 for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
920 P != doAutoInstallLater.end(); ++P) {
921 pkgDepCache::StateCache &State = (*Cache)[P];
922 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
923 continue;
924 Cache->GetDepCache()->MarkInstall(P, true);
925 }
926 doAutoInstallLater.clear();
927 }
928 /*}}}*/
929 // TryToRemove - Mark a package for removal /*{{{*/
930 void TryToRemove::operator() (pkgCache::VerIterator const &Ver)
931 {
932 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
933
934 if (Fix != NULL)
935 {
936 Fix->Clear(Pkg);
937 Fix->Protect(Pkg);
938 Fix->Remove(Pkg);
939 }
940
941 if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
942 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
943 {
944 pkgCache::GrpIterator Grp = Pkg.Group();
945 pkgCache::PkgIterator P = Grp.PackageList();
946 for (; P.end() != true; P = Grp.NextPkg(P))
947 {
948 if (P == Pkg)
949 continue;
950 if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
951 {
952 // TRANSLATORS: Note, this is not an interactive question
953 ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
954 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
955 break;
956 }
957 }
958 if (P.end() == true)
959 ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
960
961 // MarkInstall refuses to install packages on hold
962 Pkg->SelectedState = pkgCache::State::Hold;
963 }
964 else
965 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
966 }
967 /*}}}*/