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