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