]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
cc73339fd9dbae2475dd5bde5db01bea27a3b94a
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.10 1998/11/13 07:09:02 jgg Exp $
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>
35 #include <apt-pkg/acquire-item.h>
36 #include <apt-pkg/dpkgpm.h>
37 #include <strutl.h>
38
39 #include <config.h>
40
41 #include "acqprogress.h"
42
43 #include <fstream.h>
44 #include <termios.h>
45 #include <sys/ioctl.h>
46 #include <signal.h>
47 /*}}}*/
48
49 ostream c0out;
50 ostream c1out;
51 ostream c2out;
52 ofstream devnull("/dev/null");
53 unsigned int ScreenWidth = 80;
54
55 // YnPrompt - Yes No Prompt. /*{{{*/
56 // ---------------------------------------------------------------------
57 /* Returns true on a Yes.*/
58 bool 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 /*}}}*/
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. */
80 void 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. */
110 void 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 {
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)
125 {
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)
156 {
157 out << " but ";
158 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
159 if (Ver.end() == false)
160 out << Ver.VerStr() << " is installed";
161 else
162 {
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 }
170 else
171 out << "it is not installed";
172 }
173 }
174
175 out << endl;
176 }
177 }
178 }
179 /*}}}*/
180 // ShowNew - Show packages to newly install /*{{{*/
181 // ---------------------------------------------------------------------
182 /* */
183 void 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 /* */
198 void 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 /* */
213 void 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 /* */
232 void 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 /* */
250 void 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! */
269 void ShowEssential(ostream &out,pkgDepCache &Dep)
270 {
271 pkgCache::PkgIterator I = Dep.PkgBegin();
272 string List;
273 bool *Added = new bool[Dep.HeaderP->PackageCount];
274 for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
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 /* */
319 void 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 /* */
345 class 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. */
371 bool 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
389 File = new FileFd(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
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 }
426 if (pkgMinimizeUpgrade(*Cache) == false)
427 return _error->Error("Unable to minimize the upgrade set");
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 */
447 bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
448 {
449 // Show all the various warning indicators
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;
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
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)
517 {
518
519 if (_config->FindI("quiet",0) < 2 ||
520 _config->FindB("APT::Get::Assume-Yes",false) == false)
521 c2out << "Do you want to continue? [Y/n] " << flush;
522 if (YnPrompt() == false)
523 exit(1);
524 }
525
526 // Run it
527 if (Fetcher.Run() == false)
528 return false;
529
530 return true;
531 }
532 /*}}}*/
533
534 // DoUpdate - Update the package lists /*{{{*/
535 // ---------------------------------------------------------------------
536 /* */
537 bool DoUpdate(CommandLine &)
538 {
539 // Get the source list
540 pkgSourceList List;
541 if (List.ReadMainList() == false)
542 return false;
543
544 // Create the download object
545 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
546 pkgAcquire Fetcher(&Stat);
547
548 // Populate it with the source selection
549 pkgSourceList::const_iterator I;
550 for (I = List.begin(); I != List.end(); I++)
551 {
552 new pkgAcqIndex(&Fetcher,I);
553 if (_error->PendingError() == true)
554 return false;
555 }
556
557 // Run it
558 if (Fetcher.Run() == false)
559 return false;
560
561 // Clean out any old list files
562 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
563 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
564 return false;
565
566 // Prepare the cache.
567 CacheFile Cache;
568 if (Cache.Open() == false)
569 return false;
570
571 return true;
572 }
573 /*}}}*/
574 // DoUpgrade - Upgrade all packages /*{{{*/
575 // ---------------------------------------------------------------------
576 /* Upgrade all packages without installing new packages or erasing old
577 packages */
578 bool DoUpgrade(CommandLine &CmdL)
579 {
580 CacheFile Cache;
581 if (Cache.Open() == false)
582 return false;
583
584 // Do the upgrade
585 if (pkgAllUpgrade(Cache) == false)
586 {
587 ShowBroken(c1out,Cache);
588 return _error->Error("Internal Error, AllUpgrade broke stuff");
589 }
590
591 return InstallPackages(Cache,true);
592 }
593 /*}}}*/
594 // DoInstall - Install packages from the command line /*{{{*/
595 // ---------------------------------------------------------------------
596 /* Install named packages */
597 bool DoInstall(CommandLine &CmdL)
598 {
599 CacheFile Cache;
600 if (Cache.Open() == false)
601 return false;
602
603 unsigned int ExpectedInst = 0;
604 unsigned int Packages = 0;
605 pkgProblemResolver Fix(Cache);
606
607 bool DefRemove = false;
608 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
609 DefRemove = true;
610
611 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
612 {
613 // Duplicate the string
614 unsigned int Length = strlen(*I);
615 char S[300];
616 if (Length >= sizeof(S))
617 continue;
618 strcpy(S,*I);
619
620 // See if we are removing the package
621 bool Remove = DefRemove;
622 if (S[Length - 1] == '-')
623 {
624 Remove = true;
625 S[--Length] = 0;
626 }
627 if (S[Length - 1] == '+')
628 {
629 Remove = false;
630 S[--Length] = 0;
631 }
632
633 // Locate the package
634 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
635 Packages++;
636 if (Pkg.end() == true)
637 return _error->Error("Couldn't find package %s",S);
638
639 // Check if there is something new to install
640 pkgDepCache::StateCache &State = (*Cache)[Pkg];
641 if (State.CandidateVer == 0)
642 {
643 if (Pkg->ProvidesList != 0)
644 {
645 c1out << "Package " << S << " is a virtual package provided by:" << endl;
646
647 pkgCache::PrvIterator I = Pkg.ProvidesList();
648 for (; I.end() == false; I++)
649 {
650 pkgCache::PkgIterator Pkg = I.OwnerPkg();
651
652 if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
653 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
654
655 if ((*Cache)[Pkg].InstVerIter(*Cache) == I.OwnerVer())
656 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
657 " [Installed]"<< endl;
658 }
659 c1out << "You should explicly select one to install." << endl;
660 }
661 else
662 {
663 c1out << "Package " << S << " has no available version, but exists in the database." << endl;
664 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
665 c1out << "never uploaded, or that it is an obsolete package." << endl;
666 }
667
668 return _error->Error("Package %s has no installation candidate",S);
669 }
670
671 Fix.Protect(Pkg);
672 if (Remove == true)
673 {
674 Fix.Remove(Pkg);
675 Cache->MarkDelete(Pkg);
676 continue;
677 }
678
679 // Install it
680 Cache->MarkInstall(Pkg,false);
681 if (State.Install() == false)
682 c1out << "Sorry, " << S << " is already the newest version" << endl;
683 else
684 ExpectedInst++;
685
686 // Install it with autoinstalling enabled.
687 if (State.InstBroken() == true)
688 Cache->MarkInstall(Pkg,true);
689 }
690
691 // Call the scored problem resolver
692 Fix.InstallProtect();
693 if (Fix.Resolve(true) == false)
694 _error->Discard();
695
696 // Now we check the state of the packages,
697 if (Cache->BrokenCount() != 0)
698 {
699 c1out << "Some packages could not be installed. This may mean that you have" << endl;
700 c1out << "requested an impossible situation or if you are using the unstable" << endl;
701 c1out << "distribution that some required packages have not yet been created" << endl;
702 c1out << "or been moved out of Incoming." << endl;
703 if (Packages == 1)
704 {
705 c1out << endl;
706 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
707 c1out << "the package is simply not installable and a bug report against" << endl;
708 c1out << "that package should be filed." << endl;
709 }
710
711 c1out << "The following information may help to resolve the situation:" << endl;
712 c1out << endl;
713 ShowBroken(c1out,Cache);
714 return _error->Error("Sorry, broken packages");
715 }
716
717 /* Print out a list of packages that are going to be installed extra
718 to what the user asked */
719 if (Cache->InstCount() != ExpectedInst)
720 {
721 string List;
722 pkgCache::PkgIterator I = Cache->PkgBegin();
723 for (;I.end() != true; I++)
724 {
725 if ((*Cache)[I].Install() == false)
726 continue;
727
728 const char **J;
729 for (J = CmdL.FileList + 1; *J != 0; J++)
730 if (strcmp(*J,I.Name()) == 0)
731 break;
732
733 if (*J == 0)
734 List += string(I.Name()) + " ";
735 }
736
737 ShowList(c1out,"The following extra packages will be installed:",List);
738 }
739
740 // See if we need to prompt
741 if (Cache->InstCount() != ExpectedInst || Cache->DelCount() != 0)
742 return InstallPackages(Cache,false,true);
743 return InstallPackages(Cache,false);
744 }
745 /*}}}*/
746 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
747 // ---------------------------------------------------------------------
748 /* Intelligent upgrader that will install and remove packages at will */
749 bool DoDistUpgrade(CommandLine &CmdL)
750 {
751 CacheFile Cache;
752 if (Cache.Open() == false)
753 return false;
754
755 c0out << "Calculating Upgrade... " << flush;
756 if (pkgDistUpgrade(*Cache) == false)
757 {
758 c0out << "Failed" << endl;
759 ShowBroken(c1out,Cache);
760 return false;
761 }
762
763 c0out << "Done" << endl;
764
765 return InstallPackages(Cache,true);
766 }
767 /*}}}*/
768 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
769 // ---------------------------------------------------------------------
770 /* Follows dselect's selections */
771 bool DoDSelectUpgrade(CommandLine &CmdL)
772 {
773 CacheFile Cache;
774 if (Cache.Open() == false)
775 return false;
776
777 // Install everything with the install flag set
778 pkgCache::PkgIterator I = Cache->PkgBegin();
779 for (;I.end() != true; I++)
780 {
781 /* Install the package only if it is a new install, the autoupgrader
782 will deal with the rest */
783 if (I->SelectedState == pkgCache::State::Install)
784 Cache->MarkInstall(I,false);
785 }
786
787 /* Now install their deps too, if we do this above then order of
788 the status file is significant for | groups */
789 for (I = Cache->PkgBegin();I.end() != true; I++)
790 {
791 /* Install the package only if it is a new install, the autoupgrader
792 will deal with the rest */
793 if (I->SelectedState == pkgCache::State::Install)
794 Cache->MarkInstall(I);
795 }
796
797 // Apply erasures now, they override everything else.
798 for (I = Cache->PkgBegin();I.end() != true; I++)
799 {
800 // Remove packages
801 if (I->SelectedState == pkgCache::State::DeInstall ||
802 I->SelectedState == pkgCache::State::Purge)
803 Cache->MarkDelete(I);
804 }
805
806 /* Use updates smart upgrade to do the rest, it will automatically
807 ignore held items */
808 if (pkgAllUpgrade(Cache) == false)
809 {
810 ShowBroken(c1out,Cache);
811 return _error->Error("Internal Error, AllUpgrade broke stuff");
812 }
813
814 return InstallPackages(Cache,false);
815 }
816 /*}}}*/
817 // DoClean - Remove download archives /*{{{*/
818 // ---------------------------------------------------------------------
819 /* */
820 bool DoClean(CommandLine &CmdL)
821 {
822 return true;
823 }
824 /*}}}*/
825 // DoCheck - Perform the check operation /*{{{*/
826 // ---------------------------------------------------------------------
827 /* Opening automatically checks the system, this command is mostly used
828 for debugging */
829 bool DoCheck(CommandLine &CmdL)
830 {
831 CacheFile Cache;
832 Cache.Open();
833
834 return true;
835 }
836 /*}}}*/
837
838 // ShowHelp - Show a help screen /*{{{*/
839 // ---------------------------------------------------------------------
840 /* */
841 int ShowHelp()
842 {
843 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
844 " compiled on " << __DATE__ << " " << __TIME__ << endl;
845
846 cout << "Usage: apt-get [options] command" << endl;
847 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
848 cout << endl;
849 cout << "apt-get is a simple command line interface for downloading and" << endl;
850 cout << "installing packages. The most frequently used commands are update" << endl;
851 cout << "and install." << endl;
852 cout << endl;
853 cout << "Commands:" << endl;
854 cout << " update - Retrieve new lists of packages" << endl;
855 cout << " upgrade - Perform an upgrade" << endl;
856 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
857 cout << " remove - Remove packages" << endl;
858 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
859 cout << " dselect-upgrade - Follow dselect selections" << endl;
860 cout << " clean - Erase downloaded archive files" << endl;
861 cout << " check - Verify that there are no broken dependencies" << endl;
862 cout << endl;
863 cout << "Options:" << endl;
864 cout << " -h This help text." << endl;
865 cout << " -q Loggable output - no progress indicator" << endl;
866 cout << " -qq No output except for errors" << endl;
867 cout << " -d Download only - do NOT install or unpack archives" << endl;
868 cout << " -s No-act. Perform ordering simulation" << endl;
869 cout << " -y Assume Yes to all queries and do not prompt" << endl;
870 cout << " -f Attempt to continue if the integrity check fails" << endl;
871 cout << " -m Attempt to continue if archives are unlocatable" << endl;
872 cout << " -u Show a list of upgraded packages as well" << endl;
873 cout << " -c=? Read this configuration file" << endl;
874 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
875 cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
876 cout << "pages for more information." << endl;
877 return 100;
878 }
879 /*}}}*/
880 // GetInitialize - Initialize things for apt-get /*{{{*/
881 // ---------------------------------------------------------------------
882 /* */
883 void GetInitialize()
884 {
885 _config->Set("quiet",0);
886 _config->Set("help",false);
887 _config->Set("APT::Get::Download-Only",false);
888 _config->Set("APT::Get::Simulate",false);
889 _config->Set("APT::Get::Assume-Yes",false);
890 _config->Set("APT::Get::Fix-Broken",false);
891 }
892 /*}}}*/
893 // SigWinch - Window size change signal handler /*{{{*/
894 // ---------------------------------------------------------------------
895 /* */
896 void SigWinch(int)
897 {
898 // Riped from GNU ls
899 #ifdef TIOCGWINSZ
900 struct winsize ws;
901
902 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
903 ScreenWidth = ws.ws_col - 1;
904 #endif
905 }
906 /*}}}*/
907
908 int main(int argc,const char *argv[])
909 {
910 CommandLine::Args Args[] = {
911 {'h',"help","help",0},
912 {'q',"quiet","quiet",CommandLine::IntLevel},
913 {'q',"silent","quiet",CommandLine::IntLevel},
914 {'d',"download-only","APT::Get::Download-Only",0},
915 {'s',"simulate","APT::Get::Simulate",0},
916 {'s',"just-print","APT::Get::Simulate",0},
917 {'s',"recon","APT::Get::Simulate",0},
918 {'s',"no-act","APT::Get::Simulate",0},
919 {'y',"yes","APT::Get::Assume-Yes",0},
920 {'y',"assume-yes","APT::Get::Assume-Yes",0},
921 {'f',"fix-broken","APT::Get::Fix-Broken",0},
922 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
923 {'m',"ignore-missing","APT::Get::Fix-Broken",0},
924 {0,"ignore-hold","APT::Ingore-Hold",0},
925 {'c',"config-file",0,CommandLine::ConfigFile},
926 {'o',"option",0,CommandLine::ArbItem},
927 {0,0,0,0}};
928
929 // Parse the command line and initialize the package library
930 CommandLine CmdL(Args,_config);
931 if (pkgInitialize(*_config) == false ||
932 CmdL.Parse(argc,argv) == false)
933 {
934 _error->DumpErrors();
935 return 100;
936 }
937
938 // See if the help should be shown
939 if (_config->FindB("help") == true ||
940 CmdL.FileSize() == 0)
941 return ShowHelp();
942
943 // Setup the output streams
944 c0out.rdbuf(cout.rdbuf());
945 c1out.rdbuf(cout.rdbuf());
946 c2out.rdbuf(cout.rdbuf());
947 if (_config->FindI("quiet",0) > 0)
948 c0out.rdbuf(devnull.rdbuf());
949 if (_config->FindI("quiet",0) > 1)
950 c1out.rdbuf(devnull.rdbuf());
951
952 // Setup the signals
953 signal(SIGPIPE,SIG_IGN);
954 signal(SIGWINCH,SigWinch);
955 SigWinch(0);
956
957 // Match the operation
958 struct
959 {
960 const char *Match;
961 bool (*Handler)(CommandLine &);
962 } Map[] = {{"update",&DoUpdate},
963 {"upgrade",&DoUpgrade},
964 {"install",&DoInstall},
965 {"remove",&DoInstall},
966 {"dist-upgrade",&DoDistUpgrade},
967 {"dselect-upgrade",&DoDSelectUpgrade},
968 {"clean",&DoClean},
969 {"check",&DoCheck},
970 {0,0}};
971 int I;
972 for (I = 0; Map[I].Match != 0; I++)
973 {
974 if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
975 {
976 if (Map[I].Handler(CmdL) == false && _error->PendingError() == false)
977 _error->Error("Handler silently failed");
978 break;
979 }
980 }
981
982 // No matching name
983 if (Map[I].Match == 0)
984 _error->Error("Invalid operation %s", CmdL.FileList[0]);
985
986 // Print any errors or warnings found during parsing
987 if (_error->empty() == false)
988 {
989 bool Errors = _error->PendingError();
990 _error->DumpErrors();
991 if (Errors == true)
992 cout << "Returning 100." << endl;
993 return Errors == true?100:0;
994 }
995
996 return 0;
997 }