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