]> git.saurik.com Git - apt.git/blob - apt-private/private-install.cc
Merge remote-tracking branch 'mvo/feature/apt-install-deb' into debian/experimental
[apt.git] / apt-private / private-install.cc
1 // Include Files /*{{{*/
2 #include <config.h>
3
4 #include <apt-pkg/acquire.h>
5 #include <apt-pkg/acquire-item.h>
6 #include <apt-pkg/algorithms.h>
7 #include <apt-pkg/cachefile.h>
8 #include <apt-pkg/cacheset.h>
9 #include <apt-pkg/cmndline.h>
10 #include <apt-pkg/depcache.h>
11 #include <apt-pkg/error.h>
12 #include <apt-pkg/fileutl.h>
13 #include <apt-pkg/pkgrecords.h>
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>
22 #include <apt-pkg/sourcelist.h>
23
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/statfs.h>
28 #include <sys/statvfs.h>
29 #include <algorithm>
30 #include <iostream>
31 #include <set>
32 #include <vector>
33 #include <map>
34
35 #include <apt-private/acqprogress.h>
36 #include <apt-private/private-install.h>
37 #include <apt-private/private-cachefile.h>
38 #include <apt-private/private-cacheset.h>
39 #include <apt-private/private-download.h>
40 #include <apt-private/private-output.h>
41
42 #include <apti18n.h>
43 /*}}}*/
44 class pkgSourceList;
45
46 // InstallPackages - Actually download and install the packages /*{{{*/
47 // ---------------------------------------------------------------------
48 /* This displays the informative messages describing what is going to
49 happen and then calls the download routines */
50 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
51 {
52 if (_config->FindB("APT::Get::Purge",false) == true)
53 {
54 pkgCache::PkgIterator I = Cache->PkgBegin();
55 for (; I.end() == false; ++I)
56 {
57 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
58 Cache->MarkDelete(I,true);
59 }
60 }
61
62 bool Fail = false;
63 bool Essential = false;
64
65 // Show all the various warning indicators
66 ShowDel(c1out,Cache);
67 ShowNew(c1out,Cache);
68 if (ShwKept == true)
69 ShowKept(c1out,Cache);
70 Fail |= !ShowHold(c1out,Cache);
71 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
72 ShowUpgraded(c1out,Cache);
73 Fail |= !ShowDowngraded(c1out,Cache);
74 if (_config->FindB("APT::Get::Download-Only",false) == false)
75 Essential = !ShowEssential(c1out,Cache);
76 Fail |= Essential;
77 Stats(c1out,Cache);
78
79 // Sanity check
80 if (Cache->BrokenCount() != 0)
81 {
82 ShowBroken(c1out,Cache,false);
83 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
84 }
85
86 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
87 Cache->BadCount() == 0)
88 return true;
89
90 // No remove flag
91 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
92 return _error->Error(_("Packages need to be removed but remove is disabled."));
93
94 // Run the simulator ..
95 if (_config->FindB("APT::Get::Simulate") == true)
96 {
97 pkgSimulate PM(Cache);
98
99 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
100 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
101 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
102 delete progress;
103 #else
104 int status_fd = _config->FindI("APT::Status-Fd",-1);
105 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
106 #endif
107
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)
259 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
260 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
261 return true;
262 }
263
264 if (!CheckAuth(Fetcher, true))
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 }
296
297 bool Failed = false;
298 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
299 return false;
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
336 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
337 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
338 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
339 delete progress;
340 #else
341 int status_fd = _config->FindI("APT::Status-Fd", -1);
342 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
343 #endif
344
345 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
346 return false;
347 if (Res == pkgPackageManager::Completed)
348 break;
349
350 // Reload the fetcher object and loop again for media swapping
351 Fetcher.Shutdown();
352 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
353 return false;
354
355 _system->Lock();
356 }
357
358 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
359 if (disappearedPkgs.empty() == true)
360 return true;
361
362 std::string disappear;
363 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
364 d != disappearedPkgs.end(); ++d)
365 disappear.append(*d).append(" ");
366
367 ShowList(c1out, P_("The following package disappeared from your system as\n"
368 "all files have been overwritten by other packages:",
369 "The following packages disappeared from your system as\n"
370 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
371 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
372
373 return true;
374 }
375 /*}}}*/
376 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
377 // ---------------------------------------------------------------------
378 /* Remove unused automatic packages */
379 static bool DoAutomaticRemove(CacheFile &Cache)
380 {
381 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
382 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
383 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
384
385 pkgDepCache::ActionGroup group(*Cache);
386 if(Debug)
387 std::cout << "DoAutomaticRemove()" << std::endl;
388
389 if (doAutoRemove == true &&
390 _config->FindB("APT::Get::Remove",true) == false)
391 {
392 c1out << _("We are not supposed to delete stuff, can't start "
393 "AutoRemover") << std::endl;
394 return false;
395 }
396
397 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
398 bool smallList = (hideAutoRemove == false &&
399 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
400
401 unsigned long autoRemoveCount = 0;
402 APT::PackageSet tooMuch;
403 APT::PackageList autoRemoveList;
404 // look over the cache to see what can be removed
405 for (unsigned J = 0; J < Cache->Head().PackageCount; ++J)
406 {
407 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
408 if (Cache[Pkg].Garbage)
409 {
410 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
411 if(Debug)
412 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
413
414 if (doAutoRemove)
415 {
416 if(Pkg.CurrentVer() != 0 &&
417 Pkg->CurrentState != pkgCache::State::ConfigFiles)
418 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
419 else
420 Cache->MarkKeep(Pkg, false, false);
421 }
422 else
423 {
424 if (hideAutoRemove == false && Cache[Pkg].Delete() == false)
425 autoRemoveList.insert(Pkg);
426 // if the package is a new install and already garbage we don't need to
427 // install it in the first place, so nuke it instead of show it
428 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
429 {
430 if (Pkg.CandVersion() != 0)
431 tooMuch.insert(Pkg);
432 Cache->MarkDelete(Pkg, false, 0, false);
433 }
434 // only show stuff in the list that is not yet marked for removal
435 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
436 ++autoRemoveCount;
437 }
438 }
439 }
440
441 // we could have removed a new dependency of a garbage package,
442 // so check if a reverse depends is broken and if so install it again.
443 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
444 {
445 bool Changed;
446 do {
447 Changed = false;
448 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
449 Pkg != tooMuch.end(); ++Pkg)
450 {
451 APT::PackageSet too;
452 too.insert(*Pkg);
453 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
454 Prv.end() == false; ++Prv)
455 too.insert(Prv.ParentPkg());
456 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
457 {
458 for (pkgCache::DepIterator R = P.RevDependsList();
459 R.end() == false; ++R)
460 {
461 if (R.IsNegative() == true ||
462 Cache->IsImportantDep(R) == false)
463 continue;
464 pkgCache::PkgIterator N = R.ParentPkg();
465 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
466 continue;
467 if (Debug == true)
468 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
469 Cache->MarkInstall(Pkg, false, 0, false);
470 if (hideAutoRemove == false)
471 ++autoRemoveCount;
472 tooMuch.erase(Pkg);
473 Changed = true;
474 break;
475 }
476 if (Changed == true)
477 break;
478 }
479 if (Changed == true)
480 break;
481 }
482 } while (Changed == true);
483 }
484
485 std::string autoremovelist, autoremoveversions;
486 if (smallList == false && autoRemoveCount != 0)
487 {
488 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
489 {
490 if (Cache[Pkg].Garbage == false)
491 continue;
492 autoremovelist += Pkg.FullName(true) + " ";
493 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
494 }
495 }
496
497 // Now see if we had destroyed anything (if we had done anything)
498 if (Cache->BrokenCount() != 0)
499 {
500 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
501 "shouldn't happen. Please file a bug report against apt.") << std::endl;
502 c1out << std::endl;
503 c1out << _("The following information may help to resolve the situation:") << std::endl;
504 c1out << std::endl;
505 ShowBroken(c1out,Cache,false);
506
507 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
508 }
509
510 // if we don't remove them, we should show them!
511 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
512 {
513 if (smallList == false)
514 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
515 "The following packages were automatically installed and are no longer required:",
516 autoRemoveCount), autoremovelist, autoremoveversions);
517 else
518 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
519 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
520 c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl;
521 }
522 return true;
523 }
524 /*}}}*/
525 // DoCacheManipulationFromCommandLine /*{{{*/
526 static const unsigned short MOD_REMOVE = 1;
527 static const unsigned short MOD_INSTALL = 2;
528
529 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
530 {
531 std::map<unsigned short, APT::VersionSet> verset;
532 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
533 }
534 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
535 std::map<unsigned short, APT::VersionSet> &verset)
536 {
537
538 // Enter the special broken fixing mode if the user specified arguments
539 bool BrokenFix = false;
540 if (Cache->BrokenCount() != 0)
541 BrokenFix = true;
542
543 SPtr<pkgProblemResolver> Fix;
544 if (_config->FindB("APT::Get::CallResolver", true) == true)
545 Fix = new pkgProblemResolver(Cache);
546
547 unsigned short fallback = MOD_INSTALL;
548 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
549 fallback = MOD_REMOVE;
550 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
551 {
552 _config->Set("APT::Get::Purge", true);
553 fallback = MOD_REMOVE;
554 }
555 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
556 {
557 _config->Set("APT::Get::AutomaticRemove", "true");
558 fallback = MOD_REMOVE;
559 }
560
561 std::list<APT::VersionSet::Modifier> mods;
562 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
563 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
564 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
565 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
566 CacheSetHelperAPTGet helper(c0out);
567 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
568 CmdL.FileList + 1, mods, fallback, helper);
569
570 if (_error->PendingError() == true)
571 {
572 helper.showVirtualPackageErrors(Cache);
573 return false;
574 }
575
576
577 TryToInstall InstallAction(Cache, Fix, BrokenFix);
578 TryToRemove RemoveAction(Cache, Fix);
579
580 // new scope for the ActionGroup
581 {
582 pkgDepCache::ActionGroup group(Cache);
583 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
584
585 for (unsigned short i = 0; order[i] != 0; ++i)
586 {
587 if (order[i] == MOD_INSTALL)
588 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
589 else if (order[i] == MOD_REMOVE)
590 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
591 }
592
593 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
594 {
595 for (unsigned short i = 0; order[i] != 0; ++i)
596 {
597 if (order[i] != MOD_INSTALL)
598 continue;
599 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
600 InstallAction.doAutoInstall();
601 }
602 }
603
604 if (_error->PendingError() == true)
605 {
606 return false;
607 }
608
609 /* If we are in the Broken fixing mode we do not attempt to fix the
610 problems. This is if the user invoked install without -f and gave
611 packages */
612 if (BrokenFix == true && Cache->BrokenCount() != 0)
613 {
614 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
615 ShowBroken(c1out,Cache,false);
616 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
617 }
618
619 if (Fix != NULL)
620 {
621 // Call the scored problem resolver
622 Fix->Resolve(true);
623 }
624
625 // Now we check the state of the packages,
626 if (Cache->BrokenCount() != 0)
627 {
628 c1out <<
629 _("Some packages could not be installed. This may mean that you have\n"
630 "requested an impossible situation or if you are using the unstable\n"
631 "distribution that some required packages have not yet been created\n"
632 "or been moved out of Incoming.") << std::endl;
633 /*
634 if (Packages == 1)
635 {
636 c1out << std::endl;
637 c1out <<
638 _("Since you only requested a single operation it is extremely likely that\n"
639 "the package is simply not installable and a bug report against\n"
640 "that package should be filed.") << std::endl;
641 }
642 */
643
644 c1out << _("The following information may help to resolve the situation:") << std::endl;
645 c1out << std::endl;
646 ShowBroken(c1out,Cache,false);
647 if (_error->PendingError() == true)
648 return false;
649 else
650 return _error->Error(_("Broken packages"));
651 }
652 }
653 if (!DoAutomaticRemove(Cache))
654 return false;
655
656 // if nothing changed in the cache, but only the automark information
657 // we write the StateFile here, otherwise it will be written in
658 // cache.commit()
659 if (InstallAction.AutoMarkChanged > 0 &&
660 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
661 Cache->BadCount() == 0 &&
662 _config->FindB("APT::Get::Simulate",false) == false)
663 Cache->writeStateFile(NULL);
664
665 return true;
666 }
667 /*}}}*/
668 // DoInstall - Install packages from the command line /*{{{*/
669 // ---------------------------------------------------------------------
670 /* Install named packages */
671 bool DoInstall(CommandLine &CmdL)
672 {
673 CacheFile Cache;
674 // first check for local pkgs and add them to the cache
675 for (const char **I = CmdL.FileList; *I != 0; I++)
676 {
677 if(FileExists(*I))
678 {
679 // FIXME: make this more elegant
680 std::string TypeStr = flExtension(*I) + "-file";
681 pkgSourceList::Type *Type = pkgSourceList::Type::GetType(TypeStr.c_str());
682 if(Type != 0)
683 {
684 std::vector<metaIndex *> List;
685 std::map<std::string, std::string> Options;
686 if(Type->CreateItem(List, *I, "", "", Options))
687 {
688 // we have our own CacheFile that gives us a SourceList
689 // with superpowerz
690 SourceList *sources = (SourceList*)Cache.GetSourceList();
691 sources->AddMetaIndex(List[0]);
692 }
693 }
694 }
695 }
696
697 // then open the cache
698 if (Cache.OpenForInstall() == false ||
699 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
700 return false;
701
702 std::map<unsigned short, APT::VersionSet> verset;
703
704 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
705 return false;
706
707 /* Print out a list of packages that are going to be installed extra
708 to what the user asked */
709 if (Cache->InstCount() != verset[MOD_INSTALL].size())
710 {
711 std::string List;
712 std::string VersionsList;
713 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
714 {
715 pkgCache::PkgIterator I(Cache,Cache.List[J]);
716 if ((*Cache)[I].Install() == false)
717 continue;
718 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
719
720 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
721 continue;
722
723 List += I.FullName(true) + " ";
724 VersionsList += std::string(Cache[I].CandVersion) + "\n";
725 }
726
727 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
728 }
729
730 /* Print out a list of suggested and recommended packages */
731 {
732 std::string SuggestsList, RecommendsList;
733 std::string SuggestsVersions, RecommendsVersions;
734 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
735 {
736 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
737
738 /* Just look at the ones we want to install */
739 if ((*Cache)[Pkg].Install() == false)
740 continue;
741
742 // get the recommends/suggests for the candidate ver
743 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
744 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
745 {
746 pkgCache::DepIterator Start;
747 pkgCache::DepIterator End;
748 D.GlobOr(Start,End); // advances D
749
750 // FIXME: we really should display a or-group as a or-group to the user
751 // the problem is that ShowList is incapable of doing this
752 std::string RecommendsOrList,RecommendsOrVersions;
753 std::string SuggestsOrList,SuggestsOrVersions;
754 bool foundInstalledInOrGroup = false;
755 for(;;)
756 {
757 /* Skip if package is installed already, or is about to be */
758 std::string target = Start.TargetPkg().FullName(true) + " ";
759 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
760 if (TarPkg->SelectedState == pkgCache::State::Install ||
761 TarPkg->SelectedState == pkgCache::State::Hold ||
762 Cache[Start.TargetPkg()].Install())
763 {
764 foundInstalledInOrGroup=true;
765 break;
766 }
767
768 /* Skip if we already saw it */
769 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
770 {
771 foundInstalledInOrGroup=true;
772 break;
773 }
774
775 // this is a dep on a virtual pkg, check if any package that provides it
776 // should be installed
777 if(Start.TargetPkg().ProvidesList() != 0)
778 {
779 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
780 for (; I.end() == false; ++I)
781 {
782 pkgCache::PkgIterator Pkg = I.OwnerPkg();
783 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
784 Pkg.CurrentVer() != 0)
785 foundInstalledInOrGroup=true;
786 }
787 }
788
789 if (Start->Type == pkgCache::Dep::Suggests)
790 {
791 SuggestsOrList += target;
792 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
793 }
794
795 if (Start->Type == pkgCache::Dep::Recommends)
796 {
797 RecommendsOrList += target;
798 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
799 }
800
801 if (Start >= End)
802 break;
803 ++Start;
804 }
805
806 if(foundInstalledInOrGroup == false)
807 {
808 RecommendsList += RecommendsOrList;
809 RecommendsVersions += RecommendsOrVersions;
810 SuggestsList += SuggestsOrList;
811 SuggestsVersions += SuggestsOrVersions;
812 }
813
814 }
815 }
816
817 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
818 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
819
820 }
821
822 // See if we need to prompt
823 // FIXME: check if really the packages in the set are going to be installed
824 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
825 return InstallPackages(Cache,false,false);
826
827 return InstallPackages(Cache,false);
828 }
829 /*}}}*/