]> git.saurik.com Git - apt.git/blame - apt-private/private-install.cc
do not revert candidate for protected packages
[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>
b9179170 22
453b82a3
DK
23#include <errno.h>
24#include <stdlib.h>
25#include <string.h>
b9179170
MV
26#include <sys/statfs.h>
27#include <sys/statvfs.h>
453b82a3
DK
28#include <algorithm>
29#include <iostream>
30#include <set>
31#include <vector>
b9179170 32
453b82a3
DK
33#include <apt-private/acqprogress.h>
34#include <apt-private/private-install.h>
35#include <apt-private/private-cachefile.h>
36#include <apt-private/private-cacheset.h>
37#include <apt-private/private-download.h>
38#include <apt-private/private-output.h>
b9179170
MV
39
40#include <apti18n.h>
41 /*}}}*/
453b82a3 42class pkgSourceList;
b9179170 43
b9179170
MV
44// InstallPackages - Actually download and install the packages /*{{{*/
45// ---------------------------------------------------------------------
46/* This displays the informative messages describing what is going to
47 happen and then calls the download routines */
48bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
49{
50 if (_config->FindB("APT::Get::Purge",false) == true)
51 {
52 pkgCache::PkgIterator I = Cache->PkgBegin();
53 for (; I.end() == false; ++I)
54 {
55 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
56 Cache->MarkDelete(I,true);
57 }
58 }
59
60 bool Fail = false;
61 bool Essential = false;
62
63 // Show all the various warning indicators
64 ShowDel(c1out,Cache);
65 ShowNew(c1out,Cache);
66 if (ShwKept == true)
67 ShowKept(c1out,Cache);
68 Fail |= !ShowHold(c1out,Cache);
69 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
70 ShowUpgraded(c1out,Cache);
71 Fail |= !ShowDowngraded(c1out,Cache);
72 if (_config->FindB("APT::Get::Download-Only",false) == false)
73 Essential = !ShowEssential(c1out,Cache);
74 Fail |= Essential;
75 Stats(c1out,Cache);
76
77 // Sanity check
78 if (Cache->BrokenCount() != 0)
79 {
80 ShowBroken(c1out,Cache,false);
81 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
82 }
83
84 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
85 Cache->BadCount() == 0)
86 return true;
87
88 // No remove flag
89 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
90 return _error->Error(_("Packages need to be removed but remove is disabled."));
91
92 // Run the simulator ..
93 if (_config->FindB("APT::Get::Simulate") == true)
94 {
95 pkgSimulate PM(Cache);
5e9458e2 96
bd5f39b3
MV
97#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
98 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
99 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
100 delete progress;
bd5f39b3
MV
101#else
102 int status_fd = _config->FindI("APT::Status-Fd",-1);
103 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
104#endif
5e9458e2 105
b9179170
MV
106 if (Res == pkgPackageManager::Failed)
107 return false;
108 if (Res != pkgPackageManager::Completed)
109 return _error->Error(_("Internal error, Ordering didn't finish"));
110 return true;
111 }
112
113 // Create the text record parser
114 pkgRecords Recs(Cache);
115 if (_error->PendingError() == true)
116 return false;
117
118 // Create the download object
119 pkgAcquire Fetcher;
120 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
121 if (_config->FindB("APT::Get::Print-URIs", false) == true)
122 {
123 // force a hashsum for compatibility reasons
124 _config->CndSet("Acquire::ForceHash", "md5sum");
125 }
126 else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
127 return false;
128
129 // Read the source list
130 if (Cache.BuildSourceList() == false)
131 return false;
132 pkgSourceList *List = Cache.GetSourceList();
133
134 // Create the package manager and prepare to download
135 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
136 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
137 _error->PendingError() == true)
138 return false;
139
140 // Display statistics
141 unsigned long long FetchBytes = Fetcher.FetchNeeded();
142 unsigned long long FetchPBytes = Fetcher.PartialPresent();
143 unsigned long long DebBytes = Fetcher.TotalNeeded();
144 if (DebBytes != Cache->DebSize())
145 {
146 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
1166ea79 147 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
b9179170
MV
148 }
149
150 // Number of bytes
151 if (DebBytes != FetchBytes)
152 //TRANSLATOR: The required space between number and unit is already included
153 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
154 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
155 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
156 else if (DebBytes != 0)
157 //TRANSLATOR: The required space between number and unit is already included
158 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
159 ioprintf(c1out,_("Need to get %sB of archives.\n"),
160 SizeToStr(DebBytes).c_str());
161
162 // Size delta
163 if (Cache->UsrSize() >= 0)
164 //TRANSLATOR: The required space between number and unit is already included
165 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
166 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
167 SizeToStr(Cache->UsrSize()).c_str());
168 else
169 //TRANSLATOR: The required space between number and unit is already included
170 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
171 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
172 SizeToStr(-1*Cache->UsrSize()).c_str());
173
174 if (_error->PendingError() == true)
175 return false;
176
177 /* Check for enough free space, but only if we are actually going to
178 download */
179 if (_config->FindB("APT::Get::Print-URIs") == false &&
180 _config->FindB("APT::Get::Download",true) == true)
181 {
182 struct statvfs Buf;
183 std::string OutputDir = _config->FindDir("Dir::Cache::Archives");
184 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
185 if (errno == EOVERFLOW)
186 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
187 OutputDir.c_str());
188 else
189 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
190 OutputDir.c_str());
191 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
192 {
193 struct statfs Stat;
194 if (statfs(OutputDir.c_str(),&Stat) != 0
195#if HAVE_STRUCT_STATFS_F_TYPE
196 || unsigned(Stat.f_type) != RAMFS_MAGIC
197#endif
198 )
199 return _error->Error(_("You don't have enough free space in %s."),
200 OutputDir.c_str());
201 }
202 }
203
204 // Fail safe check
205 if (_config->FindI("quiet",0) >= 2 ||
206 _config->FindB("APT::Get::Assume-Yes",false) == true)
207 {
208 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
209 return _error->Error(_("There are problems and -y was used without --force-yes"));
210 }
211
212 if (Essential == true && Safety == true)
213 {
214 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
215 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
216
217 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
218 // careful with hard to type or special characters (like non-breaking spaces)
219 const char *Prompt = _("Yes, do as I say!");
220 ioprintf(c2out,
221 _("You are about to do something potentially harmful.\n"
222 "To continue type in the phrase '%s'\n"
223 " ?] "),Prompt);
224 c2out << std::flush;
225 if (AnalPrompt(Prompt) == false)
226 {
227 c2out << _("Abort.") << std::endl;
228 exit(1);
229 }
230 }
231 else
232 {
233 // Prompt to continue
234 if (Ask == true || Fail == true)
235 {
236 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
237 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
238
239 if (_config->FindI("quiet",0) < 2 &&
240 _config->FindB("APT::Get::Assume-Yes",false) == false)
241 {
242 c2out << _("Do you want to continue?") << std::flush;
243 if (YnPrompt() == false)
244 {
245 c2out << _("Abort.") << std::endl;
246 exit(1);
247 }
248 }
249 }
250 }
251
252 // Just print out the uris an exit if the --print-uris flag was used
253 if (_config->FindB("APT::Get::Print-URIs") == true)
254 {
255 pkgAcquire::UriIterator I = Fetcher.UriBegin();
256 for (; I != Fetcher.UriEnd(); ++I)
ac69a4d8 257 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
b9179170
MV
258 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
259 return true;
260 }
261
866893a6 262 if (!CheckAuth(Fetcher, true))
b9179170
MV
263 return false;
264
265 /* Unlock the dpkg lock if we are not going to be doing an install
266 after. */
267 if (_config->FindB("APT::Get::Download-Only",false) == true)
268 _system->UnLock();
269
270 // Run it
271 while (1)
272 {
273 bool Transient = false;
274 if (_config->FindB("APT::Get::Download",true) == false)
275 {
276 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
277 {
278 if ((*I)->Local == true)
279 {
280 ++I;
281 continue;
282 }
283
284 // Close the item and check if it was found in cache
285 (*I)->Finished();
286 if ((*I)->Complete == false)
287 Transient = true;
288
289 // Clear it out of the fetch list
290 delete *I;
291 I = Fetcher.ItemsBegin();
292 }
293 }
b9179170 294
866893a6
DK
295 bool Failed = false;
296 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
297 return false;
b9179170
MV
298
299 /* If we are in no download mode and missing files and there were
300 'failures' then the user must specify -m. Furthermore, there
301 is no such thing as a transient error in no-download mode! */
302 if (Transient == true &&
303 _config->FindB("APT::Get::Download",true) == false)
304 {
305 Transient = false;
306 Failed = true;
307 }
308
309 if (_config->FindB("APT::Get::Download-Only",false) == true)
310 {
311 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
312 return _error->Error(_("Some files failed to download"));
313 c1out << _("Download complete and in download only mode") << std::endl;
314 return true;
315 }
316
317 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
318 {
319 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
320 }
321
322 if (Transient == true && Failed == true)
323 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
324
325 // Try to deal with missing package files
326 if (Failed == true && PM->FixMissing() == false)
327 {
328 c2out << _("Unable to correct missing packages.") << std::endl;
329 return _error->Error(_("Aborting install."));
330 }
331
332 _system->UnLock();
e6ad8031 333
bd5f39b3
MV
334#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
335 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
336 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
337 delete progress;
bd5f39b3
MV
338#else
339 int status_fd = _config->FindI("APT::Status-Fd", -1);
340 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
341#endif
e6ad8031 342
b9179170
MV
343 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
344 return false;
345 if (Res == pkgPackageManager::Completed)
346 break;
347
348 // Reload the fetcher object and loop again for media swapping
349 Fetcher.Shutdown();
350 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
351 return false;
352
353 _system->Lock();
354 }
355
356 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
357 if (disappearedPkgs.empty() == true)
358 return true;
359
360 std::string disappear;
361 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
362 d != disappearedPkgs.end(); ++d)
363 disappear.append(*d).append(" ");
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()), disappear, "");
369 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
370
371 return true;
372}
373 /*}}}*/
b9179170
MV
374// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
375// ---------------------------------------------------------------------
376/* Remove unused automatic packages */
c3ccac92 377static bool DoAutomaticRemove(CacheFile &Cache)
b9179170
MV
378{
379 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
380 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
381 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
382
383 pkgDepCache::ActionGroup group(*Cache);
384 if(Debug)
385 std::cout << "DoAutomaticRemove()" << std::endl;
386
387 if (doAutoRemove == true &&
388 _config->FindB("APT::Get::Remove",true) == false)
389 {
390 c1out << _("We are not supposed to delete stuff, can't start "
391 "AutoRemover") << std::endl;
392 return false;
393 }
394
395 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
396 bool smallList = (hideAutoRemove == false &&
397 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
398
399 unsigned long autoRemoveCount = 0;
400 APT::PackageSet tooMuch;
401 APT::PackageList autoRemoveList;
402 // look over the cache to see what can be removed
403 for (unsigned J = 0; J < Cache->Head().PackageCount; ++J)
404 {
405 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
406 if (Cache[Pkg].Garbage)
407 {
408 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
409 if(Debug)
410 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
411
412 if (doAutoRemove)
413 {
414 if(Pkg.CurrentVer() != 0 &&
415 Pkg->CurrentState != pkgCache::State::ConfigFiles)
416 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
417 else
418 Cache->MarkKeep(Pkg, false, false);
419 }
420 else
421 {
422 if (hideAutoRemove == false && Cache[Pkg].Delete() == false)
423 autoRemoveList.insert(Pkg);
424 // if the package is a new install and already garbage we don't need to
425 // install it in the first place, so nuke it instead of show it
426 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
427 {
428 if (Pkg.CandVersion() != 0)
429 tooMuch.insert(Pkg);
430 Cache->MarkDelete(Pkg, false, 0, false);
431 }
432 // only show stuff in the list that is not yet marked for removal
433 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
434 ++autoRemoveCount;
435 }
436 }
437 }
438
439 // we could have removed a new dependency of a garbage package,
440 // so check if a reverse depends is broken and if so install it again.
441 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
442 {
443 bool Changed;
444 do {
445 Changed = false;
446 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
3a7a206f 447 Pkg != tooMuch.end(); ++Pkg)
b9179170
MV
448 {
449 APT::PackageSet too;
450 too.insert(*Pkg);
451 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
452 Prv.end() == false; ++Prv)
453 too.insert(Prv.ParentPkg());
3a7a206f
DK
454 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
455 {
b9179170
MV
456 for (pkgCache::DepIterator R = P.RevDependsList();
457 R.end() == false; ++R)
458 {
459 if (R.IsNegative() == true ||
460 Cache->IsImportantDep(R) == false)
461 continue;
462 pkgCache::PkgIterator N = R.ParentPkg();
463 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
464 continue;
465 if (Debug == true)
466 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
467 Cache->MarkInstall(Pkg, false, 0, false);
468 if (hideAutoRemove == false)
469 ++autoRemoveCount;
470 tooMuch.erase(Pkg);
471 Changed = true;
472 break;
473 }
3a7a206f
DK
474 if (Changed == true)
475 break;
b9179170 476 }
3a7a206f
DK
477 if (Changed == true)
478 break;
b9179170
MV
479 }
480 } while (Changed == true);
481 }
482
483 std::string autoremovelist, autoremoveversions;
484 if (smallList == false && autoRemoveCount != 0)
485 {
486 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
487 {
488 if (Cache[Pkg].Garbage == false)
489 continue;
490 autoremovelist += Pkg.FullName(true) + " ";
491 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
492 }
493 }
494
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!
509 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
510 {
511 if (smallList == false)
512 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
513 "The following packages were automatically installed and are no longer required:",
514 autoRemoveCount), autoremovelist, autoremoveversions);
515 else
516 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
517 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
518 c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl;
519 }
520 return true;
521}
522 /*}}}*/
ee0167c4 523// DoCacheManipulationFromCommandLine /*{{{*/
d8a8f9d7
MV
524static const unsigned short MOD_REMOVE = 1;
525static const unsigned short MOD_INSTALL = 2;
b9179170 526
d8a8f9d7
MV
527bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
528{
529 std::map<unsigned short, APT::VersionSet> verset;
530 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
531}
d8a8f9d7
MV
532bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
533 std::map<unsigned short, APT::VersionSet> &verset)
b9179170 534{
d8a8f9d7 535
b9179170
MV
536 // Enter the special broken fixing mode if the user specified arguments
537 bool BrokenFix = false;
538 if (Cache->BrokenCount() != 0)
539 BrokenFix = true;
540
be0270de 541 SPtr<pkgProblemResolver> Fix;
b9179170
MV
542 if (_config->FindB("APT::Get::CallResolver", true) == true)
543 Fix = new pkgProblemResolver(Cache);
544
b9179170
MV
545 unsigned short fallback = MOD_INSTALL;
546 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
547 fallback = MOD_REMOVE;
548 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
549 {
550 _config->Set("APT::Get::Purge", true);
551 fallback = MOD_REMOVE;
552 }
553 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
554 {
555 _config->Set("APT::Get::AutomaticRemove", "true");
556 fallback = MOD_REMOVE;
557 }
558
559 std::list<APT::VersionSet::Modifier> mods;
560 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
561 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
562 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
563 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
564 CacheSetHelperAPTGet helper(c0out);
d8a8f9d7 565 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
b9179170
MV
566 CmdL.FileList + 1, mods, fallback, helper);
567
568 if (_error->PendingError() == true)
569 {
570 helper.showVirtualPackageErrors(Cache);
b9179170
MV
571 return false;
572 }
573
574
575 TryToInstall InstallAction(Cache, Fix, BrokenFix);
576 TryToRemove RemoveAction(Cache, Fix);
577
578 // new scope for the ActionGroup
579 {
580 pkgDepCache::ActionGroup group(Cache);
581 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
582
583 for (unsigned short i = 0; order[i] != 0; ++i)
584 {
585 if (order[i] == MOD_INSTALL)
586 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
587 else if (order[i] == MOD_REMOVE)
588 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
589 }
590
591 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
592 {
593 for (unsigned short i = 0; order[i] != 0; ++i)
594 {
595 if (order[i] != MOD_INSTALL)
596 continue;
597 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
598 InstallAction.doAutoInstall();
599 }
600 }
601
602 if (_error->PendingError() == true)
603 {
b9179170
MV
604 return false;
605 }
606
607 /* If we are in the Broken fixing mode we do not attempt to fix the
608 problems. This is if the user invoked install without -f and gave
609 packages */
610 if (BrokenFix == true && Cache->BrokenCount() != 0)
611 {
612 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
613 ShowBroken(c1out,Cache,false);
b9179170
MV
614 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
615 }
616
617 if (Fix != NULL)
618 {
619 // Call the scored problem resolver
58377ceb
DK
620 if (Fix->Resolve(true) == false && Cache->BrokenCount() == 0)
621 return false;
b9179170
MV
622 }
623
624 // Now we check the state of the packages,
625 if (Cache->BrokenCount() != 0)
626 {
627 c1out <<
628 _("Some packages could not be installed. This may mean that you have\n"
629 "requested an impossible situation or if you are using the unstable\n"
630 "distribution that some required packages have not yet been created\n"
631 "or been moved out of Incoming.") << std::endl;
632 /*
633 if (Packages == 1)
634 {
635 c1out << std::endl;
636 c1out <<
637 _("Since you only requested a single operation it is extremely likely that\n"
638 "the package is simply not installable and a bug report against\n"
639 "that package should be filed.") << std::endl;
640 }
641 */
642
643 c1out << _("The following information may help to resolve the situation:") << std::endl;
644 c1out << std::endl;
645 ShowBroken(c1out,Cache,false);
646 if (_error->PendingError() == true)
647 return false;
648 else
649 return _error->Error(_("Broken packages"));
650 }
651 }
652 if (!DoAutomaticRemove(Cache))
653 return false;
654
d8a8f9d7
MV
655 // if nothing changed in the cache, but only the automark information
656 // we write the StateFile here, otherwise it will be written in
657 // cache.commit()
658 if (InstallAction.AutoMarkChanged > 0 &&
659 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
660 Cache->BadCount() == 0 &&
661 _config->FindB("APT::Get::Simulate",false) == false)
662 Cache->writeStateFile(NULL);
663
664 return true;
665}
ee0167c4 666 /*}}}*/
d8a8f9d7
MV
667// DoInstall - Install packages from the command line /*{{{*/
668// ---------------------------------------------------------------------
669/* Install named packages */
670bool DoInstall(CommandLine &CmdL)
671{
672 CacheFile Cache;
673 if (Cache.OpenForInstall() == false ||
674 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
675 return false;
676
677 std::map<unsigned short, APT::VersionSet> verset;
678
679 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
680 return false;
681
b9179170
MV
682 /* Print out a list of packages that are going to be installed extra
683 to what the user asked */
684 if (Cache->InstCount() != verset[MOD_INSTALL].size())
685 {
686 std::string List;
687 std::string VersionsList;
688 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
689 {
690 pkgCache::PkgIterator I(Cache,Cache.List[J]);
691 if ((*Cache)[I].Install() == false)
692 continue;
693 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
694
695 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
696 continue;
697
698 List += I.FullName(true) + " ";
699 VersionsList += std::string(Cache[I].CandVersion) + "\n";
700 }
701
702 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
703 }
704
705 /* Print out a list of suggested and recommended packages */
706 {
707 std::string SuggestsList, RecommendsList;
708 std::string SuggestsVersions, RecommendsVersions;
709 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
710 {
711 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
712
713 /* Just look at the ones we want to install */
714 if ((*Cache)[Pkg].Install() == false)
715 continue;
716
717 // get the recommends/suggests for the candidate ver
718 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
719 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
720 {
721 pkgCache::DepIterator Start;
722 pkgCache::DepIterator End;
723 D.GlobOr(Start,End); // advances D
724
725 // FIXME: we really should display a or-group as a or-group to the user
726 // the problem is that ShowList is incapable of doing this
727 std::string RecommendsOrList,RecommendsOrVersions;
728 std::string SuggestsOrList,SuggestsOrVersions;
729 bool foundInstalledInOrGroup = false;
730 for(;;)
731 {
732 /* Skip if package is installed already, or is about to be */
733 std::string target = Start.TargetPkg().FullName(true) + " ";
734 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
735 if (TarPkg->SelectedState == pkgCache::State::Install ||
736 TarPkg->SelectedState == pkgCache::State::Hold ||
737 Cache[Start.TargetPkg()].Install())
738 {
739 foundInstalledInOrGroup=true;
740 break;
741 }
742
743 /* Skip if we already saw it */
744 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
745 {
746 foundInstalledInOrGroup=true;
747 break;
748 }
749
750 // this is a dep on a virtual pkg, check if any package that provides it
751 // should be installed
752 if(Start.TargetPkg().ProvidesList() != 0)
753 {
754 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
755 for (; I.end() == false; ++I)
756 {
757 pkgCache::PkgIterator Pkg = I.OwnerPkg();
758 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
759 Pkg.CurrentVer() != 0)
760 foundInstalledInOrGroup=true;
761 }
762 }
763
764 if (Start->Type == pkgCache::Dep::Suggests)
765 {
766 SuggestsOrList += target;
767 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
768 }
769
770 if (Start->Type == pkgCache::Dep::Recommends)
771 {
772 RecommendsOrList += target;
773 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
774 }
775
776 if (Start >= End)
777 break;
778 ++Start;
779 }
780
781 if(foundInstalledInOrGroup == false)
782 {
783 RecommendsList += RecommendsOrList;
784 RecommendsVersions += RecommendsOrVersions;
785 SuggestsList += SuggestsOrList;
786 SuggestsVersions += SuggestsOrVersions;
787 }
788
789 }
790 }
791
792 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
793 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
794
795 }
796
b9179170
MV
797 // See if we need to prompt
798 // FIXME: check if really the packages in the set are going to be installed
799 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
800 return InstallPackages(Cache,false,false);
801
802 return InstallPackages(Cache,false);
803}
804 /*}}}*/