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