]> git.saurik.com Git - apt.git/blame - apt-private/private-install.cc
apt-private: #ifdef HAVE_STRUCT_STATFS_F_TYPE, not #if
[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
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 /*}}}*/
b9179170
MV
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 */
eb1f04dd 80static void RemoveDownloadNeedingItemsFromFetcher(pkgAcquire &Fetcher, bool &Transient)
b9179170 81{
eb1f04dd 82 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
b9179170 83 {
eb1f04dd 84 if ((*I)->Local == true)
b9179170 85 {
eb1f04dd
DK
86 ++I;
87 continue;
b9179170 88 }
eb1f04dd
DK
89
90 // Close the item and check if it was found in cache
91 (*I)->Finished();
92 if ((*I)->Complete == false)
93 Transient = true;
94
95 // Clear it out of the fetch list
96 delete *I;
97 I = Fetcher.ItemsBegin();
b9179170 98 }
eb1f04dd
DK
99}
100bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
101{
102 if (_config->FindB("APT::Get::Purge", false) == true)
103 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I)
104 if (Cache[I].Delete() == true && Cache[I].Purge() == false)
105 Cache->MarkDelete(I,true);
106
107 // Create the download object
108 aptAcquireWithTextStatus Fetcher;
109 if (_config->FindB("APT::Get::Print-URIs", false) == true)
110 {
111 // force a hashsum for compatibility reasons
112 _config->CndSet("Acquire::ForceHash", "md5sum");
113 }
1bae1021
DK
114 else if (_config->FindB("APT::Get::Simulate") == true)
115 ;
eb1f04dd
DK
116 else if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false)
117 return false;
118
119 // Read the source list
120 if (Cache.BuildSourceList() == false)
121 return false;
122 pkgSourceList * const List = Cache.GetSourceList();
123
124 // Create the text record parser
125 pkgRecords Recs(Cache);
126 if (_error->PendingError() == true)
127 return false;
128
129 // Create the package manager and prepare to download
130 std::unique_ptr<pkgPackageManager> PM(_system->CreatePM(Cache));
131 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
132 _error->PendingError() == true)
133 return false;
134
135 if (_config->FindB("APT::Get::Fix-Missing",false) == true &&
136 _config->FindB("APT::Get::Download",true) == false)
137 {
138 bool Missing = false;
139 RemoveDownloadNeedingItemsFromFetcher(Fetcher, Missing);
140 if (Missing)
141 PM->FixMissing();
142 Fetcher.Shutdown();
143 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
144 _error->PendingError() == true)
145 return false;
146 }
147
b9179170
MV
148 // Show all the various warning indicators
149 ShowDel(c1out,Cache);
150 ShowNew(c1out,Cache);
151 if (ShwKept == true)
152 ShowKept(c1out,Cache);
eb1f04dd 153 bool const Hold = !ShowHold(c1out,Cache);
b9179170
MV
154 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
155 ShowUpgraded(c1out,Cache);
eb1f04dd 156 bool const Downgrade = !ShowDowngraded(c1out,Cache);
b381a482 157
eb1f04dd 158 bool Essential = false;
b9179170
MV
159 if (_config->FindB("APT::Get::Download-Only",false) == false)
160 Essential = !ShowEssential(c1out,Cache);
b381a482 161
b9179170
MV
162 Stats(c1out,Cache);
163
164 // Sanity check
165 if (Cache->BrokenCount() != 0)
166 {
167 ShowBroken(c1out,Cache,false);
168 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
169 }
170
171 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
172 Cache->BadCount() == 0)
173 return true;
174
175 // No remove flag
176 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
177 return _error->Error(_("Packages need to be removed but remove is disabled."));
b381a482
JAK
178
179 // Fail safe check
eb1f04dd 180 bool const Fail = (Essential || Downgrade || Hold);
b381a482
JAK
181 if (_config->FindI("quiet",0) >= 2 ||
182 _config->FindB("APT::Get::Assume-Yes",false) == true)
183 {
184 if (_config->FindB("APT::Get::Force-Yes",false) == true) {
185 _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead."));
186 }
187
188 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) {
189 if (Essential == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
190 return _error->Error(_("Essential packages were removed and -y was used without --allow-remove-essential."));
191 if (Downgrade == true && _config->FindB("APT::Get::allow-downgrades", false) == false)
192 return _error->Error(_("Packages were downgraded and -y was used without --allow-downgrades."));
193 if (Hold == true && _config->FindB("APT::Get::allow-change-held-packages", false) == false)
194 return _error->Error(_("Held packages were changed and -y was used without --allow-change-held-packages."));
195 }
196 }
197
b9179170
MV
198 // Run the simulator ..
199 if (_config->FindB("APT::Get::Simulate") == true)
200 {
201 pkgSimulate PM(Cache);
5e9458e2 202
bd5f39b3 203 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
204 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
205 delete progress;
5e9458e2 206
b9179170
MV
207 if (Res == pkgPackageManager::Failed)
208 return false;
209 if (Res != pkgPackageManager::Completed)
210 return _error->Error(_("Internal error, Ordering didn't finish"));
211 return true;
212 }
b9179170
MV
213
214 // Display statistics
eb1f04dd
DK
215 auto const FetchBytes = Fetcher.FetchNeeded();
216 auto const FetchPBytes = Fetcher.PartialPresent();
217 auto const DebBytes = Fetcher.TotalNeeded();
b9179170
MV
218 if (DebBytes != Cache->DebSize())
219 {
220 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
1166ea79 221 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
b9179170
MV
222 }
223
224 // Number of bytes
225 if (DebBytes != FetchBytes)
226 //TRANSLATOR: The required space between number and unit is already included
227 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
228 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
229 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
230 else if (DebBytes != 0)
231 //TRANSLATOR: The required space between number and unit is already included
232 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
233 ioprintf(c1out,_("Need to get %sB of archives.\n"),
234 SizeToStr(DebBytes).c_str());
235
236 // Size delta
237 if (Cache->UsrSize() >= 0)
238 //TRANSLATOR: The required space between number and unit is already included
239 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
240 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
241 SizeToStr(Cache->UsrSize()).c_str());
242 else
243 //TRANSLATOR: The required space between number and unit is already included
244 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
245 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
246 SizeToStr(-1*Cache->UsrSize()).c_str());
247
eb1f04dd 248 if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false)
b9179170
MV
249 return false;
250
eb1f04dd 251 if (_error->PendingError() == true)
9c81f8de
DK
252 return false;
253
eb1f04dd
DK
254 // Just print out the uris an exit if the --print-uris flag was used
255 if (_config->FindB("APT::Get::Print-URIs") == true)
256 {
257 pkgAcquire::UriIterator I = Fetcher.UriBegin();
258 for (; I != Fetcher.UriEnd(); ++I)
259 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
b58e2c7c 260 std::to_string(I->Owner->FileSize) << ' ' << I->Owner->HashSum() << std::endl;
eb1f04dd
DK
261 return true;
262 }
263
b381a482 264 if (Essential == true && Safety == true && _config->FindB("APT::Get::allow-remove-essential", false) == false)
b9179170
MV
265 {
266 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
267 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
268
269 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
270 // careful with hard to type or special characters (like non-breaking spaces)
271 const char *Prompt = _("Yes, do as I say!");
fd789740
DK
272 std::string question;
273 strprintf(question,
b9179170
MV
274 _("You are about to do something potentially harmful.\n"
275 "To continue type in the phrase '%s'\n"
276 " ?] "),Prompt);
fd789740 277 if (AnalPrompt(question, Prompt) == false)
b9179170
MV
278 {
279 c2out << _("Abort.") << std::endl;
280 exit(1);
eb1f04dd 281 }
b9179170
MV
282 }
283 else
eb1f04dd 284 {
b9179170
MV
285 // Prompt to continue
286 if (Ask == true || Fail == true)
eb1f04dd 287 {
b9179170
MV
288 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
289 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
eb1f04dd 290
b9179170
MV
291 if (_config->FindI("quiet",0) < 2 &&
292 _config->FindB("APT::Get::Assume-Yes",false) == false)
293 {
eb1f04dd 294 if (YnPrompt(_("Do you want to continue?")) == false)
b9179170
MV
295 {
296 c2out << _("Abort.") << std::endl;
297 exit(1);
eb1f04dd
DK
298 }
299 }
300 }
b9179170
MV
301 }
302
866893a6 303 if (!CheckAuth(Fetcher, true))
b9179170
MV
304 return false;
305
306 /* Unlock the dpkg lock if we are not going to be doing an install
307 after. */
308 if (_config->FindB("APT::Get::Download-Only",false) == true)
309 _system->UnLock();
eb1f04dd 310
b9179170 311 // Run it
eb1f04dd 312 bool Failed = false;
b9179170
MV
313 while (1)
314 {
315 bool Transient = false;
866893a6
DK
316 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
317 return false;
b9179170 318
b9179170
MV
319 if (_config->FindB("APT::Get::Download-Only",false) == true)
320 {
321 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
322 return _error->Error(_("Some files failed to download"));
323 c1out << _("Download complete and in download only mode") << std::endl;
324 return true;
325 }
eb1f04dd 326
b9179170 327 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
b9179170 328 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
eb1f04dd 329
b9179170
MV
330 if (Transient == true && Failed == true)
331 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
eb1f04dd 332
b9179170
MV
333 // Try to deal with missing package files
334 if (Failed == true && PM->FixMissing() == false)
335 {
336 c2out << _("Unable to correct missing packages.") << std::endl;
337 return _error->Error(_("Aborting install."));
338 }
339
eb1f04dd 340 auto const progress = APT::Progress::PackageManagerProgressFactory();
b9179170 341 _system->UnLock();
eb1f04dd 342 pkgPackageManager::OrderResult const Res = PM->DoInstall(progress);
e6ad8031
MV
343 delete progress;
344
b9179170
MV
345 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
346 return false;
347 if (Res == pkgPackageManager::Completed)
348 break;
eb1f04dd
DK
349
350 _system->Lock();
351
b9179170
MV
352 // Reload the fetcher object and loop again for media swapping
353 Fetcher.Shutdown();
354 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
355 return false;
eb1f04dd
DK
356
357 Failed = false;
358 if (_config->FindB("APT::Get::Download",true) == false)
359 RemoveDownloadNeedingItemsFromFetcher(Fetcher, Failed);
b9179170
MV
360 }
361
362 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
9112f777
DK
363 if (disappearedPkgs.empty() == false)
364 {
365 ShowList(c1out, P_("The following package disappeared from your system as\n"
366 "all files have been overwritten by other packages:",
367 "The following packages disappeared from your system as\n"
368 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappearedPkgs,
369 [](std::string const &Pkg) { return Pkg.empty() == false; },
370 [](std::string const &Pkg) { return Pkg; },
371 [](std::string const &) { return std::string(); });
372 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
373 }
b9179170 374
ee02b5b3
MV
375 // cleanup downloaded debs
376 if (_config->FindB("APT::Keep-Downloaded-Packages", true) == false)
377 {
378 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
379 for (auto I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
380 {
381 if (flNotFile((*I)->DestFile) != archivedir || (*I)->Local)
382 continue;
383 RemoveFile("Keep-Downloaded-Packages=false", (*I)->DestFile);
384 }
385 }
386
b9179170
MV
387 return true;
388}
389 /*}}}*/
b9179170
MV
390// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
391// ---------------------------------------------------------------------
392/* Remove unused automatic packages */
a249b3e6 393bool DoAutomaticRemove(CacheFile &Cache)
b9179170
MV
394{
395 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
396 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
397 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
398
399 pkgDepCache::ActionGroup group(*Cache);
400 if(Debug)
401 std::cout << "DoAutomaticRemove()" << std::endl;
402
403 if (doAutoRemove == true &&
404 _config->FindB("APT::Get::Remove",true) == false)
405 {
406 c1out << _("We are not supposed to delete stuff, can't start "
407 "AutoRemover") << std::endl;
408 return false;
409 }
410
411 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
412 bool smallList = (hideAutoRemove == false &&
413 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
414
415 unsigned long autoRemoveCount = 0;
416 APT::PackageSet tooMuch;
a0c19a21 417 SortedPackageUniverse Universe(Cache);
b9179170 418 // look over the cache to see what can be removed
a0c19a21 419 for (auto const &Pkg: Universe)
b9179170 420 {
b9179170
MV
421 if (Cache[Pkg].Garbage)
422 {
423 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
424 if(Debug)
425 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
426
427 if (doAutoRemove)
428 {
429 if(Pkg.CurrentVer() != 0 &&
430 Pkg->CurrentState != pkgCache::State::ConfigFiles)
431 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
432 else
433 Cache->MarkKeep(Pkg, false, false);
434 }
435 else
436 {
b9179170
MV
437 // if the package is a new install and already garbage we don't need to
438 // install it in the first place, so nuke it instead of show it
439 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
440 {
84573326 441 tooMuch.insert(Pkg);
b9179170
MV
442 Cache->MarkDelete(Pkg, false, 0, false);
443 }
444 // only show stuff in the list that is not yet marked for removal
445 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
446 ++autoRemoveCount;
447 }
448 }
449 }
450
451 // we could have removed a new dependency of a garbage package,
452 // so check if a reverse depends is broken and if so install it again.
453 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
454 {
455 bool Changed;
456 do {
457 Changed = false;
ffb081b7 458 for (APT::PackageSet::iterator Pkg = tooMuch.begin();
3a7a206f 459 Pkg != tooMuch.end(); ++Pkg)
b9179170
MV
460 {
461 APT::PackageSet too;
462 too.insert(*Pkg);
463 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
464 Prv.end() == false; ++Prv)
465 too.insert(Prv.ParentPkg());
3a7a206f
DK
466 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
467 {
b9179170
MV
468 for (pkgCache::DepIterator R = P.RevDependsList();
469 R.end() == false; ++R)
470 {
471 if (R.IsNegative() == true ||
472 Cache->IsImportantDep(R) == false)
473 continue;
474 pkgCache::PkgIterator N = R.ParentPkg();
475 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
476 continue;
477 if (Debug == true)
84573326 478 std::clog << "Save " << APT::PrettyPkg(Cache, Pkg) << " as another installed garbage package depends on it" << std::endl;
b9179170
MV
479 Cache->MarkInstall(Pkg, false, 0, false);
480 if (hideAutoRemove == false)
481 ++autoRemoveCount;
482 tooMuch.erase(Pkg);
483 Changed = true;
484 break;
485 }
3a7a206f
DK
486 if (Changed == true)
487 break;
b9179170 488 }
3a7a206f
DK
489 if (Changed == true)
490 break;
b9179170
MV
491 }
492 } while (Changed == true);
493 }
494
b9179170
MV
495 // Now see if we had destroyed anything (if we had done anything)
496 if (Cache->BrokenCount() != 0)
497 {
498 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
499 "shouldn't happen. Please file a bug report against apt.") << std::endl;
500 c1out << std::endl;
501 c1out << _("The following information may help to resolve the situation:") << std::endl;
502 c1out << std::endl;
503 ShowBroken(c1out,Cache,false);
504
505 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
506 }
507
508 // if we don't remove them, we should show them!
a0c19a21 509 if (doAutoRemove == false && autoRemoveCount != 0)
b9179170
MV
510 {
511 if (smallList == false)
a0c19a21
DK
512 {
513 SortedPackageUniverse Universe(Cache);
b9179170
MV
514 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
515 "The following packages were automatically installed and are no longer required:",
a0c19a21
DK
516 autoRemoveCount), Universe,
517 [&Cache](pkgCache::PkgIterator const &Pkg) { return (*Cache)[Pkg].Garbage == true && (*Cache)[Pkg].Delete() == false; },
518 &PrettyFullName, CandidateVersion(&Cache));
519 }
b9179170
MV
520 else
521 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
522 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
73fe49f9 523 std::string autocmd = "apt autoremove";
f1e8e9da
DK
524 if (getenv("SUDO_USER") != nullptr)
525 {
526 auto const envsudocmd = getenv("SUDO_COMMAND");
527 auto const envshell = getenv("SHELL");
528 if (envsudocmd == nullptr || envshell == nullptr || strcmp(envsudocmd, envshell) != 0)
529 autocmd = "sudo " + autocmd;
530 }
73fe49f9
DK
531 ioprintf(c1out, P_("Use '%s' to remove it.", "Use '%s' to remove them.", autoRemoveCount), autocmd.c_str());
532 c1out << std::endl;
b9179170
MV
533 }
534 return true;
535}
536 /*}}}*/
ee0167c4 537// DoCacheManipulationFromCommandLine /*{{{*/
d8a8f9d7
MV
538static const unsigned short MOD_REMOVE = 1;
539static const unsigned short MOD_INSTALL = 2;
b9179170 540
172947cd 541bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
14341a7e 542{
92296fe4 543 std::vector<std::string> VolatileCmdL;
14341a7e
DK
544 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
545}
92296fe4 546bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
d8a8f9d7
MV
547{
548 std::map<unsigned short, APT::VersionSet> verset;
14341a7e 549 return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode);
d8a8f9d7 550}
92296fe4 551bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache,
172947cd 552 std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
b9179170 553{
b9179170
MV
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
6c413b18 559 std::unique_ptr<pkgProblemResolver> Fix(nullptr);
b9179170 560 if (_config->FindB("APT::Get::CallResolver", true) == true)
6c413b18 561 Fix.reset(new pkgProblemResolver(Cache));
b9179170 562
b9179170
MV
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 }
f66738d7
JAK
571 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0 ||
572 strcasecmp(CmdL.FileList[0], "auto-remove") == 0)
b9179170
MV
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, "+",
e6f0c9bc 580 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::CANDIDATE));
b9179170 581 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
e6f0c9bc 582 APT::VersionSet::Modifier::POSTFIX, APT::CacheSetHelper::NEWEST));
b9179170 583 CacheSetHelperAPTGet helper(c0out);
d8a8f9d7 584 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
b9179170
MV
585 CmdL.FileList + 1, mods, fallback, helper);
586
14341a7e
DK
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
b9179170
MV
601 if (_error->PendingError() == true)
602 {
603 helper.showVirtualPackageErrors(Cache);
b9179170
MV
604 return false;
605 }
606
607
6c413b18
JAK
608 TryToInstall InstallAction(Cache, Fix.get(), BrokenFix);
609 TryToRemove RemoveAction(Cache, Fix.get());
b9179170
MV
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 {
9777639e
DK
626 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
627 InstallAction.doAutoInstall();
b9179170
MV
628 }
629
630 if (_error->PendingError() == true)
631 {
b9179170
MV
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);
b9179170
MV
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
2a884c61
DK
648 OpTextProgress Progress(*_config);
649 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
650
67caa2e6
DK
651 bool resolver_fail = false;
652 if (distUpgradeMode == true || UpgradeMode != APT::Upgrade::ALLOW_EVERYTHING)
2a884c61 653 resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
67caa2e6
DK
654 else
655 resolver_fail = Fix->Resolve(true, &Progress);
172947cd
DK
656
657 if (resolver_fail == false && Cache->BrokenCount() == 0)
58377ceb 658 return false;
b9179170
MV
659 }
660
a249b3e6
DK
661 if (CheckNothingBroken(Cache) == false)
662 return false;
b9179170
MV
663 }
664 if (!DoAutomaticRemove(Cache))
665 return false;
666
d8a8f9d7
MV
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}
ee0167c4 678 /*}}}*/
d8a8f9d7
MV
679// DoInstall - Install packages from the command line /*{{{*/
680// ---------------------------------------------------------------------
681/* Install named packages */
a0c19a21
DK
682struct 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) {}
258b9e51 686 bool operator() (pkgCache::PkgIterator const &Pkg)
a0c19a21
DK
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};
d8a8f9d7
MV
694bool DoInstall(CommandLine &CmdL)
695{
696 CacheFile Cache;
92296fe4 697 std::vector<std::string> VolatileCmdL;
14341a7e 698 Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
0d29b9d4
MV
699
700 // then open the cache
d8a8f9d7
MV
701 if (Cache.OpenForInstall() == false ||
702 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
703 return false;
848fd2a6 704
14341a7e
DK
705 std::map<unsigned short, APT::VersionSet> verset;
706 if(!DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, 0))
d8a8f9d7
MV
707 return false;
708
b9179170
MV
709 /* Print out a list of packages that are going to be installed extra
710 to what the user asked */
a0c19a21 711 SortedPackageUniverse Universe(Cache);
b9179170 712 if (Cache->InstCount() != verset[MOD_INSTALL].size())
1040dc88 713 ShowList(c1out, _("The following additional packages will be installed:"), Universe,
a0c19a21
DK
714 PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]),
715 &PrettyFullName, CandidateVersion(&Cache));
b9179170
MV
716
717 /* Print out a list of suggested and recommended packages */
718 {
9112f777 719 std::list<std::string> Recommends, Suggests, SingleRecommends, SingleSuggests;
a0c19a21 720 for (auto const &Pkg: Universe)
b9179170 721 {
b9179170
MV
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
9112f777
DK
733 if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests)
734 continue;
b9179170 735
b9179170 736 {
9112f777
DK
737 // Skip if we already saw this
738 std::string target;
739 for (pkgCache::DepIterator I = Start; I != D; ++I)
b9179170 740 {
9112f777
DK
741 if (target.empty() == false)
742 target.append(" | ");
743 target.append(I.TargetPkg().FullName(true));
b9179170 744 }
9112f777
DK
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 }
b9179170 750
9112f777
DK
751 std::list<std::string> OrList;
752 bool foundInstalledInOrGroup = false;
753 for (pkgCache::DepIterator I = Start; I != D; ++I)
754 {
b9179170 755 {
9112f777
DK
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())
b9179170 760 {
9112f777
DK
761 foundInstalledInOrGroup = true;
762 break;
b9179170
MV
763 }
764 }
765
b9179170 766 {
9112f777
DK
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 }
b9179170
MV
775 }
776
9112f777
DK
777 if (OrList.empty())
778 OrList.push_back(I.TargetPkg().FullName(true));
779 else
780 OrList.push_back("| " + I.TargetPkg().FullName(true));
b9179170 781 }
9112f777 782
b9179170
MV
783 if(foundInstalledInOrGroup == false)
784 {
9112f777
DK
785 std::list<std::string> &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests;
786 std::move(OrList.begin(), OrList.end(), std::back_inserter(Type));
b9179170 787 }
b9179170
MV
788 }
789 }
9112f777
DK
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);
b9179170
MV
806 }
807
b9179170
MV
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
9112f777 813 return InstallPackages(Cache,false);
b9179170
MV
814}
815 /*}}}*/
4d695011
DK
816
817// TryToInstall - Mark a package for installation /*{{{*/
818void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
a249b3e6
DK
819 if (unlikely(Ver.end()))
820 {
821 _error->Fatal("The given version to TryToInstall is invalid!");
822 return;
823 }
4d695011 824 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a249b3e6
DK
825 if (unlikely(Pkg.end()))
826 {
827 _error->Fatal("The given version to TryToInstall has an invalid parent package!");
828 return;
829 }
4d695011
DK
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
3b9eaca8
JAK
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());
4d695011
DK
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 /*}}}*/
884bool 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 /*}}}*/
918void 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 /*{{{*/
930void 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 /*}}}*/