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