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