Local file fixes
[ntk/apt.git] / cmdline / apt-get.cc
CommitLineData
0a8e3465
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
e331f6ed 3// $Id: apt-get.cc,v 1.11 1998/11/14 01:39:48 jgg Exp $
0a8e3465
AL
4/* ######################################################################
5
6 apt-get - Cover for dpkg
7
8 This is an allout cover for dpkg implementing a safer front end. It is
9 based largely on libapt-pkg.
10
11 The syntax is different,
12 apt-get [opt] command [things]
13 Where command is:
14 update - Resyncronize the package files from their sources
15 upgrade - Smart-Download the newest versions of all packages
16 dselect-upgrade - Follows dselect's changes to the Status: field
17 and installes new and removes old packages
18 dist-upgrade - Powerfull upgrader designed to handle the issues with
19 a new distribution.
20 install - Download and install a given package (by name, not by .deb)
21 check - Update the package cache and check for broken packages
22 clean - Erase the .debs downloaded to /var/cache/apt/archives and
23 the partial dir too
24
25 ##################################################################### */
26 /*}}}*/
27// Include Files /*{{{*/
28#include <apt-pkg/error.h>
29#include <apt-pkg/cmndline.h>
30#include <apt-pkg/init.h>
31#include <apt-pkg/depcache.h>
32#include <apt-pkg/sourcelist.h>
33#include <apt-pkg/pkgcachegen.h>
34#include <apt-pkg/algorithms.h>
0919e3f9 35#include <apt-pkg/acquire-item.h>
03e39e59 36#include <apt-pkg/dpkgpm.h>
a6568219 37#include <strutl.h>
0a8e3465
AL
38
39#include <config.h>
40
0919e3f9
AL
41#include "acqprogress.h"
42
0a8e3465 43#include <fstream.h>
d7827aca
AL
44#include <termios.h>
45#include <sys/ioctl.h>
46#include <signal.h>
0a8e3465
AL
47 /*}}}*/
48
49ostream c0out;
50ostream c1out;
51ostream c2out;
52ofstream devnull("/dev/null");
53unsigned int ScreenWidth = 80;
54
a6568219
AL
55// YnPrompt - Yes No Prompt. /*{{{*/
56// ---------------------------------------------------------------------
57/* Returns true on a Yes.*/
58bool YnPrompt()
59{
60 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
61 {
62 c2out << 'Y' << endl;
63 return true;
64 }
65
66 char C = 0;
67 char Jnk = 0;
68 read(STDIN_FILENO,&C,1);
69 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
70
71 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
72 return false;
73 return true;
74}
75 /*}}}*/
0a8e3465
AL
76// ShowList - Show a list /*{{{*/
77// ---------------------------------------------------------------------
78/* This prints out a string of space seperated words with a title and
79 a two space indent line wraped to the current screen width. */
80void ShowList(ostream &out,string Title,string List)
81{
82 if (List.empty() == true)
83 return;
84
85 // Acount for the leading space
86 int ScreenWidth = ::ScreenWidth - 3;
87
88 out << Title << endl;
89 string::size_type Start = 0;
90 while (Start < List.size())
91 {
92 string::size_type End;
93 if (Start + ScreenWidth >= List.size())
94 End = List.size();
95 else
96 End = List.rfind(' ',Start+ScreenWidth);
97
98 if (End == string::npos || End < Start)
99 End = Start + ScreenWidth;
100 out << " " << string(List,Start,End - Start) << endl;
101 Start = End + 1;
102 }
103}
104 /*}}}*/
105// ShowBroken - Debugging aide /*{{{*/
106// ---------------------------------------------------------------------
107/* This prints out the names of all the packages that are broken along
108 with the name of each each broken dependency and a quite version
109 description. */
110void ShowBroken(ostream &out,pkgDepCache &Cache)
111{
112 out << "Sorry, but the following packages are broken - this means they have unmet" << endl;
113 out << "dependencies:" << endl;
114 pkgCache::PkgIterator I = Cache.PkgBegin();
115 for (;I.end() != true; I++)
116 {
303a1703
AL
117 if (Cache[I].InstBroken() == false)
118 continue;
119
120 // Print out each package and the failed dependencies
121 out <<" " << I.Name() << ":";
122 int Indent = strlen(I.Name()) + 3;
123 bool First = true;
124 if (Cache[I].InstVerIter(Cache).end() == true)
0a8e3465 125 {
303a1703
AL
126 cout << endl;
127 continue;
128 }
129
130 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
131 {
132 if (Cache.IsImportantDep(D) == false || (Cache[D] &
133 pkgDepCache::DepInstall) != 0)
134 continue;
135
136 if (First == false)
137 for (int J = 0; J != Indent; J++)
138 out << ' ';
139 First = false;
140
141 if (D->Type == pkgCache::Dep::Conflicts)
142 out << " Conflicts:" << D.TargetPkg().Name();
143 else
144 out << " Depends:" << D.TargetPkg().Name();
145
146 // Show a quick summary of the version requirements
147 if (D.TargetVer() != 0)
148 out << " (" << D.CompType() << " " << D.TargetVer() <<
149 ")";
150
151 /* Show a summary of the target package if possible. In the case
152 of virtual packages we show nothing */
153
154 pkgCache::PkgIterator Targ = D.TargetPkg();
155 if (Targ->ProvidesList == 0)
0a8e3465 156 {
303a1703
AL
157 out << " but ";
158 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
159 if (Ver.end() == false)
160 out << Ver.VerStr() << " is installed";
0a8e3465 161 else
7e798dd7 162 {
303a1703
AL
163 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
164 {
165 if (Targ->ProvidesList == 0)
166 out << "it is not installable";
167 else
168 out << "it is a virtual package";
169 }
7e798dd7
AL
170 else
171 out << "it is not installed";
303a1703
AL
172 }
173 }
174
175 out << endl;
176 }
0a8e3465
AL
177 }
178}
179 /*}}}*/
180// ShowNew - Show packages to newly install /*{{{*/
181// ---------------------------------------------------------------------
182/* */
183void ShowNew(ostream &out,pkgDepCache &Dep)
184{
185 /* Print out a list of packages that are going to be removed extra
186 to what the user asked */
187 pkgCache::PkgIterator I = Dep.PkgBegin();
188 string List;
189 for (;I.end() != true; I++)
190 if (Dep[I].NewInstall() == true)
191 List += string(I.Name()) + " ";
192 ShowList(out,"The following NEW packages will be installed:",List);
193}
194 /*}}}*/
195// ShowDel - Show packages to delete /*{{{*/
196// ---------------------------------------------------------------------
197/* */
198void ShowDel(ostream &out,pkgDepCache &Dep)
199{
200 /* Print out a list of packages that are going to be removed extra
201 to what the user asked */
202 pkgCache::PkgIterator I = Dep.PkgBegin();
203 string List;
204 for (;I.end() != true; I++)
205 if (Dep[I].Delete() == true)
206 List += string(I.Name()) + " ";
207 ShowList(out,"The following packages will be REMOVED:",List);
208}
209 /*}}}*/
210// ShowKept - Show kept packages /*{{{*/
211// ---------------------------------------------------------------------
212/* */
213void ShowKept(ostream &out,pkgDepCache &Dep)
214{
215 pkgCache::PkgIterator I = Dep.PkgBegin();
216 string List;
217 for (;I.end() != true; I++)
218 {
219 // Not interesting
220 if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
221 I->CurrentVer == 0 || Dep[I].Delete() == true)
222 continue;
223
224 List += string(I.Name()) + " ";
225 }
226 ShowList(out,"The following packages have been kept back",List);
227}
228 /*}}}*/
229// ShowUpgraded - Show upgraded packages /*{{{*/
230// ---------------------------------------------------------------------
231/* */
232void ShowUpgraded(ostream &out,pkgDepCache &Dep)
233{
234 pkgCache::PkgIterator I = Dep.PkgBegin();
235 string List;
236 for (;I.end() != true; I++)
237 {
238 // Not interesting
239 if (Dep[I].Upgrade() == false || Dep[I].NewInstall() == true)
240 continue;
241
242 List += string(I.Name()) + " ";
243 }
244 ShowList(out,"The following packages will be upgraded",List);
245}
246 /*}}}*/
247// ShowHold - Show held but changed packages /*{{{*/
248// ---------------------------------------------------------------------
249/* */
250void ShowHold(ostream &out,pkgDepCache &Dep)
251{
252 pkgCache::PkgIterator I = Dep.PkgBegin();
253 string List;
254 for (;I.end() != true; I++)
255 {
256 if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
257 I->SelectedState == pkgCache::State::Hold)
258 List += string(I.Name()) + " ";
259 }
260
261 ShowList(out,"The following held packages will be changed:",List);
262}
263 /*}}}*/
264// ShowEssential - Show an essential package warning /*{{{*/
265// ---------------------------------------------------------------------
266/* This prints out a warning message that is not to be ignored. It shows
267 all essential packages and their dependents that are to be removed.
268 It is insanely risky to remove the dependents of an essential package! */
269void ShowEssential(ostream &out,pkgDepCache &Dep)
270{
271 pkgCache::PkgIterator I = Dep.PkgBegin();
272 string List;
273 bool *Added = new bool[Dep.HeaderP->PackageCount];
93641593 274 for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
0a8e3465
AL
275 Added[I] = false;
276
277 for (;I.end() != true; I++)
278 {
279 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
280 continue;
281
282 // The essential package is being removed
283 if (Dep[I].Delete() == true)
284 {
285 if (Added[I->ID] == false)
286 {
287 Added[I->ID] = true;
288 List += string(I.Name()) + " ";
289 }
290 }
291
292 if (I->CurrentVer == 0)
293 continue;
294
295 // Print out any essential package depenendents that are to be removed
296 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
297 {
298 pkgCache::PkgIterator P = D.SmartTargetPkg();
299 if (Dep[P].Delete() == true)
300 {
301 if (Added[P->ID] == true)
302 continue;
303 Added[P->ID] = true;
304 List += string(P.Name()) + " ";
305 }
306 }
307 }
308
309 if (List.empty() == false)
310 out << "WARNING: The following essential packages will be removed" << endl;
311 ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
312
313 delete [] Added;
314}
315 /*}}}*/
316// Stats - Show some statistics /*{{{*/
317// ---------------------------------------------------------------------
318/* */
319void Stats(ostream &out,pkgDepCache &Dep)
320{
321 unsigned long Upgrade = 0;
322 unsigned long Install = 0;
323 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
324 {
325 if (Dep[I].NewInstall() == true)
326 Install++;
327 else
328 if (Dep[I].Upgrade() == true)
329 Upgrade++;
330 }
331
332 out << Upgrade << " packages upgraded, " <<
333 Install << " newly installed, " <<
334 Dep.DelCount() << " to remove and " <<
335 Dep.KeepCount() << " not upgraded." << endl;
336
337 if (Dep.BadCount() != 0)
338 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
339}
340 /*}}}*/
341
342// class CacheFile - Cover class for some dependency cache functions /*{{{*/
343// ---------------------------------------------------------------------
344/* */
345class CacheFile
346{
347 public:
348
349 FileFd *File;
350 MMap *Map;
351 pkgDepCache *Cache;
352
353 inline operator pkgDepCache &() {return *Cache;};
354 inline pkgDepCache *operator ->() {return Cache;};
355 inline pkgDepCache &operator *() {return *Cache;};
356
357 bool Open();
358 CacheFile() : File(0), Map(0), Cache(0) {};
359 ~CacheFile()
360 {
361 delete Cache;
362 delete Map;
363 delete File;
364 }
365};
366 /*}}}*/
367// CacheFile::Open - Open the cache file /*{{{*/
368// ---------------------------------------------------------------------
369/* This routine generates the caches and then opens the dependency cache
370 and verifies that the system is OK. */
371bool CacheFile::Open()
372{
373 // Create a progress class
374 OpTextProgress Progress(*_config);
375
376 // Read the source list
377 pkgSourceList List;
378 if (List.ReadMainList() == false)
379 return _error->Error("The list of sources could not be read.");
380
381 // Build all of the caches
382 pkgMakeStatusCache(List,Progress);
383 if (_error->PendingError() == true)
384 return _error->Error("The package lists or status file could not be parsed or opened.");
385
386 Progress.Done();
387
388 // Open the cache file
303a1703 389 File = new FileFd(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
0a8e3465
AL
390 if (_error->PendingError() == true)
391 return false;
392
393 Map = new MMap(*File,MMap::Public | MMap::ReadOnly);
394 if (_error->PendingError() == true)
395 return false;
396
397 Cache = new pkgDepCache(*Map,Progress);
398 if (_error->PendingError() == true)
399 return false;
400
401 Progress.Done();
402
403 // Check that the system is OK
404 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
405 return _error->Error("Internal Error, non-zero counts");
406
407 // Apply corrections for half-installed packages
408 if (pkgApplyStatus(*Cache) == false)
409 return false;
410
411 // Nothing is broken
412 if (Cache->BrokenCount() == 0)
413 return true;
414
415 // Attempt to fix broken things
416 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
417 {
418 c1out << "Correcting dependencies..." << flush;
419 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
420 {
421 c1out << " failed." << endl;
422 ShowBroken(c1out,*this);
423
424 return _error->Error("Unable to correct dependencies");
425 }
7e798dd7
AL
426 if (pkgMinimizeUpgrade(*Cache) == false)
427 return _error->Error("Unable to minimize the upgrade set");
0a8e3465
AL
428
429 c1out << " Done" << endl;
430 }
431 else
432 {
433 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
434 ShowBroken(c1out,*this);
435
436 return _error->Error("Unmet dependencies. Try using -f.");
437 }
438
439 return true;
440}
441 /*}}}*/
442
443// InstallPackages - Actually download and install the packages /*{{{*/
444// ---------------------------------------------------------------------
445/* This displays the informative messages describing what is going to
446 happen and then calls the download routines */
03e39e59 447bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
0a8e3465 448{
a6568219 449 // Show all the various warning indicators
0a8e3465
AL
450 ShowDel(c1out,Cache);
451 ShowNew(c1out,Cache);
452 if (ShwKept == true)
453 ShowKept(c1out,Cache);
454 ShowHold(c1out,Cache);
455 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
456 ShowUpgraded(c1out,Cache);
457 ShowEssential(c1out,Cache);
458 Stats(c1out,Cache);
459
460 // Sanity check
461 if (Cache.BrokenCount() != 0)
462 {
463 ShowBroken(c1out,Cache);
464 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
465 }
466
467 if (Cache.DelCount() == 0 && Cache.InstCount() == 0 &&
468 Cache.BadCount() == 0)
469 return true;
03e39e59
AL
470
471 // Run the simulator ..
472 if (_config->FindB("APT::Get::Simulate") == true)
473 {
474 pkgSimulate PM(Cache);
475 return PM.DoInstall();
476 }
477
478 // Create the text record parser
479 pkgRecords Recs(Cache);
480
481 // Create the download object
482 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
483 pkgAcquire Fetcher(&Stat);
484
485 // Read the source list
486 pkgSourceList List;
487 if (List.ReadMainList() == false)
488 return _error->Error("The list of sources could not be read.");
489
490 // Create the package manager and prepare to download
491 pkgPackageManager PM(Cache);
492 if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
493 return false;
494
a6568219
AL
495 unsigned long FetchBytes = Fetcher.FetchNeeded();
496 unsigned long DebBytes = Fetcher.TotalNeeded();
497 if (DebBytes != Cache.DebSize())
498 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
499
500 c1out << "Need to get ";
501 if (DebBytes != FetchBytes)
502 c1out << SizeToStr(FetchBytes) << '/' << SizeToStr(DebBytes);
503 else
504 c1out << SizeToStr(DebBytes);
505
506 c1out << " of archives. After unpacking ";
507
508 if (Cache.UsrSize() >= 0)
509 c1out << SizeToStr(Cache.UsrSize()) << " will be used." << endl;
510 else
511 c1out << SizeToStr(-1*Cache.UsrSize()) << " will be freed." << endl;
512
513 if (_error->PendingError() == true)
514 return false;
515
516 if (Ask == true)
e331f6ed 517 {
a6568219
AL
518 if (_config->FindI("quiet",0) < 2 ||
519 _config->FindB("APT::Get::Assume-Yes",false) == false)
520 c2out << "Do you want to continue? [Y/n] " << flush;
521 if (YnPrompt() == false)
522 exit(1);
523 }
524
03e39e59
AL
525 // Run it
526 if (Fetcher.Run() == false)
527 return false;
528
0a8e3465
AL
529 return true;
530}
531 /*}}}*/
532
533// DoUpdate - Update the package lists /*{{{*/
534// ---------------------------------------------------------------------
535/* */
0919e3f9 536bool DoUpdate(CommandLine &)
0a8e3465 537{
0919e3f9
AL
538 // Get the source list
539 pkgSourceList List;
540 if (List.ReadMainList() == false)
541 return false;
542
543 // Create the download object
544 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
545 pkgAcquire Fetcher(&Stat);
546
547 // Populate it with the source selection
548 pkgSourceList::const_iterator I;
549 for (I = List.begin(); I != List.end(); I++)
550 {
551 new pkgAcqIndex(&Fetcher,I);
552 if (_error->PendingError() == true)
553 return false;
554 }
555
556 // Run it
557 if (Fetcher.Run() == false)
558 return false;
559
7a7fa5f0
AL
560 // Clean out any old list files
561 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
562 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
563 return false;
564
0919e3f9
AL
565 // Prepare the cache.
566 CacheFile Cache;
567 if (Cache.Open() == false)
568 return false;
569
570 return true;
0a8e3465
AL
571}
572 /*}}}*/
573// DoUpgrade - Upgrade all packages /*{{{*/
574// ---------------------------------------------------------------------
575/* Upgrade all packages without installing new packages or erasing old
576 packages */
577bool DoUpgrade(CommandLine &CmdL)
578{
579 CacheFile Cache;
580 if (Cache.Open() == false)
581 return false;
582
583 // Do the upgrade
0a8e3465
AL
584 if (pkgAllUpgrade(Cache) == false)
585 {
586 ShowBroken(c1out,Cache);
587 return _error->Error("Internal Error, AllUpgrade broke stuff");
588 }
589
590 return InstallPackages(Cache,true);
591}
592 /*}}}*/
593// DoInstall - Install packages from the command line /*{{{*/
594// ---------------------------------------------------------------------
595/* Install named packages */
596bool DoInstall(CommandLine &CmdL)
597{
598 CacheFile Cache;
599 if (Cache.Open() == false)
600 return false;
601
a6568219
AL
602 unsigned int ExpectedInst = 0;
603 unsigned int Packages = 0;
0a8e3465
AL
604 pkgProblemResolver Fix(Cache);
605
303a1703
AL
606 bool DefRemove = false;
607 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
608 DefRemove = true;
609
0a8e3465
AL
610 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
611 {
612 // Duplicate the string
613 unsigned int Length = strlen(*I);
614 char S[300];
615 if (Length >= sizeof(S))
616 continue;
617 strcpy(S,*I);
618
619 // See if we are removing the package
303a1703 620 bool Remove = DefRemove;
0a8e3465
AL
621 if (S[Length - 1] == '-')
622 {
623 Remove = true;
624 S[--Length] = 0;
625 }
303a1703
AL
626 if (S[Length - 1] == '+')
627 {
628 Remove = false;
629 S[--Length] = 0;
630 }
0a8e3465
AL
631
632 // Locate the package
633 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
303a1703 634 Packages++;
0a8e3465
AL
635 if (Pkg.end() == true)
636 return _error->Error("Couldn't find package %s",S);
637
638 // Check if there is something new to install
639 pkgDepCache::StateCache &State = (*Cache)[Pkg];
640 if (State.CandidateVer == 0)
303a1703
AL
641 {
642 if (Pkg->ProvidesList != 0)
643 {
644 c1out << "Package " << S << " is a virtual package provided by:" << endl;
645
646 pkgCache::PrvIterator I = Pkg.ProvidesList();
647 for (; I.end() == false; I++)
648 {
649 pkgCache::PkgIterator Pkg = I.OwnerPkg();
650
651 if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
652 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
653
654 if ((*Cache)[Pkg].InstVerIter(*Cache) == I.OwnerVer())
655 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
656 " [Installed]"<< endl;
657 }
658 c1out << "You should explicly select one to install." << endl;
659 }
660 else
661 {
662 c1out << "Package " << S << " has no available version, but exists in the database." << endl;
663 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
664 c1out << "never uploaded, or that it is an obsolete package." << endl;
665 }
666
0a8e3465 667 return _error->Error("Package %s has no installation candidate",S);
303a1703 668 }
0a8e3465
AL
669
670 Fix.Protect(Pkg);
671 if (Remove == true)
672 {
303a1703 673 Fix.Remove(Pkg);
0a8e3465
AL
674 Cache->MarkDelete(Pkg);
675 continue;
676 }
677
678 // Install it
679 Cache->MarkInstall(Pkg,false);
680 if (State.Install() == false)
681 c1out << "Sorry, " << S << " is already the newest version" << endl;
682 else
683 ExpectedInst++;
684
685 // Install it with autoinstalling enabled.
686 if (State.InstBroken() == true)
687 Cache->MarkInstall(Pkg,true);
688 }
689
690 // Call the scored problem resolver
303a1703 691 Fix.InstallProtect();
0a8e3465
AL
692 if (Fix.Resolve(true) == false)
693 _error->Discard();
694
695 // Now we check the state of the packages,
696 if (Cache->BrokenCount() != 0)
697 {
303a1703
AL
698 c1out << "Some packages could not be installed. This may mean that you have" << endl;
699 c1out << "requested an impossible situation or if you are using the unstable" << endl;
700 c1out << "distribution that some required packages have not yet been created" << endl;
701 c1out << "or been moved out of Incoming." << endl;
702 if (Packages == 1)
703 {
704 c1out << endl;
705 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
706 c1out << "the package is simply not installable and a bug report against" << endl;
707 c1out << "that package should be filed." << endl;
708 }
709
710 c1out << "The following information may help to resolve the situation:" << endl;
711 c1out << endl;
0a8e3465
AL
712 ShowBroken(c1out,Cache);
713 return _error->Error("Sorry, broken packages");
714 }
715
716 /* Print out a list of packages that are going to be installed extra
717 to what the user asked */
718 if (Cache->InstCount() != ExpectedInst)
719 {
720 string List;
721 pkgCache::PkgIterator I = Cache->PkgBegin();
722 for (;I.end() != true; I++)
723 {
724 if ((*Cache)[I].Install() == false)
725 continue;
726
727 const char **J;
728 for (J = CmdL.FileList + 1; *J != 0; J++)
729 if (strcmp(*J,I.Name()) == 0)
730 break;
731
732 if (*J == 0)
733 List += string(I.Name()) + " ";
734 }
735
736 ShowList(c1out,"The following extra packages will be installed:",List);
737 }
738
03e39e59
AL
739 // See if we need to prompt
740 if (Cache->InstCount() != ExpectedInst || Cache->DelCount() != 0)
741 return InstallPackages(Cache,false,true);
742 return InstallPackages(Cache,false);
0a8e3465
AL
743}
744 /*}}}*/
745// DoDistUpgrade - Automatic smart upgrader /*{{{*/
746// ---------------------------------------------------------------------
747/* Intelligent upgrader that will install and remove packages at will */
748bool DoDistUpgrade(CommandLine &CmdL)
749{
750 CacheFile Cache;
751 if (Cache.Open() == false)
752 return false;
753
754 c0out << "Calculating Upgrade... " << flush;
755 if (pkgDistUpgrade(*Cache) == false)
756 {
757 c0out << "Failed" << endl;
758 ShowBroken(c1out,Cache);
759 return false;
760 }
761
762 c0out << "Done" << endl;
763
764 return InstallPackages(Cache,true);
765}
766 /*}}}*/
767// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
768// ---------------------------------------------------------------------
769/* Follows dselect's selections */
770bool DoDSelectUpgrade(CommandLine &CmdL)
771{
772 CacheFile Cache;
773 if (Cache.Open() == false)
774 return false;
775
776 // Install everything with the install flag set
777 pkgCache::PkgIterator I = Cache->PkgBegin();
778 for (;I.end() != true; I++)
779 {
780 /* Install the package only if it is a new install, the autoupgrader
781 will deal with the rest */
782 if (I->SelectedState == pkgCache::State::Install)
783 Cache->MarkInstall(I,false);
784 }
785
786 /* Now install their deps too, if we do this above then order of
787 the status file is significant for | groups */
788 for (I = Cache->PkgBegin();I.end() != true; I++)
789 {
790 /* Install the package only if it is a new install, the autoupgrader
791 will deal with the rest */
792 if (I->SelectedState == pkgCache::State::Install)
793 Cache->MarkInstall(I);
794 }
795
796 // Apply erasures now, they override everything else.
797 for (I = Cache->PkgBegin();I.end() != true; I++)
798 {
799 // Remove packages
800 if (I->SelectedState == pkgCache::State::DeInstall ||
801 I->SelectedState == pkgCache::State::Purge)
802 Cache->MarkDelete(I);
803 }
804
805 /* Use updates smart upgrade to do the rest, it will automatically
806 ignore held items */
807 if (pkgAllUpgrade(Cache) == false)
808 {
809 ShowBroken(c1out,Cache);
810 return _error->Error("Internal Error, AllUpgrade broke stuff");
811 }
812
813 return InstallPackages(Cache,false);
814}
815 /*}}}*/
816// DoClean - Remove download archives /*{{{*/
817// ---------------------------------------------------------------------
818/* */
819bool DoClean(CommandLine &CmdL)
820{
821 return true;
822}
823 /*}}}*/
824// DoCheck - Perform the check operation /*{{{*/
825// ---------------------------------------------------------------------
826/* Opening automatically checks the system, this command is mostly used
827 for debugging */
828bool DoCheck(CommandLine &CmdL)
829{
830 CacheFile Cache;
831 Cache.Open();
832
833 return true;
834}
835 /*}}}*/
836
837// ShowHelp - Show a help screen /*{{{*/
838// ---------------------------------------------------------------------
839/* */
840int ShowHelp()
841{
842 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
843 " compiled on " << __DATE__ << " " << __TIME__ << endl;
844
845 cout << "Usage: apt-get [options] command" << endl;
846 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
847 cout << endl;
848 cout << "apt-get is a simple command line interface for downloading and" << endl;
849 cout << "installing packages. The most frequently used commands are update" << endl;
850 cout << "and install." << endl;
851 cout << endl;
852 cout << "Commands:" << endl;
853 cout << " update - Retrieve new lists of packages" << endl;
854 cout << " upgrade - Perform an upgrade" << endl;
855 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
303a1703 856 cout << " remove - Remove packages" << endl;
0a8e3465
AL
857 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
858 cout << " dselect-upgrade - Follow dselect selections" << endl;
859 cout << " clean - Erase downloaded archive files" << endl;
860 cout << " check - Verify that there are no broken dependencies" << endl;
861 cout << endl;
862 cout << "Options:" << endl;
863 cout << " -h This help text." << endl;
864 cout << " -q Loggable output - no progress indicator" << endl;
865 cout << " -qq No output except for errors" << endl;
866 cout << " -d Download only - do NOT install or unpack archives" << endl;
867 cout << " -s No-act. Perform ordering simulation" << endl;
868 cout << " -y Assume Yes to all queries and do not prompt" << endl;
869 cout << " -f Attempt to continue if the integrity check fails" << endl;
870 cout << " -m Attempt to continue if archives are unlocatable" << endl;
871 cout << " -u Show a list of upgraded packages as well" << endl;
872 cout << " -c=? Read this configuration file" << endl;
873 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
874 cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
875 cout << "pages for more information." << endl;
876 return 100;
877}
878 /*}}}*/
879// GetInitialize - Initialize things for apt-get /*{{{*/
880// ---------------------------------------------------------------------
881/* */
882void GetInitialize()
883{
884 _config->Set("quiet",0);
885 _config->Set("help",false);
886 _config->Set("APT::Get::Download-Only",false);
887 _config->Set("APT::Get::Simulate",false);
888 _config->Set("APT::Get::Assume-Yes",false);
889 _config->Set("APT::Get::Fix-Broken",false);
890}
891 /*}}}*/
d7827aca
AL
892// SigWinch - Window size change signal handler /*{{{*/
893// ---------------------------------------------------------------------
894/* */
895void SigWinch(int)
896{
897 // Riped from GNU ls
898#ifdef TIOCGWINSZ
899 struct winsize ws;
900
901 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
902 ScreenWidth = ws.ws_col - 1;
903#endif
904}
905 /*}}}*/
0a8e3465
AL
906
907int main(int argc,const char *argv[])
908{
909 CommandLine::Args Args[] = {
910 {'h',"help","help",0},
911 {'q',"quiet","quiet",CommandLine::IntLevel},
912 {'q',"silent","quiet",CommandLine::IntLevel},
913 {'d',"download-only","APT::Get::Download-Only",0},
914 {'s',"simulate","APT::Get::Simulate",0},
915 {'s',"just-print","APT::Get::Simulate",0},
916 {'s',"recon","APT::Get::Simulate",0},
917 {'s',"no-act","APT::Get::Simulate",0},
918 {'y',"yes","APT::Get::Assume-Yes",0},
919 {'y',"assume-yes","APT::Get::Assume-Yes",0},
920 {'f',"fix-broken","APT::Get::Fix-Broken",0},
921 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
922 {'m',"ignore-missing","APT::Get::Fix-Broken",0},
c88edf1d 923 {0,"ignore-hold","APT::Ingore-Hold",0},
0a8e3465
AL
924 {'c',"config-file",0,CommandLine::ConfigFile},
925 {'o',"option",0,CommandLine::ArbItem},
926 {0,0,0,0}};
927
928 // Parse the command line and initialize the package library
929 CommandLine CmdL(Args,_config);
930 if (pkgInitialize(*_config) == false ||
931 CmdL.Parse(argc,argv) == false)
932 {
933 _error->DumpErrors();
934 return 100;
935 }
936
937 // See if the help should be shown
938 if (_config->FindB("help") == true ||
939 CmdL.FileSize() == 0)
940 return ShowHelp();
941
942 // Setup the output streams
943 c0out.rdbuf(cout.rdbuf());
944 c1out.rdbuf(cout.rdbuf());
945 c2out.rdbuf(cout.rdbuf());
946 if (_config->FindI("quiet",0) > 0)
947 c0out.rdbuf(devnull.rdbuf());
948 if (_config->FindI("quiet",0) > 1)
949 c1out.rdbuf(devnull.rdbuf());
d7827aca
AL
950
951 // Setup the signals
952 signal(SIGPIPE,SIG_IGN);
953 signal(SIGWINCH,SigWinch);
954 SigWinch(0);
0a8e3465
AL
955
956 // Match the operation
957 struct
958 {
959 const char *Match;
960 bool (*Handler)(CommandLine &);
961 } Map[] = {{"update",&DoUpdate},
962 {"upgrade",&DoUpgrade},
963 {"install",&DoInstall},
303a1703 964 {"remove",&DoInstall},
0a8e3465
AL
965 {"dist-upgrade",&DoDistUpgrade},
966 {"dselect-upgrade",&DoDSelectUpgrade},
967 {"clean",&DoClean},
968 {"check",&DoCheck},
969 {0,0}};
970 int I;
971 for (I = 0; Map[I].Match != 0; I++)
972 {
973 if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
974 {
0919e3f9
AL
975 if (Map[I].Handler(CmdL) == false && _error->PendingError() == false)
976 _error->Error("Handler silently failed");
0a8e3465
AL
977 break;
978 }
979 }
980
981 // No matching name
982 if (Map[I].Match == 0)
983 _error->Error("Invalid operation %s", CmdL.FileList[0]);
984
985 // Print any errors or warnings found during parsing
986 if (_error->empty() == false)
987 {
988 bool Errors = _error->PendingError();
989 _error->DumpErrors();
990 if (Errors == true)
991 cout << "Returning 100." << endl;
992 return Errors == true?100:0;
993 }
994
995 return 0;
996}