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