]> git.saurik.com Git - apt.git/blame - apt-private/private-install.cc
fix progress output for (dist-)upgrade calculation
[apt.git] / apt-private / private-install.cc
CommitLineData
b9179170
MV
1// Include Files /*{{{*/
2#include <config.h>
3
453b82a3 4#include <apt-pkg/acquire.h>
b9179170 5#include <apt-pkg/acquire-item.h>
453b82a3 6#include <apt-pkg/algorithms.h>
b9179170
MV
7#include <apt-pkg/cachefile.h>
8#include <apt-pkg/cacheset.h>
453b82a3
DK
9#include <apt-pkg/cmndline.h>
10#include <apt-pkg/depcache.h>
11#include <apt-pkg/error.h>
12#include <apt-pkg/fileutl.h>
b9179170 13#include <apt-pkg/pkgrecords.h>
453b82a3
DK
14#include <apt-pkg/pkgsystem.h>
15#include <apt-pkg/sptr.h>
16#include <apt-pkg/strutl.h>
17#include <apt-pkg/cacheiterators.h>
18#include <apt-pkg/configuration.h>
19#include <apt-pkg/macros.h>
20#include <apt-pkg/packagemanager.h>
21#include <apt-pkg/pkgcache.h>
172947cd 22#include <apt-pkg/upgrade.h>
b58f28d4 23#include <apt-pkg/install-progress.h>
0d29b9d4 24
453b82a3
DK
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
b9179170
MV
28#include <sys/statfs.h>
29#include <sys/statvfs.h>
453b82a3
DK
30#include <algorithm>
31#include <iostream>
32#include <set>
33#include <vector>
eafc5435 34#include <map>
b9179170 35
453b82a3
DK
36#include <apt-private/acqprogress.h>
37#include <apt-private/private-install.h>
38#include <apt-private/private-cachefile.h>
39#include <apt-private/private-cacheset.h>
40#include <apt-private/private-download.h>
41#include <apt-private/private-output.h>
b9179170
MV
42
43#include <apti18n.h>
44 /*}}}*/
453b82a3 45class pkgSourceList;
b9179170 46
b9179170
MV
47// InstallPackages - Actually download and install the packages /*{{{*/
48// ---------------------------------------------------------------------
49/* This displays the informative messages describing what is going to
50 happen and then calls the download routines */
51bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
52{
53 if (_config->FindB("APT::Get::Purge",false) == true)
54 {
55 pkgCache::PkgIterator I = Cache->PkgBegin();
56 for (; I.end() == false; ++I)
57 {
58 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
59 Cache->MarkDelete(I,true);
60 }
61 }
62
63 bool Fail = false;
64 bool Essential = false;
65
66 // Show all the various warning indicators
67 ShowDel(c1out,Cache);
68 ShowNew(c1out,Cache);
69 if (ShwKept == true)
70 ShowKept(c1out,Cache);
71 Fail |= !ShowHold(c1out,Cache);
72 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
73 ShowUpgraded(c1out,Cache);
74 Fail |= !ShowDowngraded(c1out,Cache);
75 if (_config->FindB("APT::Get::Download-Only",false) == false)
76 Essential = !ShowEssential(c1out,Cache);
77 Fail |= Essential;
78 Stats(c1out,Cache);
79
80 // Sanity check
81 if (Cache->BrokenCount() != 0)
82 {
83 ShowBroken(c1out,Cache,false);
84 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
85 }
86
87 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
88 Cache->BadCount() == 0)
89 return true;
90
91 // No remove flag
92 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
93 return _error->Error(_("Packages need to be removed but remove is disabled."));
94
95 // Run the simulator ..
96 if (_config->FindB("APT::Get::Simulate") == true)
97 {
98 pkgSimulate PM(Cache);
5e9458e2 99
bd5f39b3
MV
100#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
101 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
102 pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
103 delete progress;
bd5f39b3
MV
104#else
105 int status_fd = _config->FindI("APT::Status-Fd",-1);
106 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
107#endif
5e9458e2 108
b9179170
MV
109 if (Res == pkgPackageManager::Failed)
110 return false;
111 if (Res != pkgPackageManager::Completed)
112 return _error->Error(_("Internal error, Ordering didn't finish"));
113 return true;
114 }
115
116 // Create the text record parser
117 pkgRecords Recs(Cache);
118 if (_error->PendingError() == true)
119 return false;
120
121 // Create the download object
122 pkgAcquire Fetcher;
123 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
124 if (_config->FindB("APT::Get::Print-URIs", false) == true)
125 {
126 // force a hashsum for compatibility reasons
127 _config->CndSet("Acquire::ForceHash", "md5sum");
128 }
129 else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
130 return false;
131
132 // Read the source list
133 if (Cache.BuildSourceList() == false)
134 return false;
135 pkgSourceList *List = Cache.GetSourceList();
136
137 // Create the package manager and prepare to download
138 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
139 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
140 _error->PendingError() == true)
141 return false;
142
143 // Display statistics
144 unsigned long long FetchBytes = Fetcher.FetchNeeded();
145 unsigned long long FetchPBytes = Fetcher.PartialPresent();
146 unsigned long long DebBytes = Fetcher.TotalNeeded();
147 if (DebBytes != Cache->DebSize())
148 {
149 c0out << DebBytes << ',' << Cache->DebSize() << std::endl;
1166ea79 150 c0out << _("How odd... The sizes didn't match, email apt@packages.debian.org") << std::endl;
b9179170
MV
151 }
152
153 // Number of bytes
154 if (DebBytes != FetchBytes)
155 //TRANSLATOR: The required space between number and unit is already included
156 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
157 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
158 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
159 else if (DebBytes != 0)
160 //TRANSLATOR: The required space between number and unit is already included
161 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
162 ioprintf(c1out,_("Need to get %sB of archives.\n"),
163 SizeToStr(DebBytes).c_str());
164
165 // Size delta
166 if (Cache->UsrSize() >= 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,_("After this operation, %sB of additional disk space will be used.\n"),
170 SizeToStr(Cache->UsrSize()).c_str());
171 else
172 //TRANSLATOR: The required space between number and unit is already included
173 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
174 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
175 SizeToStr(-1*Cache->UsrSize()).c_str());
176
177 if (_error->PendingError() == true)
178 return false;
179
180 /* Check for enough free space, but only if we are actually going to
181 download */
182 if (_config->FindB("APT::Get::Print-URIs") == false &&
183 _config->FindB("APT::Get::Download",true) == true)
184 {
185 struct statvfs Buf;
186 std::string OutputDir = _config->FindDir("Dir::Cache::Archives");
187 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
188 if (errno == EOVERFLOW)
189 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
190 OutputDir.c_str());
191 else
192 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
193 OutputDir.c_str());
194 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
195 {
196 struct statfs Stat;
197 if (statfs(OutputDir.c_str(),&Stat) != 0
198#if HAVE_STRUCT_STATFS_F_TYPE
199 || unsigned(Stat.f_type) != RAMFS_MAGIC
200#endif
201 )
202 return _error->Error(_("You don't have enough free space in %s."),
203 OutputDir.c_str());
204 }
205 }
206
207 // Fail safe check
208 if (_config->FindI("quiet",0) >= 2 ||
209 _config->FindB("APT::Get::Assume-Yes",false) == true)
210 {
211 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
212 return _error->Error(_("There are problems and -y was used without --force-yes"));
213 }
214
215 if (Essential == true && Safety == true)
216 {
217 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
218 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
219
220 // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be
221 // careful with hard to type or special characters (like non-breaking spaces)
222 const char *Prompt = _("Yes, do as I say!");
223 ioprintf(c2out,
224 _("You are about to do something potentially harmful.\n"
225 "To continue type in the phrase '%s'\n"
226 " ?] "),Prompt);
227 c2out << std::flush;
228 if (AnalPrompt(Prompt) == false)
229 {
230 c2out << _("Abort.") << std::endl;
231 exit(1);
232 }
233 }
234 else
235 {
236 // Prompt to continue
237 if (Ask == true || Fail == true)
238 {
239 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
240 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
241
242 if (_config->FindI("quiet",0) < 2 &&
243 _config->FindB("APT::Get::Assume-Yes",false) == false)
244 {
245 c2out << _("Do you want to continue?") << std::flush;
246 if (YnPrompt() == false)
247 {
248 c2out << _("Abort.") << std::endl;
249 exit(1);
250 }
251 }
252 }
253 }
254
255 // Just print out the uris an exit if the --print-uris flag was used
256 if (_config->FindB("APT::Get::Print-URIs") == true)
257 {
258 pkgAcquire::UriIterator I = Fetcher.UriBegin();
259 for (; I != Fetcher.UriEnd(); ++I)
ac69a4d8 260 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
b9179170
MV
261 I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
262 return true;
263 }
264
866893a6 265 if (!CheckAuth(Fetcher, true))
b9179170
MV
266 return false;
267
268 /* Unlock the dpkg lock if we are not going to be doing an install
269 after. */
270 if (_config->FindB("APT::Get::Download-Only",false) == true)
271 _system->UnLock();
272
273 // Run it
274 while (1)
275 {
276 bool Transient = false;
277 if (_config->FindB("APT::Get::Download",true) == false)
278 {
279 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
280 {
281 if ((*I)->Local == true)
282 {
283 ++I;
284 continue;
285 }
286
287 // Close the item and check if it was found in cache
288 (*I)->Finished();
289 if ((*I)->Complete == false)
290 Transient = true;
291
292 // Clear it out of the fetch list
293 delete *I;
294 I = Fetcher.ItemsBegin();
295 }
296 }
b9179170 297
866893a6
DK
298 bool Failed = false;
299 if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
300 return false;
b9179170
MV
301
302 /* If we are in no download mode and missing files and there were
303 'failures' then the user must specify -m. Furthermore, there
304 is no such thing as a transient error in no-download mode! */
305 if (Transient == true &&
306 _config->FindB("APT::Get::Download",true) == false)
307 {
308 Transient = false;
309 Failed = true;
310 }
311
312 if (_config->FindB("APT::Get::Download-Only",false) == true)
313 {
314 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
315 return _error->Error(_("Some files failed to download"));
316 c1out << _("Download complete and in download only mode") << std::endl;
317 return true;
318 }
319
320 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
321 {
322 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
323 }
324
325 if (Transient == true && Failed == true)
326 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
327
328 // Try to deal with missing package files
329 if (Failed == true && PM->FixMissing() == false)
330 {
331 c2out << _("Unable to correct missing packages.") << std::endl;
332 return _error->Error(_("Aborting install."));
333 }
334
335 _system->UnLock();
e6ad8031 336
bd5f39b3
MV
337#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
338 APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
e6ad8031
MV
339 pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
340 delete progress;
bd5f39b3
MV
341#else
342 int status_fd = _config->FindI("APT::Status-Fd", -1);
343 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
344#endif
e6ad8031 345
b9179170
MV
346 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
347 return false;
348 if (Res == pkgPackageManager::Completed)
349 break;
350
351 // Reload the fetcher object and loop again for media swapping
352 Fetcher.Shutdown();
353 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
354 return false;
355
356 _system->Lock();
357 }
358
359 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
360 if (disappearedPkgs.empty() == true)
361 return true;
362
363 std::string disappear;
364 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
365 d != disappearedPkgs.end(); ++d)
366 disappear.append(*d).append(" ");
367
368 ShowList(c1out, P_("The following package disappeared from your system as\n"
369 "all files have been overwritten by other packages:",
370 "The following packages disappeared from your system as\n"
371 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
372 c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl;
373
374 return true;
375}
376 /*}}}*/
b9179170
MV
377// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
378// ---------------------------------------------------------------------
379/* Remove unused automatic packages */
c3ccac92 380static bool DoAutomaticRemove(CacheFile &Cache)
b9179170
MV
381{
382 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
383 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
384 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
385
386 pkgDepCache::ActionGroup group(*Cache);
387 if(Debug)
388 std::cout << "DoAutomaticRemove()" << std::endl;
389
390 if (doAutoRemove == true &&
391 _config->FindB("APT::Get::Remove",true) == false)
392 {
393 c1out << _("We are not supposed to delete stuff, can't start "
394 "AutoRemover") << std::endl;
395 return false;
396 }
397
398 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
399 bool smallList = (hideAutoRemove == false &&
400 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
401
402 unsigned long autoRemoveCount = 0;
403 APT::PackageSet tooMuch;
404 APT::PackageList autoRemoveList;
405 // look over the cache to see what can be removed
406 for (unsigned J = 0; J < Cache->Head().PackageCount; ++J)
407 {
408 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
409 if (Cache[Pkg].Garbage)
410 {
411 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
412 if(Debug)
413 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
414
415 if (doAutoRemove)
416 {
417 if(Pkg.CurrentVer() != 0 &&
418 Pkg->CurrentState != pkgCache::State::ConfigFiles)
419 Cache->MarkDelete(Pkg, purgePkgs, 0, false);
420 else
421 Cache->MarkKeep(Pkg, false, false);
422 }
423 else
424 {
425 if (hideAutoRemove == false && Cache[Pkg].Delete() == false)
426 autoRemoveList.insert(Pkg);
427 // if the package is a new install and already garbage we don't need to
428 // install it in the first place, so nuke it instead of show it
429 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
430 {
431 if (Pkg.CandVersion() != 0)
432 tooMuch.insert(Pkg);
433 Cache->MarkDelete(Pkg, false, 0, false);
434 }
435 // only show stuff in the list that is not yet marked for removal
436 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
437 ++autoRemoveCount;
438 }
439 }
440 }
441
442 // we could have removed a new dependency of a garbage package,
443 // so check if a reverse depends is broken and if so install it again.
444 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
445 {
446 bool Changed;
447 do {
448 Changed = false;
449 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
3a7a206f 450 Pkg != tooMuch.end(); ++Pkg)
b9179170
MV
451 {
452 APT::PackageSet too;
453 too.insert(*Pkg);
454 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
455 Prv.end() == false; ++Prv)
456 too.insert(Prv.ParentPkg());
3a7a206f
DK
457 for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
458 {
b9179170
MV
459 for (pkgCache::DepIterator R = P.RevDependsList();
460 R.end() == false; ++R)
461 {
462 if (R.IsNegative() == true ||
463 Cache->IsImportantDep(R) == false)
464 continue;
465 pkgCache::PkgIterator N = R.ParentPkg();
466 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
467 continue;
468 if (Debug == true)
469 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
470 Cache->MarkInstall(Pkg, false, 0, false);
471 if (hideAutoRemove == false)
472 ++autoRemoveCount;
473 tooMuch.erase(Pkg);
474 Changed = true;
475 break;
476 }
3a7a206f
DK
477 if (Changed == true)
478 break;
b9179170 479 }
3a7a206f
DK
480 if (Changed == true)
481 break;
b9179170
MV
482 }
483 } while (Changed == true);
484 }
485
486 std::string autoremovelist, autoremoveversions;
487 if (smallList == false && autoRemoveCount != 0)
488 {
489 for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg)
490 {
491 if (Cache[Pkg].Garbage == false)
492 continue;
493 autoremovelist += Pkg.FullName(true) + " ";
494 autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n";
495 }
496 }
497
498 // Now see if we had destroyed anything (if we had done anything)
499 if (Cache->BrokenCount() != 0)
500 {
501 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
502 "shouldn't happen. Please file a bug report against apt.") << std::endl;
503 c1out << std::endl;
504 c1out << _("The following information may help to resolve the situation:") << std::endl;
505 c1out << std::endl;
506 ShowBroken(c1out,Cache,false);
507
508 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
509 }
510
511 // if we don't remove them, we should show them!
512 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
513 {
514 if (smallList == false)
515 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
516 "The following packages were automatically installed and are no longer required:",
517 autoRemoveCount), autoremovelist, autoremoveversions);
518 else
519 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
520 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
521 c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl;
522 }
523 return true;
524}
525 /*}}}*/
ee0167c4 526// DoCacheManipulationFromCommandLine /*{{{*/
d8a8f9d7
MV
527static const unsigned short MOD_REMOVE = 1;
528static const unsigned short MOD_INSTALL = 2;
b9179170 529
172947cd 530bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
d8a8f9d7
MV
531{
532 std::map<unsigned short, APT::VersionSet> verset;
172947cd 533 return DoCacheManipulationFromCommandLine(CmdL, Cache, verset, UpgradeMode);
d8a8f9d7 534}
d8a8f9d7 535bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
172947cd 536 std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
b9179170 537{
b9179170
MV
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
be0270de 543 SPtr<pkgProblemResolver> Fix;
b9179170
MV
544 if (_config->FindB("APT::Get::CallResolver", true) == true)
545 Fix = new pkgProblemResolver(Cache);
546
b9179170
MV
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);
d8a8f9d7 567 verset = APT::VersionSet::GroupedFromCommandLine(Cache,
b9179170
MV
568 CmdL.FileList + 1, mods, fallback, helper);
569
570 if (_error->PendingError() == true)
571 {
572 helper.showVirtualPackageErrors(Cache);
b9179170
MV
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 {
b9179170
MV
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);
b9179170
MV
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
172947cd 622 bool resolver_fail = false;
2a884c61
DK
623 OpTextProgress Progress(*_config);
624 bool const distUpgradeMode = strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0;
625
172947cd
DK
626 if (UpgradeMode == 0)
627 {
2a884c61
DK
628 if (distUpgradeMode == true)
629 resolver_fail = APT::Upgrade::Upgrade(Cache, 0, &Progress);
172947cd 630 else
2a884c61 631 resolver_fail = Fix->Resolve(true, &Progress);
172947cd 632 } else
2a884c61 633 resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode, &Progress);
172947cd
DK
634
635 if (resolver_fail == false && Cache->BrokenCount() == 0)
58377ceb 636 return false;
b9179170
MV
637 }
638
639 // Now we check the state of the packages,
640 if (Cache->BrokenCount() != 0)
641 {
642 c1out <<
643 _("Some packages could not be installed. This may mean that you have\n"
644 "requested an impossible situation or if you are using the unstable\n"
645 "distribution that some required packages have not yet been created\n"
646 "or been moved out of Incoming.") << std::endl;
647 /*
648 if (Packages == 1)
649 {
650 c1out << std::endl;
651 c1out <<
652 _("Since you only requested a single operation it is extremely likely that\n"
653 "the package is simply not installable and a bug report against\n"
654 "that package should be filed.") << std::endl;
655 }
656 */
657
658 c1out << _("The following information may help to resolve the situation:") << std::endl;
659 c1out << std::endl;
660 ShowBroken(c1out,Cache,false);
661 if (_error->PendingError() == true)
662 return false;
663 else
664 return _error->Error(_("Broken packages"));
665 }
666 }
667 if (!DoAutomaticRemove(Cache))
668 return false;
669
d8a8f9d7
MV
670 // if nothing changed in the cache, but only the automark information
671 // we write the StateFile here, otherwise it will be written in
672 // cache.commit()
673 if (InstallAction.AutoMarkChanged > 0 &&
674 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
675 Cache->BadCount() == 0 &&
676 _config->FindB("APT::Get::Simulate",false) == false)
677 Cache->writeStateFile(NULL);
678
679 return true;
680}
ee0167c4 681 /*}}}*/
d8a8f9d7
MV
682// DoInstall - Install packages from the command line /*{{{*/
683// ---------------------------------------------------------------------
684/* Install named packages */
685bool DoInstall(CommandLine &CmdL)
686{
687 CacheFile Cache;
0d29b9d4
MV
688 // first check for local pkgs and add them to the cache
689 for (const char **I = CmdL.FileList; *I != 0; I++)
690 {
691 if(FileExists(*I))
692 {
eafc5435
MV
693 // FIXME: make this more elegant
694 std::string TypeStr = flExtension(*I) + "-file";
695 pkgSourceList::Type *Type = pkgSourceList::Type::GetType(TypeStr.c_str());
696 if(Type != 0)
697 {
698 std::vector<metaIndex *> List;
699 std::map<std::string, std::string> Options;
700 if(Type->CreateItem(List, *I, "", "", Options))
701 {
aaf677da
MV
702 // we have our own CacheFile that gives us a SourceList
703 // with superpowerz
704 SourceList *sources = (SourceList*)Cache.GetSourceList();
94f66115 705 sources->AddMetaIndex(List[0]);
eafc5435
MV
706 }
707 }
0d29b9d4
MV
708 }
709 }
710
711 // then open the cache
d8a8f9d7
MV
712 if (Cache.OpenForInstall() == false ||
713 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
714 return false;
0d29b9d4 715
d8a8f9d7
MV
716 std::map<unsigned short, APT::VersionSet> verset;
717
172947cd 718 if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset, 0))
d8a8f9d7
MV
719 return false;
720
b9179170
MV
721 /* Print out a list of packages that are going to be installed extra
722 to what the user asked */
723 if (Cache->InstCount() != verset[MOD_INSTALL].size())
724 {
725 std::string List;
726 std::string VersionsList;
727 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
728 {
729 pkgCache::PkgIterator I(Cache,Cache.List[J]);
730 if ((*Cache)[I].Install() == false)
731 continue;
732 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
733
734 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
735 continue;
736
737 List += I.FullName(true) + " ";
738 VersionsList += std::string(Cache[I].CandVersion) + "\n";
739 }
740
741 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
742 }
743
744 /* Print out a list of suggested and recommended packages */
745 {
746 std::string SuggestsList, RecommendsList;
747 std::string SuggestsVersions, RecommendsVersions;
748 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
749 {
750 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
751
752 /* Just look at the ones we want to install */
753 if ((*Cache)[Pkg].Install() == false)
754 continue;
755
756 // get the recommends/suggests for the candidate ver
757 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
758 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
759 {
760 pkgCache::DepIterator Start;
761 pkgCache::DepIterator End;
762 D.GlobOr(Start,End); // advances D
763
764 // FIXME: we really should display a or-group as a or-group to the user
765 // the problem is that ShowList is incapable of doing this
766 std::string RecommendsOrList,RecommendsOrVersions;
767 std::string SuggestsOrList,SuggestsOrVersions;
768 bool foundInstalledInOrGroup = false;
769 for(;;)
770 {
771 /* Skip if package is installed already, or is about to be */
772 std::string target = Start.TargetPkg().FullName(true) + " ";
773 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
774 if (TarPkg->SelectedState == pkgCache::State::Install ||
775 TarPkg->SelectedState == pkgCache::State::Hold ||
776 Cache[Start.TargetPkg()].Install())
777 {
778 foundInstalledInOrGroup=true;
779 break;
780 }
781
782 /* Skip if we already saw it */
783 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
784 {
785 foundInstalledInOrGroup=true;
786 break;
787 }
788
789 // this is a dep on a virtual pkg, check if any package that provides it
790 // should be installed
791 if(Start.TargetPkg().ProvidesList() != 0)
792 {
793 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
794 for (; I.end() == false; ++I)
795 {
796 pkgCache::PkgIterator Pkg = I.OwnerPkg();
797 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
798 Pkg.CurrentVer() != 0)
799 foundInstalledInOrGroup=true;
800 }
801 }
802
803 if (Start->Type == pkgCache::Dep::Suggests)
804 {
805 SuggestsOrList += target;
806 SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
807 }
808
809 if (Start->Type == pkgCache::Dep::Recommends)
810 {
811 RecommendsOrList += target;
812 RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n";
813 }
814
815 if (Start >= End)
816 break;
817 ++Start;
818 }
819
820 if(foundInstalledInOrGroup == false)
821 {
822 RecommendsList += RecommendsOrList;
823 RecommendsVersions += RecommendsOrVersions;
824 SuggestsList += SuggestsOrList;
825 SuggestsVersions += SuggestsOrVersions;
826 }
827
828 }
829 }
830
831 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
832 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
833
834 }
835
b9179170
MV
836 // See if we need to prompt
837 // FIXME: check if really the packages in the set are going to be installed
838 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
839 return InstallPackages(Cache,false,false);
840
841 return InstallPackages(Cache,false);
842}
843 /*}}}*/
4d695011
DK
844
845// TryToInstall - Mark a package for installation /*{{{*/
846void TryToInstall::operator() (pkgCache::VerIterator const &Ver) {
847 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
848
849 Cache->GetDepCache()->SetCandidateVersion(Ver);
850 pkgDepCache::StateCache &State = (*Cache)[Pkg];
851
852 // Handle the no-upgrade case
853 if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
854 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
855 Pkg.FullName(true).c_str());
856 // Ignore request for install if package would be new
857 else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
858 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
859 Pkg.FullName(true).c_str());
860 else {
861 if (Fix != NULL) {
862 Fix->Clear(Pkg);
863 Fix->Protect(Pkg);
864 }
865 Cache->GetDepCache()->MarkInstall(Pkg,false);
866
867 if (State.Install() == false) {
868 if (_config->FindB("APT::Get::ReInstall",false) == true) {
869 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
870 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
871 Pkg.FullName(true).c_str());
872 else
873 Cache->GetDepCache()->SetReInstall(Pkg, true);
874 } else
875 ioprintf(c1out,_("%s is already the newest version.\n"),
876 Pkg.FullName(true).c_str());
877 }
878
879 // Install it with autoinstalling enabled (if we not respect the minial
880 // required deps or the policy)
881 if (FixBroken == false)
882 doAutoInstallLater.insert(Pkg);
883 }
884
885 // see if we need to fix the auto-mark flag
886 // e.g. apt-get install foo
887 // where foo is marked automatic
888 if (State.Install() == false &&
889 (State.Flags & pkgCache::Flag::Auto) &&
890 _config->FindB("APT::Get::ReInstall",false) == false &&
891 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
892 _config->FindB("APT::Get::Download-Only",false) == false)
893 {
894 ioprintf(c1out,_("%s set to manually installed.\n"),
895 Pkg.FullName(true).c_str());
896 Cache->GetDepCache()->MarkAuto(Pkg,false);
897 AutoMarkChanged++;
898 }
899}
900 /*}}}*/
901bool TryToInstall::propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > const &start, std::ostream &out)/*{{{*/
902{
903 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
904 s != start.end(); ++s)
905 Cache->GetDepCache()->SetCandidateVersion(s->first);
906
907 bool Success = true;
908 // the Changed list contains:
909 // first: "new version"
910 // second: "what-caused the change"
911 std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
912 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
913 s != start.end(); ++s)
914 {
915 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
916 // We continue here even if it failed to enhance the ShowBroken output
917 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
918 }
919 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
920 c != Changed.end(); ++c)
921 {
922 if (c->second.end() == true)
923 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
924 c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
925 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
926 {
927 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
928 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
929 V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
930 }
931 }
932 return Success;
933}
934 /*}}}*/
935void TryToInstall::doAutoInstall() { /*{{{*/
936 for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
937 P != doAutoInstallLater.end(); ++P) {
938 pkgDepCache::StateCache &State = (*Cache)[P];
939 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
940 continue;
941 Cache->GetDepCache()->MarkInstall(P, true);
942 }
943 doAutoInstallLater.clear();
944}
945 /*}}}*/
946// TryToRemove - Mark a package for removal /*{{{*/
947void TryToRemove::operator() (pkgCache::VerIterator const &Ver)
948{
949 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
950
951 if (Fix != NULL)
952 {
953 Fix->Clear(Pkg);
954 Fix->Protect(Pkg);
955 Fix->Remove(Pkg);
956 }
957
958 if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
959 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
960 {
961 pkgCache::GrpIterator Grp = Pkg.Group();
962 pkgCache::PkgIterator P = Grp.PackageList();
963 for (; P.end() != true; P = Grp.NextPkg(P))
964 {
965 if (P == Pkg)
966 continue;
967 if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
968 {
969 // TRANSLATORS: Note, this is not an interactive question
970 ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
971 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
972 break;
973 }
974 }
975 if (P.end() == true)
976 ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
977
978 // MarkInstall refuses to install packages on hold
979 Pkg->SelectedState = pkgCache::State::Hold;
980 }
981 else
982 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
983}
984 /*}}}*/