- we dont have dselect so we dont need dselect-upgrade either
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: c++; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: apt-get.cc,v 1.144 2003/10/29 17:56:31 mdz 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/algorithms.h>
34 #include <apt-pkg/acquire-item.h>
35 #include <apt-pkg/strutl.h>
36 #include <apt-pkg/clean.h>
37 #include <apt-pkg/srcrecords.h>
38 #include <apt-pkg/version.h>
39 #include <apt-pkg/cachefile.h>
40 #include <apt-pkg/sptr.h>
41 #include <apt-pkg/versionmatch.h>
42     
43 #include <config.h>
44 #include <apti18n.h>
45
46 #include "acqprogress.h"
47 #include "cmdline.h"
48
49 // CNC:2003-02-14 - apti18n.h includes libintl.h which includes locale.h,
50 //                  as reported by Radu Greab.
51 //#include <locale.h>
52 #include <langinfo.h>
53 #include <fstream>
54 #include <termios.h>
55 #include <sys/ioctl.h>
56 #include <sys/stat.h>
57 #include <sys/statvfs.h>
58 #include <signal.h>
59 #include <unistd.h>
60 #include <stdio.h>
61 #include <errno.h>
62 #include <regex.h>
63 #include <sys/wait.h>
64
65 // CNC:2003-03-18
66 #include <apt-pkg/luaiface.h>
67     
68                                                                         /*}}}*/
69
70 using namespace std;
71
72 // class CacheFile - Cover class for some dependency cache functions    /*{{{*/
73 // ---------------------------------------------------------------------
74 /* */
75 class CacheFile : public cmdCacheFile
76 {
77    public:
78    bool CheckDeps(bool AllowBroken = false);
79    bool BuildCaches(bool WithLock = true)
80    {
81       OpTextProgress Prog(*_config);
82       if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
83          return false;
84       return true;
85    }
86    bool Open(bool WithLock = true) 
87    {
88       OpTextProgress Prog(*_config);
89       if (pkgCacheFile::Open(Prog,WithLock) == false)
90          return false;
91       Sort();
92       
93       return true;
94    };
95    bool OpenForInstall()
96    {
97       // CNC:2004-03-07 - dont take lock if in download mode
98       if (_config->FindB("APT::Get::Print-URIs") == true ||
99           _config->FindB("APT::Get::Download-only") == true)
100          return Open(false);
101       else
102          return Open(true);
103    }
104    CacheFile() : cmdCacheFile() {};
105 };
106                                                                         /*}}}*/
107
108 // CNC:2003-03-19
109 #ifdef WITH_LUA
110 class AptGetLuaCache : public LuaCacheControl
111 {
112    public:
113
114    CacheFile *Cache;
115
116    virtual pkgDepCache *Open(bool Write)
117    {
118       if (Cache == NULL) {
119          Cache = new CacheFile();
120          if (Cache->Open(Write) == false)
121             return NULL;
122          if (Cache->CheckDeps() == false)
123             return NULL;
124       }
125       return *Cache;
126    }
127
128    virtual void Close()
129    {
130       if (Cache) {
131          delete Cache;
132          Cache = NULL;
133       }
134    };
135
136    AptGetLuaCache() : Cache(0) {};
137 };
138 #endif
139                                                                         /*}}}*/
140 // CNC:2003-03-06
141 // CheckOnly - Check if the cache has any changes to be applied         /*{{{*/
142 // ---------------------------------------------------------------------
143 /* Returns true if CheckOnly is active. */
144 bool CheckOnly(CacheFile &Cache)
145 {
146    if (_config->FindB("APT::Get::Check-Only", false) == false)
147       return false;
148    if (Cache->InstCount() != 0 || Cache->DelCount() != 0) {
149       if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
150          ShowUpgraded(c1out,Cache);
151       ShowDel(c1out,Cache);
152       ShowNew(c1out,Cache);
153       //ShowKept(c1out,Cache);
154       ShowHold(c1out,Cache);
155       ShowDowngraded(c1out,Cache);
156       ShowEssential(c1out,Cache);
157       Stats(c1out,Cache);
158       _error->Error(_("There are changes to be made"));
159    }
160
161    return true;
162 }
163                                                                         /*}}}*/
164
165
166 // CacheFile::CheckDeps - Open the cache file                           /*{{{*/
167 // ---------------------------------------------------------------------
168 /* This routine generates the caches and then opens the dependency cache
169    and verifies that the system is OK. */
170 bool CacheFile::CheckDeps(bool AllowBroken)
171 {
172    if (_error->PendingError() == true)
173       return false;
174
175 // CNC:2003-03-19 - Might be changed by some extension.
176 #if 0
177    // Check that the system is OK
178    if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
179       return _error->Error("Internal Error, non-zero counts");
180 #endif
181    
182    // Apply corrections for half-installed packages
183    if (pkgApplyStatus(*DCache) == false)
184       return false;
185    
186    // Nothing is broken
187    if (DCache->BrokenCount() == 0 || AllowBroken == true)
188       return true;
189
190    // Attempt to fix broken things
191    if (_config->FindB("APT::Get::Fix-Broken",false) == true)
192    {
193       c1out << _("Correcting dependencies...") << flush;
194       if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
195       {
196          c1out << _(" failed.") << endl;
197          ShowBroken(c1out,*this,true);
198
199          return _error->Error(_("Unable to correct dependencies"));
200       }
201       if (pkgMinimizeUpgrade(*DCache) == false)
202          return _error->Error(_("Unable to minimize the upgrade set"));
203       
204       c1out << _(" Done") << endl;
205    }
206    else
207    {
208       c1out << _("You might want to run `apt-get --fix-broken install' to correct these.") << endl;
209       ShowBroken(c1out,*this,true);
210
211       return _error->Error(_("Unmet dependencies. Try using --fix-broken."));
212    }
213       
214    return true;
215 }
216                                                                         /*}}}*/
217 bool DoClean(CommandLine &CmdL);
218 bool DoAutoClean(CommandLine &CmdL);
219
220 // InstallPackages - Actually download and install the packages         /*{{{*/
221 // ---------------------------------------------------------------------
222 /* This displays the informative messages describing what is going to 
223    happen and then calls the download routines */
224 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
225                      bool Saftey = true)
226 {
227    if (_config->FindB("APT::Get::Purge",false) == true)
228    {
229       pkgCache::PkgIterator I = Cache->PkgBegin();
230       for (; I.end() == false; I++)
231       {
232          if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
233             Cache->MarkDelete(I,true);
234       }
235    }
236    
237    bool Fail = false;
238    bool Essential = false;
239    
240    // Show all the various warning indicators
241    // CNC:2002-03-06 - Change Show-Upgraded default to true, and move upwards.
242    if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
243       ShowUpgraded(c1out,Cache);
244    ShowDel(c1out,Cache);
245    ShowNew(c1out,Cache);
246    if (ShwKept == true)
247       ShowKept(c1out,Cache);
248    Fail |= !ShowHold(c1out,Cache);
249    Fail |= !ShowDowngraded(c1out,Cache);
250    if (_config->FindB("APT::Get::Download-Only",false) == false)
251         Essential = !ShowEssential(c1out,Cache);
252    Fail |= Essential;
253    Stats(c1out,Cache);
254    
255    // Sanity check
256    if (Cache->BrokenCount() != 0)
257    {
258       ShowBroken(c1out,Cache,false);
259       return _error->Error("Internal Error, InstallPackages was called with broken packages!");
260    }
261
262    if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
263        Cache->BadCount() == 0)
264       return true;
265
266    // No remove flag
267    if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
268       return _error->Error(_("Packages need to be removed but Remove is disabled."));
269        
270    // Run the simulator ..
271    if (_config->FindB("APT::Get::Simulate") == true)
272    {
273       pkgSimulate PM(Cache);
274       pkgPackageManager::OrderResult Res = PM.DoInstall();
275       if (Res == pkgPackageManager::Failed)
276          return false;
277       if (Res != pkgPackageManager::Completed)
278          return _error->Error("Internal Error, Ordering didn't finish");
279       return true;
280    }
281    
282    // Create the text record parser
283    pkgRecords Recs(Cache);
284    if (_error->PendingError() == true)
285       return false;
286    
287    // Lock the archive directory
288    FileFd Lock;
289    if (_config->FindB("Debug::NoLocking",false) == false &&
290        _config->FindB("APT::Get::Print-URIs") == false)
291    {
292       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
293       if (_error->PendingError() == true)
294          return _error->Error(_("Unable to lock the download directory"));
295    }
296    
297    // Create the download object
298    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
299    pkgAcquire Fetcher(&Stat);
300
301    // Read the source list
302    pkgSourceList List;
303    if (List.ReadMainList() == false)
304       return _error->Error(_("The list of sources could not be read."));
305    
306    // Create the package manager and prepare to download
307    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
308    if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
309        _error->PendingError() == true)
310       return false;
311
312    // Display statistics
313    double FetchBytes = Fetcher.FetchNeeded();
314    double FetchPBytes = Fetcher.PartialPresent();
315    double DebBytes = Fetcher.TotalNeeded();
316    if (DebBytes != Cache->DebSize())
317    {
318       c0out << DebBytes << ',' << Cache->DebSize() << endl;
319       c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
320    }
321    
322    // Number of bytes
323    if (DebBytes != FetchBytes)
324       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
325                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
326    else
327       ioprintf(c1out,_("Need to get %sB of archives.\n"),
328                SizeToStr(DebBytes).c_str());
329
330    // Size delta
331    if (Cache->UsrSize() >= 0)
332       ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
333                SizeToStr(Cache->UsrSize()).c_str());
334    else
335       ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
336                SizeToStr(-1*Cache->UsrSize()).c_str());
337
338    if (_error->PendingError() == true)
339       return false;
340
341    /* Check for enough free space, but only if we are actually going to
342       download */
343    if (_config->FindB("APT::Get::Print-URIs") == false &&
344        _config->FindB("APT::Get::Download",true) == true)
345    {
346       struct statvfs Buf;
347       string OutputDir = _config->FindDir("Dir::Cache::Archives");
348       if (statvfs(OutputDir.c_str(),&Buf) != 0)
349          return _error->Errno("statvfs","Couldn't determine free space in %s",
350                               OutputDir.c_str());
351       // CNC:2002-07-11
352       if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
353          return _error->Error(_("You don't have enough free space in %s."),
354                               OutputDir.c_str());
355    }
356    
357    // Fail safe check
358    if (_config->FindI("quiet",0) >= 2 ||
359        _config->FindB("APT::Get::Assume-Yes",false) == true)
360    {
361       if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
362          return _error->Error(_("There are problems and -y was used without --force-yes"));
363    }         
364
365    if (Essential == true && Saftey == true)
366    {
367       if (_config->FindB("APT::Get::Trivial-Only",false) == true)
368          return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
369       
370       const char *Prompt = _("Yes, do as I say!");
371       ioprintf(c2out,
372                _("You are about to do something potentially harmful\n"
373                  "To continue type in the phrase '%s'\n"
374                  " ?] "),Prompt);
375       c2out << flush;
376       if (AnalPrompt(Prompt) == false)
377       {
378          c2out << _("Abort.") << endl;
379          exit(1);
380       }     
381    }
382    else
383    {      
384       // Prompt to continue
385       if (Ask == true || Fail == true)
386       {            
387          if (_config->FindB("APT::Get::Trivial-Only",false) == true)
388             return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
389          
390          if (_config->FindI("quiet",0) < 2 &&
391              _config->FindB("APT::Get::Assume-Yes",false) == false)
392          {
393             c2out << _("Do you want to continue? [Y/n] ") << flush;
394          
395             if (YnPrompt() == false)
396             {
397                c2out << _("Abort.") << endl;
398                exit(1);
399             }     
400          }       
401       }      
402    }
403    
404    // Just print out the uris an exit if the --print-uris flag was used
405    if (_config->FindB("APT::Get::Print-URIs") == true)
406    {
407       pkgAcquire::UriIterator I = Fetcher.UriBegin();
408       for (; I != Fetcher.UriEnd(); I++)
409          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
410                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
411       return true;
412    }
413
414 // CNC:2004-03-07 - lock not taken in download mode in the first place
415 #if 0
416    /* Unlock the dpkg lock if we are not going to be doing an install
417       after. */
418    if (_config->FindB("APT::Get::Download-Only",false) == true)
419       _system->UnLock();
420 #endif
421
422    // CNC:2003-02-24
423    bool Ret = true;
424    
425    // Run it
426    while (1)
427    {
428       bool Transient = false;
429       if (_config->FindB("APT::Get::Download",true) == false)
430       {
431          for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
432          {
433             if ((*I)->Local == true)
434             {
435                I++;
436                continue;
437             }
438
439             // Close the item and check if it was found in cache
440             (*I)->Finished();
441             if ((*I)->Complete == false)
442                Transient = true;
443             
444             // Clear it out of the fetch list
445             delete *I;
446             I = Fetcher.ItemsBegin();
447          }       
448       }
449       
450       if (Fetcher.Run() == pkgAcquire::Failed)
451          return false;
452
453       // CNC:2003-02-24
454       _error->PopState();
455       
456       // Print out errors
457       bool Failed = false;
458       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
459       {
460          if ((*I)->Status == pkgAcquire::Item::StatDone &&
461              (*I)->Complete == true)
462             continue;
463          
464          if ((*I)->Status == pkgAcquire::Item::StatIdle)
465          {
466             Transient = true;
467             // Failed = true;
468             continue;
469          }
470
471          fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
472                  (*I)->ErrorText.c_str());
473          Failed = true;
474       }
475
476       /* If we are in no download mode and missing files and there were
477          'failures' then the user must specify -m. Furthermore, there 
478          is no such thing as a transient error in no-download mode! */
479       if (Transient == true &&
480           _config->FindB("APT::Get::Download",true) == false)
481       {
482          Transient = false;
483          Failed = true;
484       }
485       
486       if (_config->FindB("APT::Get::Download-Only",false) == true)
487       {
488          if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
489             return _error->Error(_("Some files failed to download"));
490          c1out << _("Download complete and in download only mode") << endl;
491          return true;
492       }
493       
494       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
495       {
496          return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
497       }
498       
499       if (Transient == true && Failed == true)
500          return _error->Error(_("--fix-missing and media swapping is not currently supported"));
501       
502       // Try to deal with missing package files
503       if (Failed == true && PM->FixMissing() == false)
504       {
505          cerr << _("Unable to correct missing packages.") << endl;
506          return _error->Error(_("Aborting Install."));
507       }
508
509       // CNC:2002-10-18
510       if (Transient == false || _config->FindB("Acquire::CDROM::Copy-All", false) == false) {
511          if (Transient == true) {
512             // We must do that in a system independent way. */
513             _config->Set("RPM::Install-Options::", "--nodeps");
514          }
515          _system->UnLock();
516          pkgPackageManager::OrderResult Res = PM->DoInstall();
517          if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
518          {
519             if (Transient == false)
520                return false;
521             Ret = false;
522          }
523
524          // CNC:2002-07-06
525          if (Res == pkgPackageManager::Completed)
526          {
527             CommandLine *CmdL = NULL; // Watch out! If used will blow up!
528             if (_config->FindB("APT::Post-Install::Clean",false) == true) 
529                Ret &= DoClean(*CmdL);
530             else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) 
531                Ret &= DoAutoClean(*CmdL);
532             return Ret;
533          }
534          
535          _system->Lock();
536       }
537
538       // CNC:2003-02-24
539       _error->PushState();
540       
541       // Reload the fetcher object and loop again for media swapping
542       Fetcher.Shutdown();
543       if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
544          return false;
545    }   
546 }
547                                                                         /*}}}*/
548 // CNC:2003-12-02
549 // DownloadPackages - Fetch packages                                    /*{{{*/
550 // ---------------------------------------------------------------------
551 /* Fetch packages */
552 bool DownloadPackages(vector<string> &URLLst)
553 {
554
555    // Create the download object
556    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
557    pkgAcquire Fetcher(&Stat);
558
559    // Load the requestd sources into the fetcher
560    vector<string>::const_iterator I = URLLst.begin();
561    for (; I != URLLst.end(); I++)
562       new pkgAcqFile(&Fetcher,*I,"",0,*I,flNotDir(*I));
563    
564    // Run it
565    if (Fetcher.Run() == pkgAcquire::Failed)
566       return false;
567
568    // Print error messages
569    bool Failed = false;
570    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
571    {
572       if ((*I)->Status == pkgAcquire::Item::StatDone &&
573           (*I)->Complete == true)
574          continue;
575       
576       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
577               (*I)->ErrorText.c_str());
578       Failed = true;
579    }
580    if (Failed == true)
581       return _error->Error(_("Failed to fetch some archives."));
582
583    return true;
584 }
585                                                                         /*}}}*/
586 // TryToInstall - Try to install a single package                       /*{{{*/
587 // ---------------------------------------------------------------------
588 /* This used to be inlined in DoInstall, but with the advent of regex package
589    name matching it was split out.. */
590 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
591                   pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
592                   unsigned int &ExpectedInst,bool AllowFail = true)
593 {
594    // CNC:2004-03-03 - Improved virtual package handling.
595    if (Pkg->VersionList == 0 && Pkg->ProvidesList != 0)
596    {
597       vector<pkgCache::Package *> GoodSolutions;
598       for (pkgCache::PrvIterator Prv = Pkg.ProvidesList();
599            Prv.end() == false; Prv++)
600       {
601          pkgCache::PkgIterator PrvPkg = Prv.OwnerPkg();
602          // Check if it's a different version of a package already
603          // considered as a good solution.
604          bool AlreadySeen = false;
605          for (size_t i = 0; i != GoodSolutions.size(); i++)
606          {
607             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
608             if (PrvPkg == GoodPkg)
609             {
610                AlreadySeen = true;
611                break;
612             }
613          }
614          if (AlreadySeen)
615             continue;
616          // Is the current version the provides owner?
617          if (PrvPkg.CurrentVer() == Prv.OwnerVer())
618          {
619             // Already installed packages are good solutions, since
620             // the user might try to install something he already has
621             // without being aware.
622             GoodSolutions.push_back(PrvPkg);
623             continue;
624          }
625          pkgCache::VerIterator PrvPkgCandVer =
626                                  Cache[PrvPkg].CandidateVerIter(Cache);
627          if (PrvPkgCandVer.end() == true)
628          {
629             // Packages without a candidate version are not good solutions.
630             continue;
631          }
632          // Is the provides pointing to the candidate version?
633          if (PrvPkgCandVer == Prv.OwnerVer())
634          {
635             // Yes, it is. This is a good solution.
636             GoodSolutions.push_back(PrvPkg);
637             continue;
638          }
639       }
640       vector<string> GoodSolutionNames;
641       for (size_t i = 0; i != GoodSolutions.size(); i++)
642       {
643          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
644          GoodSolutionNames.push_back(GoodPkg.Name());
645       }
646 #ifdef WITH_LUA
647       if (GoodSolutions.size() > 1)
648       {
649          vector<string> VS;
650          _lua->SetDepCache(&Cache);
651          _lua->SetDontFix();
652          _lua->SetGlobal("virtualname", Pkg.Name());
653          _lua->SetGlobal("packages", GoodSolutions);
654          _lua->SetGlobal("packagenames", GoodSolutionNames);
655          _lua->SetGlobal("selected");
656          _lua->RunScripts("Scripts::AptGet::Install::SelectPackage");
657          pkgCache::Package *selected = _lua->GetGlobalPkg("selected");
658          if (selected) {
659             GoodSolutions.clear();
660             GoodSolutions.push_back(selected);
661          }
662          else
663          {
664             vector<string> Tmp = _lua->GetGlobalStrList("packagenames");
665             if (Tmp.size() == GoodSolutions.size())
666                GoodSolutionNames = Tmp;
667          }
668          _lua->ResetGlobals();
669          _lua->ResetCaches();
670       }
671 #endif
672       if (GoodSolutions.size() == 1)
673       {
674          pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[0]);
675          ioprintf(c1out,_("Selecting %s for '%s'\n"),
676                   GoodPkg.Name(), Pkg.Name());
677          Pkg = GoodPkg;
678       }
679       else if (GoodSolutions.size() == 0)
680       {
681          _error->Error(_("Package %s is a virtual package with no "
682                          "good providers.\n"), Pkg.Name());
683          return false;
684       }
685       else
686       {
687          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
688                   Pkg.Name());
689          for (size_t i = 0; i != GoodSolutions.size(); i++)
690          {
691             pkgCache::PkgIterator GoodPkg(Cache, GoodSolutions[i]);
692             if (GoodPkg.CurrentVer().end() == false)
693                c1out << "  " << GoodSolutionNames[i]
694                      << " "  << Cache[GoodPkg].CandVersion
695                      << _(" [Installed]") << endl;
696             else
697                c1out << "  " << GoodSolutionNames[i]
698                      << " "  << Cache[GoodPkg].CandVersion << endl;
699          }
700          c1out << _("You should explicitly select one to install.") << endl;
701          _error->Error(_("Package %s is a virtual package with multiple "
702                          "good providers.\n"), Pkg.Name());
703          return false;
704       }
705    }
706    
707    // Handle the no-upgrade case
708    if (_config->FindB("APT::Get::upgrade",true) == false &&
709        Pkg->CurrentVer != 0)
710    {
711       if (AllowFail == true)
712          ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
713                   Pkg.Name());
714       return true;
715    }
716    
717    // Check if there is something at all to install
718    pkgDepCache::StateCache &State = Cache[Pkg];
719    if (Remove == true && Pkg->CurrentVer == 0)
720    {
721       Fix.Clear(Pkg);
722       Fix.Protect(Pkg);
723       Fix.Remove(Pkg);
724       
725       /* We want to continue searching for regex hits, so we return false here
726          otherwise this is not really an error. */
727       if (AllowFail == false)
728          return false;
729       
730       ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
731       return true;
732    }
733    
734    if (State.CandidateVer == 0 && Remove == false)
735    {
736       if (AllowFail == false)
737          return false;
738       
739 // CNC:2004-03-03 - Improved virtual package handling.
740 #if 0
741       if (Pkg->ProvidesList != 0)
742       {
743          ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
744                   Pkg.Name());
745          
746          pkgCache::PrvIterator I = Pkg.ProvidesList();
747          for (; I.end() == false; I++)
748          {
749             pkgCache::PkgIterator Pkg = I.OwnerPkg();
750             
751             if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
752             {
753                if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
754                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
755                   _(" [Installed]") << endl;
756                else
757                   c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
758             }      
759          }
760          c1out << _("You should explicitly select one to install.") << endl;
761       }
762       else
763 #endif
764       {
765          ioprintf(c1out,
766          _("Package %s has no available version, but exists in the database.\n"
767            "This typically means that the package was mentioned in a dependency and\n"
768            "never uploaded, has been obsoleted or is not available with the contents\n"
769            "of sources.list\n"),Pkg.Name());
770          
771          string List;
772          string VersionsList;
773          SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
774          memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
775          pkgCache::DepIterator Dep = Pkg.RevDependsList();
776          for (; Dep.end() == false; Dep++)
777          {
778             // CNC:2002-07-30
779             if (Dep->Type != pkgCache::Dep::Replaces &&
780                 Dep->Type != pkgCache::Dep::Obsoletes)
781                continue;
782             if (Seen[Dep.ParentPkg()->ID] == true)
783                continue;
784             Seen[Dep.ParentPkg()->ID] = true;
785             List += string(Dep.ParentPkg().Name()) + " ";
786         //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
787          }          
788          ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
789       }
790       
791       _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
792       return false;
793    }
794
795    Fix.Clear(Pkg);
796    Fix.Protect(Pkg);   
797    if (Remove == true)
798    {
799       Fix.Remove(Pkg);
800       Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
801       return true;
802    }
803    
804    // Install it
805    Cache.MarkInstall(Pkg,false);
806    if (State.Install() == false)
807    {
808       if (_config->FindB("APT::Get::ReInstall",false) == true)
809       {
810          if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
811             ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
812                      Pkg.Name());
813          else
814             Cache.SetReInstall(Pkg,true);
815       }      
816       else
817       {
818          if (AllowFail == true)
819             ioprintf(c1out,_("%s is already the newest version.\n"),
820                      Pkg.Name());
821       }      
822    }   
823    else
824       ExpectedInst++;
825    
826    // Install it with autoinstalling enabled.
827    if (State.InstBroken() == true && BrokenFix == false)
828       Cache.MarkInstall(Pkg,true);
829    return true;
830 }
831                                                                         /*}}}*/
832 // TryToChangeVer - Try to change a candidate version                   /*{{{*/
833 // ---------------------------------------------------------------------
834 // CNC:2003-11-11
835 bool TryToChangeVer(pkgCache::PkgIterator &Pkg,pkgDepCache &Cache,
836                     int VerOp,const char *VerTag,bool IsRel)
837 {
838    // CNC:2003-11-05
839    pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
840                                  pkgVersionMatch::Version),VerOp);
841    
842    pkgCache::VerIterator Ver = Match.Find(Pkg);
843                          
844    if (Ver.end() == true)
845    {
846       // CNC:2003-11-05
847       if (IsRel == true)
848          return _error->Error(_("Release %s'%s' for '%s' was not found"),
849                               op2str(VerOp),VerTag,Pkg.Name());
850       return _error->Error(_("Version %s'%s' for '%s' was not found"),
851                            op2str(VerOp),VerTag,Pkg.Name());
852    }
853    
854    if (strcmp(VerTag,Ver.VerStr()) != 0)
855    {
856       // CNC:2003-11-11
857       if (IsRel == true)
858          ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
859                   Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
860       else
861          ioprintf(c1out,_("Selected version %s for %s\n"),
862                   Ver.VerStr(),Pkg.Name());
863    }
864    
865    Cache.SetCandidateVersion(Ver);
866    // CNC:2003-11-11
867    Pkg = Ver.ParentPkg();
868    return true;
869 }
870                                                                         /*}}}*/
871
872 // DoUpdate - Update the package lists                                  /*{{{*/
873 // ---------------------------------------------------------------------
874 /* */
875
876 // CNC:2004-04-19
877 class UpdateLogCleaner : public pkgArchiveCleaner
878 {
879    protected:
880    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
881    {
882       c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
883       unlink(File);      
884    };
885    public:
886    virtual ~UpdateLogCleaner() {};
887 };
888
889 bool DoUpdate(CommandLine &CmdL)
890 {
891 // CNC:2003-03-27
892 #if 0
893    if (CmdL.FileSize() != 1)
894       return _error->Error(_("The update command takes no arguments"));
895
896    // Get the source list
897    pkgSourceList List;
898    if (List.ReadMainList() == false)
899       return false;
900 #else
901    bool Partial = false;
902    pkgSourceList List;
903
904    if (CmdL.FileSize() != 1)
905    {
906       List.ReadVendors();
907       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
908       {
909          string Repo = _config->FindDir("Dir::Etc::sourceparts") + *I;
910          if (FileExists(Repo) == false)
911             Repo += ".list";
912          if (FileExists(Repo) == true)
913          {
914             if (List.ReadAppend(Repo) == true)
915                Partial = true;
916             else
917                return _error->Error(_("Sources list %s could not be read"),Repo.c_str());
918          }
919          else
920             return _error->Error(_("Sources list %s doesn't exist"),Repo.c_str());
921       }
922    }
923    else if (List.ReadMainList() == false)
924       return false;
925 #endif
926
927    // Lock the list directory
928    FileFd Lock;
929    if (_config->FindB("Debug::NoLocking",false) == false)
930    {
931       Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
932       if (_error->PendingError() == true)
933          return _error->Error(_("Unable to lock the list directory"));
934    }
935    
936 // CNC:2003-03-19
937 #ifdef WITH_LUA
938    if (_lua->HasScripts("Scripts::AptGet::Update::Pre")) {
939       _lua->RunScripts("Scripts::AptGet::Update::Pre");
940       LuaCacheControl *LuaCache = _lua->GetCacheControl();
941       LuaCache->Close();
942    }
943 #endif
944    
945    // Create the download object
946    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
947    pkgAcquire Fetcher(&Stat);
948
949    // CNC:2002-07-03
950    bool Failed = false;
951    // Populate it with release file URIs
952    if (List.GetReleases(&Fetcher) == false)
953       return false;
954    if (_config->FindB("APT::Get::Print-URIs") == false)
955    {
956       Fetcher.Run();
957       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
958       {
959          if ((*I)->Status == pkgAcquire::Item::StatDone)
960             continue;
961          (*I)->Finished();
962          Failed = true;
963       }
964       if (Failed == true)
965          _error->Warning(_("Release files for some repositories could not be retrieved or authenticated. Such repositories are being ignored."));
966    }
967    
968    // Populate it with the source selection
969    if (List.GetIndexes(&Fetcher) == false)
970          return false;
971    
972    // Just print out the uris an exit if the --print-uris flag was used
973    if (_config->FindB("APT::Get::Print-URIs") == true)
974    {
975       pkgAcquire::UriIterator I = Fetcher.UriBegin();
976       for (; I != Fetcher.UriEnd(); I++)
977          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
978                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
979       return true;
980    }
981    
982    // Run it
983    if (Fetcher.Run() == pkgAcquire::Failed)
984       return false;
985
986    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
987    {
988       if ((*I)->Status == pkgAcquire::Item::StatDone)
989          continue;
990
991       (*I)->Finished();
992       
993       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
994               (*I)->ErrorText.c_str());
995       Failed = true;
996    }
997    
998    // Clean out any old list files if not in partial update
999    if (Partial == false && _config->FindB("APT::Get::List-Cleanup",true) == true)
1000    {
1001       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1002           Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1003          return false;
1004    }
1005    
1006 // CNC:2003-03-19
1007 #if 0
1008    // Prepare the cache.   
1009    CacheFile Cache;
1010    if (Cache.BuildCaches() == false)
1011       return false;
1012 #else
1013    // Prepare the cache.   
1014    CacheFile Cache;
1015    if (Cache.Open() == false)
1016       return false;
1017
1018 #ifdef WITH_LUA
1019    _lua->RunScripts("Scripts::AptGet::Update::Post");
1020 #endif
1021 #endif
1022
1023    // CNC:2004-04-19
1024    if (Failed == false && _config->FindB("APT::Get::Archive-Cleanup",true) == true)
1025    {
1026       UpdateLogCleaner Cleaner;
1027       Cleaner.Go(_config->FindDir("Dir::Cache::archives"), *Cache);
1028       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",
1029                  *Cache);
1030    }
1031    
1032    if (Failed == true)
1033       return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
1034    
1035    return true;
1036 }
1037                                                                         /*}}}*/
1038 // DoUpgrade - Upgrade all packages                                     /*{{{*/
1039 // ---------------------------------------------------------------------
1040 /* Upgrade all packages without installing new packages or erasing old
1041    packages */
1042 bool DoUpgrade(CommandLine &CmdL)
1043 {
1044    CacheFile Cache;
1045    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1046       return false;
1047
1048    // Do the upgrade
1049    if (pkgAllUpgrade(Cache) == false)
1050    {
1051       ShowBroken(c1out,Cache,false);
1052       return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
1053    }
1054
1055 // CNC:2003-03-19
1056 #ifdef WITH_LUA
1057    _lua->SetDepCache(Cache);
1058    _lua->RunScripts("Scripts::AptGet::Upgrade");
1059    _lua->ResetCaches();
1060 #endif
1061
1062    // CNC:2003-03-06
1063    if (CheckOnly(Cache) == true)
1064       return true;
1065    
1066    return InstallPackages(Cache,true);
1067 }
1068                                                                         /*}}}*/
1069 // DoInstall - Install packages from the command line                   /*{{{*/
1070 // ---------------------------------------------------------------------
1071 /* Install named packages */
1072 bool DoInstall(CommandLine &CmdL)
1073 {
1074    CacheFile Cache;
1075    if (Cache.OpenForInstall() == false || 
1076        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1077       return false;
1078    
1079    // Enter the special broken fixing mode if the user specified arguments
1080    bool BrokenFix = false;
1081    if (Cache->BrokenCount() != 0)
1082       BrokenFix = true;
1083    
1084    unsigned int ExpectedInst = 0;
1085    unsigned int Packages = 0;
1086    pkgProblemResolver Fix(Cache);
1087    
1088    bool DefRemove = false;
1089    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1090       DefRemove = true;
1091    // CNC:2004-03-22
1092    else if (strcasecmp(CmdL.FileList[0],"reinstall") == 0)
1093       _config->Set("APT::Get::ReInstall", true);
1094
1095    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1096    {
1097       // Duplicate the string
1098       size_t Length = strlen(*I);
1099       char S[300];
1100       if (Length >= sizeof(S))
1101          continue;
1102       strcpy(S,*I);
1103
1104       // CNC:2003-03-15
1105       char OrigS[300];
1106       strcpy(OrigS,S);
1107       
1108       // See if we are removing and special indicators..
1109       bool Remove = DefRemove;
1110       char *VerTag = 0;
1111       bool VerIsRel = false;
1112       // CNC:2003-11-05
1113       int VerOp = 0;
1114       while (Cache->FindPkg(S).end() == true)
1115       {
1116          // Handle an optional end tag indicating what to do
1117          if (Length >= 1 && S[Length - 1] == '-')
1118          {
1119             Remove = true;
1120             S[--Length] = 0;
1121             continue;
1122          }
1123          
1124          if (Length >= 1 && S[Length - 1] == '+')
1125          {
1126             Remove = false;
1127             S[--Length] = 0;
1128             continue;
1129          }
1130          
1131          // CNC:2003-11-05
1132          char *sep = strpbrk(S,"=><");
1133          if (sep)
1134          {
1135             char *p;
1136             int eq = 0, gt = 0, lt = 0;
1137
1138             VerIsRel = false;
1139             for (p = sep; *p && strchr("=><",*p); ++p)
1140                switch (*p)
1141                {
1142                   case '=': eq = 1; break;
1143                   case '>': gt = 1; break;
1144                   case '<': lt = 1; break;
1145                }
1146             if (eq)
1147             {
1148                if (lt && gt)
1149                   return _error->Error(_("Couldn't parse name '%s'"),S);
1150                else if (lt)
1151                   VerOp = pkgCache::Dep::LessEq;
1152                else if (gt)
1153                   VerOp = pkgCache::Dep::GreaterEq;
1154                else
1155                   VerOp = pkgCache::Dep::Equals;
1156             }
1157             else
1158             {
1159                if (lt && gt)
1160                   VerOp = pkgCache::Dep::NotEquals;
1161                else if (lt)
1162                   VerOp = pkgCache::Dep::Less;
1163                else if (gt)
1164                   VerOp = pkgCache::Dep::Greater;
1165                else
1166                   return _error->Error(_("Couldn't parse name '%s'"),S);
1167             }
1168             *sep = '\0';
1169             VerTag = p;
1170          }
1171          
1172          // CNC:2003-11-21 - Try to handle unknown file items.
1173          if (S[0] == '/')
1174          {
1175             pkgRecords Recs(Cache);
1176             if (_error->PendingError() == true)
1177                return false;
1178             pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1179             for (; Pkg.end() == false; Pkg++)
1180             {
1181                // Should we try on all versions?
1182                pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1183                if (Ver.end() == false)
1184                {
1185                   pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1186                   if (Parse.HasFile(S)) {
1187                      strcpy(S, Pkg.Name());
1188                      ioprintf(c1out,_("Selecting %s for '%s'\n"),
1189                               Pkg.Name(),OrigS);
1190                      // Confirm the translation.
1191                      ExpectedInst += 1000;
1192                      break;
1193                   }
1194                }
1195             }
1196          }
1197
1198          char *Slash = strchr(S,'/');
1199          if (Slash != 0)
1200          {
1201             VerIsRel = true;
1202             *Slash = 0;
1203             VerTag = Slash + 1;
1204          }
1205          
1206          break;
1207       }
1208       
1209       // Locate the package
1210       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1211       Packages++;
1212       if (Pkg.end() == true)
1213       {
1214          // Check if the name is a regex
1215          const char *I;
1216          for (I = S; *I != 0; I++)
1217             if (*I == '?' || *I == '*' || *I == '|' ||
1218                 *I == '[' || *I == '^' || *I == '$')
1219                break;
1220
1221          // CNC:2003-05-15
1222          if (*I == 0) {
1223 #ifdef WITH_LUA
1224             vector<string> VS;
1225             _lua->SetDepCache(Cache);
1226             _lua->SetDontFix();
1227             _lua->SetGlobal("argument", OrigS);
1228             _lua->SetGlobal("translated", VS);
1229             _lua->RunScripts("Scripts::AptGet::Install::TranslateArg");
1230             const char *name = _lua->GetGlobalStr("translated");
1231             if (name != NULL) {
1232                VS.push_back(name);
1233             } else {
1234                VS = _lua->GetGlobalStrList("translated");
1235             }
1236             _lua->ResetGlobals();
1237             _lua->ResetCaches();
1238
1239             // Translations must always be confirmed
1240             ExpectedInst += 1000;
1241
1242             // Run over the matches
1243             bool Hit = false;
1244             for (vector<string>::const_iterator I = VS.begin();
1245                  I != VS.end(); I++) {
1246
1247                Pkg = Cache->FindPkg(*I);
1248                if (Pkg.end() == true)
1249                   continue;
1250
1251                ioprintf(c1out,_("Selecting %s for '%s'\n"),
1252                         Pkg.Name(),OrigS);
1253             
1254                Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1255                                    ExpectedInst,true);
1256             }
1257          
1258             if (Hit == true)
1259                continue;
1260 #endif
1261             return _error->Error(_("Couldn't find package %s"),S);
1262          }
1263
1264          // Regexs must always be confirmed
1265          ExpectedInst += 1000;
1266          
1267          // Compile the regex pattern
1268          regex_t Pattern;
1269          int Res;
1270          if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1271                      REG_NOSUB)) != 0)
1272          {
1273             char Error[300];        
1274             regerror(Res,&Pattern,Error,sizeof(Error));
1275             return _error->Error(_("Regex compilation error - %s"),Error);
1276          }
1277          
1278          // Run over the matches
1279          bool Hit = false;
1280          for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1281          {
1282             if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1283                continue;
1284             
1285             // CNC:2003-11-23
1286             ioprintf(c1out,_("Selecting %s for '%s'\n"),
1287                      Pkg.Name(),S);
1288             
1289             if (VerTag != 0)
1290                // CNC:2003-11-05
1291                if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1292                   return false;
1293             
1294             Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1295                                 ExpectedInst,false);
1296          }
1297          regfree(&Pattern);
1298          
1299          if (Hit == false)
1300             return _error->Error(_("Couldn't find package %s"),S);
1301       }
1302       else
1303       {
1304          if (VerTag != 0)
1305             // CNC:2003-11-05
1306             if (TryToChangeVer(Pkg,Cache,VerOp,VerTag,VerIsRel) == false)
1307                return false;
1308          if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
1309             return false;
1310       }      
1311    }
1312
1313 // CNC:2003-03-19
1314 #ifdef WITH_LUA
1315    _lua->SetDepCache(Cache);
1316    _lua->SetDontFix();
1317    _lua->RunScripts("Scripts::AptGet::Install::PreResolve");
1318    _lua->ResetCaches();
1319 #endif
1320
1321    // CNC:2002-08-01
1322    if (_config->FindB("APT::Remove-Depends",false) == true)
1323       Fix.RemoveDepends();
1324
1325    /* If we are in the Broken fixing mode we do not attempt to fix the
1326       problems. This is if the user invoked install without -f and gave
1327       packages */
1328    if (BrokenFix == true && Cache->BrokenCount() != 0)
1329    {
1330       c1out << _("You might want to run `apt-get --fix-broken install' to correct these:") << endl;
1331       ShowBroken(c1out,Cache,false);
1332
1333       return _error->Error(_("Unmet dependencies. Try 'apt-get --fix-broken install' with no packages (or specify a solution)."));
1334    }
1335    
1336    // Call the scored problem resolver
1337    Fix.InstallProtect();
1338    if (Fix.Resolve(true) == false)
1339       _error->Discard();
1340
1341 // CNC:2003-03-19
1342 #ifdef WITH_LUA
1343    if (Cache->BrokenCount() == 0) {
1344       _lua->SetDepCache(Cache);
1345       _lua->SetProblemResolver(&Fix);
1346       _lua->RunScripts("Scripts::AptGet::Install::PostResolve");
1347       _lua->ResetCaches();
1348    }
1349 #endif
1350
1351    // Now we check the state of the packages,
1352    if (Cache->BrokenCount() != 0)
1353    {
1354       c1out << 
1355        _("Some packages could not be installed. This may mean that you have\n" 
1356          "requested an impossible situation or that some of the repositories\n"
1357          "in use are in an inconsistent state at the moment.") << endl;
1358       if (Packages == 1)
1359       {
1360          c1out << endl;
1361          c1out << 
1362           _("Since you only requested a single operation it is extremely likely that\n"
1363             "the package is simply not installable and a bug report against\n" 
1364             "that package should be filed.") << endl;
1365       }
1366
1367       c1out << _("The following information may help to resolve the situation:") << endl;
1368       c1out << endl;
1369       ShowBroken(c1out,Cache,false);
1370       return _error->Error(_("Broken packages"));
1371    }   
1372    
1373    /* Print out a list of packages that are going to be installed extra
1374       to what the user asked */
1375    if (Cache->InstCount() != ExpectedInst)
1376    {
1377       string List;
1378       string VersionsList;
1379       for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1380       {
1381          pkgCache::PkgIterator I(Cache,Cache.List[J]);
1382          if ((*Cache)[I].Install() == false)
1383             continue;
1384
1385          // CNC:2004-06-15
1386          const char **K;
1387          for (K = CmdL.FileList + 1; *K != 0; K++)
1388             if (strcmp(*K,I.Name()) == 0)
1389                 break;
1390          
1391          if (*K == 0) {
1392             List += string(I.Name()) + " ";
1393         VersionsList += string(Cache[I].CandVersion) + "\n";
1394      }
1395       }
1396       
1397       ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
1398    }
1399
1400    /* Print out a list of suggested and recommended packages */
1401    {
1402       string SuggestsList, RecommendsList, List;
1403       string SuggestsVersions, RecommendsVersions;
1404       for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1405       {
1406          pkgCache::PkgIterator I(Cache,Cache.List[J]);
1407
1408          /* Just look at the ones we want to install */
1409          if ((*Cache)[I].Install() == false)
1410            continue;
1411
1412          for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
1413            {
1414              for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
1415                {
1416                  pkgCache::DepIterator Start;
1417                  pkgCache::DepIterator End;
1418                  D.GlobOr(Start,End);
1419
1420                  /* 
1421                   * If this is a virtual package, we need to check the list of
1422                   * packages that provide it and see if any of those are
1423                   * installed
1424                   */
1425                  pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
1426                  bool providedBySomething = false;
1427                  for (; Prv.end() != true; Prv++)
1428                     if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) {
1429                        providedBySomething = true;
1430                        break;
1431                     }
1432
1433                  if (providedBySomething) continue;
1434             
1435                  do
1436                    {
1437                      if (Start->Type == pkgCache::Dep::Suggests) {
1438
1439                        /* A suggests relations, let's see if we have it 
1440                           installed already */
1441
1442                        string target = string(Start.TargetPkg().Name()) + " ";
1443                        if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
1444                          break;
1445                        /* Does another package suggest it as well?  If so,
1446                           don't print it twice */
1447                        if (int(SuggestsList.find(target)) > -1)
1448                          break; 
1449                        SuggestsList += target;
1450                        SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
1451                      }
1452                      
1453                      if (Start->Type == pkgCache::Dep::Recommends) {
1454
1455                        /* A recommends relation, let's see if we have it
1456                           installed already */
1457
1458                        string target = string(Start.TargetPkg().Name()) + " ";
1459                        if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
1460                          break;
1461                        
1462                        /* Does another package recommend it as well?  If so,
1463                           don't print it twice */
1464
1465                        if (int(RecommendsList.find(target)) > -1)
1466                          break;
1467                        RecommendsList += target;
1468                        SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
1469                      }
1470               if (Start == End)
1471                 break;
1472               Start++;
1473             } while (1);
1474                }
1475            }
1476       }
1477       ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
1478       ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
1479
1480    }
1481
1482    // CNC:2003-03-06
1483    if (CheckOnly(Cache) == true)
1484       return true;
1485
1486    // See if we need to prompt
1487    if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
1488       return InstallPackages(Cache,false,false);
1489    
1490    return InstallPackages(Cache,false);   
1491 }
1492                                                                         /*}}}*/
1493 // DoDistUpgrade - Automatic smart upgrader                             /*{{{*/
1494 // ---------------------------------------------------------------------
1495 /* Intelligent upgrader that will install and remove packages at will */
1496 bool DoDistUpgrade(CommandLine &CmdL)
1497 {
1498    CacheFile Cache;
1499    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1500       return false;
1501
1502    c0out << _("Calculating Upgrade... ") << flush;
1503    if (pkgDistUpgrade(*Cache) == false)
1504    {
1505       c0out << _("Failed") << endl;
1506       ShowBroken(c1out,Cache,false);
1507       return false;
1508    }
1509
1510 // CNC:2003-03-19
1511 #ifdef WITH_LUA
1512    _lua->SetDepCache(Cache);
1513    _lua->RunScripts("Scripts::AptGet::DistUpgrade");
1514    _lua->ResetCaches();
1515 #endif
1516    
1517    // CNC:2003-03-06
1518    if (CheckOnly(Cache) == true)
1519       return true;
1520    
1521    c0out << _("Done") << endl;
1522    
1523    return InstallPackages(Cache,true);
1524 }
1525                                                                         /*}}}*/
1526 // DoClean - Remove download archives                                   /*{{{*/
1527 // ---------------------------------------------------------------------
1528 /* */
1529 bool DoClean(CommandLine &CmdL)
1530 {
1531    return cmdDoClean(CmdL);
1532 }
1533                                                                         /*}}}*/
1534 bool DoAutoClean(CommandLine &CmdL)
1535 {
1536    // Lock the archive directory
1537    FileFd Lock;
1538    if (_config->FindB("Debug::NoLocking",false) == false)
1539    {
1540       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1541       if (_error->PendingError() == true)
1542          return _error->Error(_("Unable to lock the download directory"));
1543    }
1544    
1545    CacheFile Cache;
1546    if (Cache.Open() == false)
1547       return false;
1548    
1549    LogCleaner Cleaner;
1550    
1551    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1552       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1553 }
1554                                                                         /*}}}*/
1555 // DoCheck - Perform the check operation                                /*{{{*/
1556 // ---------------------------------------------------------------------
1557 /* Opening automatically checks the system, this command is mostly used
1558    for debugging */
1559 bool DoCheck(CommandLine &CmdL)
1560 {
1561    CacheFile Cache;
1562    Cache.Open();
1563    Cache.CheckDeps();
1564    
1565    return true;
1566 }
1567                                                                         /*}}}*/
1568 // DoSource - Fetch a source archive                                    /*{{{*/
1569 // ---------------------------------------------------------------------
1570 /* Fetch souce packages */
1571 struct DscFile
1572 {
1573    string Package;
1574    string Version;
1575    string Dsc;
1576 };
1577
1578 bool DoSource(CommandLine &CmdL)
1579 {
1580    CacheFile Cache;
1581    if (Cache.Open(false) == false)
1582       return false;
1583
1584    if (CmdL.FileSize() <= 1)
1585       return _error->Error(_("Must specify at least one package to fetch source for"));
1586    
1587    // Read the source list
1588    pkgSourceList List;
1589    if (List.ReadMainList() == false)
1590       return _error->Error(_("The list of sources could not be read."));
1591    
1592    // Create the text record parsers
1593    pkgRecords Recs(Cache);
1594    pkgSrcRecords SrcRecs(List);
1595    if (_error->PendingError() == true)
1596       return false;
1597
1598    // Create the download object
1599    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1600    pkgAcquire Fetcher(&Stat);
1601
1602    DscFile *Dsc = new DscFile[CmdL.FileSize()];
1603    
1604    // Load the requestd sources into the fetcher
1605    unsigned J = 0;
1606    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1607    {
1608       // CNC:2004-09-23 - Try to handle unknown file items.
1609       size_t Length = strlen(*I);
1610       char S[300];
1611       if (Length >= sizeof(S))
1612         continue;
1613       strcpy(S,*I);
1614
1615       if (S[0] == '/')
1616       {
1617          pkgRecords Recs(Cache);
1618          if (_error->PendingError() == true)
1619             return false;
1620          pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1621          for (; Pkg.end() == false; Pkg++)
1622          {
1623             // Should we try on all versions?
1624             pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1625             if (Ver.end() == false)
1626             {
1627                pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1628                if (Parse.HasFile(S)) {
1629                   ioprintf(c1out,_("Selecting %s for '%s'\n"),
1630                            Pkg.Name(),S);
1631                   strcpy(S, Pkg.Name());
1632                   break;
1633                }
1634             }
1635          }
1636       }
1637
1638       string Src;
1639       pkgSrcRecords::Parser *Last = FindSrc(S,Recs,SrcRecs,Src,*Cache);
1640       
1641       if (Last == 0)
1642          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1643       
1644       // Back track
1645       vector<pkgSrcRecords::File> Lst;
1646       if (Last->Files(Lst) == false)
1647          return false;
1648
1649       // Load them into the fetcher
1650       for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1651            I != Lst.end(); I++)
1652       {
1653          if (I->Type == "srpm") {
1654             Dsc[J].Package = Last->Package();
1655             Dsc[J].Version = Last->Version();
1656             Dsc[J].Dsc = flNotDir(I->Path);
1657          } else {
1658             continue;
1659          }
1660          
1661          new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
1662                         I->MD5Hash,I->Size,
1663                         Last->Index().SourceInfo(*Last,*I),Src);
1664       }
1665    }
1666    
1667    // Display statistics
1668    double FetchBytes = Fetcher.FetchNeeded();
1669    double FetchPBytes = Fetcher.PartialPresent();
1670    double DebBytes = Fetcher.TotalNeeded();
1671
1672    // Check for enough free space
1673    struct statvfs Buf;
1674    string OutputDir = ".";
1675    if (statvfs(OutputDir.c_str(),&Buf) != 0)
1676       return _error->Errno("statvfs","Couldn't determine free space in %s",
1677                            OutputDir.c_str());
1678    // CNC:2002-07-12
1679    if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1680       return _error->Error(_("You don't have enough free space in %s"),
1681                            OutputDir.c_str());
1682    
1683    // Number of bytes
1684    if (DebBytes != FetchBytes)
1685       ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
1686                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
1687    else
1688       ioprintf(c1out,_("Need to get %sB of source archives.\n"),
1689                SizeToStr(DebBytes).c_str());
1690    
1691    if (_config->FindB("APT::Get::Simulate",false) == true)
1692    {
1693       for (unsigned I = 0; I != J; I++)
1694          ioprintf(cout,_("Fetch Source %s\n"),Dsc[I].Package.c_str());
1695       return true;
1696    }
1697    
1698    // Just print out the uris an exit if the --print-uris flag was used
1699    if (_config->FindB("APT::Get::Print-URIs") == true)
1700    {
1701       pkgAcquire::UriIterator I = Fetcher.UriBegin();
1702       for (; I != Fetcher.UriEnd(); I++)
1703          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
1704                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1705       return true;
1706    }
1707    
1708    // Run it
1709    if (Fetcher.Run() == pkgAcquire::Failed)
1710       return false;
1711
1712    // Print error messages
1713    bool Failed = false;
1714    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1715    {
1716       if ((*I)->Status == pkgAcquire::Item::StatDone &&
1717           (*I)->Complete == true)
1718          continue;
1719       
1720       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
1721               (*I)->ErrorText.c_str());
1722       Failed = true;
1723    }
1724    if (Failed == true)
1725       return _error->Error(_("Failed to fetch some archives."));
1726    
1727    if (_config->FindB("APT::Get::Download-only",false) == true)
1728    {
1729       c1out << _("Download complete and in download only mode") << endl;
1730       return true;
1731    }
1732
1733    // Unpack the sources
1734    pid_t Process = ExecFork();
1735    
1736    if (Process == 0)
1737    {
1738       for (unsigned I = 0; I != J; I++)
1739       {
1740          string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
1741          
1742          if (Dsc[I].Dsc.empty() == true)
1743             continue;
1744
1745          if (_config->FindB("APT::Get::Compile",false) == true)
1746          {
1747             char S[500];
1748             snprintf(S,sizeof(S),"%s %s %s",
1749                      _config->Find("RPM::Source::Build-Command","rpmbuild --rebuild").c_str(),
1750                      _config->Find("RPM::Source::Build-Options","").c_str(),
1751                      Dsc[I].Dsc.c_str());
1752             if (system(S) != 0)
1753             {
1754                fprintf(stderr,_("Build command '%s' failed.\n"),S);
1755                _exit(1);
1756             }       
1757          }
1758          else
1759          {
1760             char S[500];
1761             snprintf(S,sizeof(S),"%s %s",
1762                      _config->Find("RPM::Source::Install-Command","rpm -ivh").c_str(),
1763                      Dsc[I].Dsc.c_str());
1764             if (system(S) != 0)
1765             {
1766                fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
1767                _exit(1);
1768             }       
1769          } 
1770       }
1771       
1772       _exit(0);
1773    }
1774    
1775    // Wait for the subprocess
1776    int Status = 0;
1777    while (waitpid(Process,&Status,0) != Process)
1778    {
1779       if (errno == EINTR)
1780          continue;
1781       return _error->Errno("waitpid","Couldn't wait for subprocess");
1782    }
1783
1784    if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1785       return _error->Error(_("Child process failed"));
1786    
1787    return true;
1788 }
1789                                                                         /*}}}*/
1790 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
1791 // ---------------------------------------------------------------------
1792 /* This function will look at the build depends list of the given source 
1793    package and install the necessary packages to make it true, or fail. */
1794 bool DoBuildDep(CommandLine &CmdL)
1795 {
1796    CacheFile Cache;
1797    // CNC:2004-04-06
1798    if (Cache.OpenForInstall() == false || 
1799        Cache.CheckDeps() == false)
1800       return false;
1801
1802    if (CmdL.FileSize() <= 1)
1803       return _error->Error(_("Must specify at least one package to check builddeps for"));
1804    
1805    // Read the source list
1806    pkgSourceList List;
1807    if (List.ReadMainList() == false)
1808       return _error->Error(_("The list of sources could not be read."));
1809    
1810    // Create the text record parsers
1811    pkgRecords Recs(Cache);
1812    pkgSrcRecords SrcRecs(List);
1813    if (_error->PendingError() == true)
1814       return false;
1815
1816    // Create the download object
1817    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1818    pkgAcquire Fetcher(&Stat);
1819
1820    unsigned J = 0;
1821    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1822    {
1823       string Src;
1824       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1825       if (Last == 0)
1826          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1827             
1828       // Process the build-dependencies
1829       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1830       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
1831         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1832    
1833       // Also ensure that build-essential packages are present
1834       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1835       if (Opts) 
1836          Opts = Opts->Child;
1837       for (; Opts; Opts = Opts->Next)
1838       {
1839          if (Opts->Value.empty() == true)
1840             continue;
1841
1842          pkgSrcRecords::Parser::BuildDepRec rec;
1843          rec.Package = Opts->Value;
1844          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1845          rec.Op = 0;
1846          BuildDeps.push_back(rec);
1847       }
1848
1849       if (BuildDeps.size() == 0)
1850       {
1851          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1852          continue;
1853       }
1854       
1855       // Install the requested packages
1856       unsigned int ExpectedInst = 0;
1857       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1858       pkgProblemResolver Fix(Cache);
1859       bool skipAlternatives = false; // skip remaining alternatives in an or group
1860       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1861       {
1862          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1863
1864          if (skipAlternatives == true)
1865          {
1866             if (!hasAlternatives)
1867                skipAlternatives = false; // end of or group
1868             continue;
1869          }
1870
1871          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1872              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1873          {
1874             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1875             // Build-conflicts on unknown packages are silently ignored
1876             if (Pkg.end() == true)
1877                continue;
1878
1879             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1880
1881             /* 
1882              * Remove if we have an installed version that satisfies the 
1883              * version criteria
1884              */
1885             if (IV.end() == false && 
1886                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1887                TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
1888          }
1889          else // BuildDep || BuildDepIndep
1890          {
1891             if (_config->FindB("Debug::BuildDeps",false) == true)
1892                  cout << "Looking for " << (*D).Package << "...\n";
1893
1894             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1895
1896             // CNC:2003-11-21 - Try to handle unknown file deps.
1897             if (Pkg.end() == true && (*D).Package[0] == '/')
1898             {
1899                const char *File = (*D).Package.c_str();
1900                Pkg = (*Cache).PkgBegin();
1901                for (; Pkg.end() == false; Pkg++)
1902                {
1903                   // Should we try on all versions?
1904                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1905                   if (Ver.end() == false)
1906                   {
1907                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1908                      if (Parse.HasFile(File))
1909                         break;
1910                   }
1911                }
1912             }
1913
1914             if (Pkg.end() == true)
1915             {
1916                if (_config->FindB("Debug::BuildDeps",false) == true)
1917                     cout << " (not found)" << (*D).Package << endl;
1918
1919                if (hasAlternatives)
1920                   continue;
1921
1922                return _error->Error(_("%s dependency for %s cannot be satisfied "
1923                                       "because the package %s cannot be found"),
1924                                     Last->BuildDepType((*D).Type),Src.c_str(),
1925                                     (*D).Package.c_str());
1926             }
1927
1928             /*
1929              * if there are alternatives, we've already picked one, so skip
1930              * the rest
1931              *
1932              * TODO: this means that if there's a build-dep on A|B and B is
1933              * installed, we'll still try to install A; more importantly,
1934              * if A is currently broken, we cannot go back and try B. To fix 
1935              * this would require we do a Resolve cycle for each package we 
1936              * add to the install list. Ugh
1937              */
1938                        
1939             /* 
1940              * If this is a virtual package, we need to check the list of
1941              * packages that provide it and see if any of those are
1942              * installed
1943              */
1944             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1945             for (; Prv.end() != true; Prv++)
1946             {
1947                if (_config->FindB("Debug::BuildDeps",false) == true)
1948                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
1949
1950                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1951                   break;
1952             }
1953             
1954             // Get installed version and version we are going to install
1955             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1956
1957             if ((*D).Version[0] != '\0') {
1958                  // Versioned dependency
1959
1960                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1961
1962                  for (; CV.end() != true; CV++)
1963                  {
1964                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1965                            break;
1966                  }
1967                  if (CV.end() == true)
1968                    if (hasAlternatives)
1969                    {
1970                       continue;
1971                    }
1972                    else
1973                    {
1974                       return _error->Error(_("%s dependency for %s cannot be satisfied "
1975                                              "because no available versions of package %s "
1976                                              "can satisfy version requirements"),
1977                                            Last->BuildDepType((*D).Type),Src.c_str(),
1978                                            (*D).Package.c_str());
1979                    }
1980             }
1981             else
1982             {
1983                // Only consider virtual packages if there is no versioned dependency
1984                if (Prv.end() == false)
1985                {
1986                   if (_config->FindB("Debug::BuildDeps",false) == true)
1987                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
1988                   skipAlternatives = hasAlternatives;
1989                   continue;
1990                }
1991             }
1992
1993             if (IV.end() == false)
1994             {
1995                if (_config->FindB("Debug::BuildDeps",false) == true)
1996                   cout << "  Is installed\n";
1997
1998                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1999                {
2000                   skipAlternatives = hasAlternatives;
2001                   continue;
2002                }
2003
2004                if (_config->FindB("Debug::BuildDeps",false) == true)
2005                   cout << "    ...but the installed version doesn't meet the version requirement\n";
2006
2007                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
2008                {
2009                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
2010                                        Last->BuildDepType((*D).Type),
2011                                        Src.c_str(),
2012                                        Pkg.Name());
2013                }
2014             }
2015
2016
2017             if (_config->FindB("Debug::BuildDeps",false) == true)
2018                cout << "  Trying to install " << (*D).Package << endl;
2019
2020             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
2021             {
2022                // We successfully installed something; skip remaining alternatives
2023                skipAlternatives = hasAlternatives;
2024                continue;
2025             }
2026             else if (hasAlternatives)
2027             {
2028                if (_config->FindB("Debug::BuildDeps",false) == true)
2029                   cout << "  Unsatisfiable, trying alternatives\n";
2030                continue;
2031             }
2032             else
2033             {
2034                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
2035                                     Last->BuildDepType((*D).Type),
2036                                     Src.c_str(),
2037                                     (*D).Package.c_str());
2038             }
2039          }             
2040       }
2041       
2042       Fix.InstallProtect();
2043       if (Fix.Resolve(true) == false)
2044          _error->Discard();
2045       
2046       // Now we check the state of the packages,
2047       if (Cache->BrokenCount() != 0)
2048       {
2049          // CNC:2004-07-05
2050          ShowBroken(c1out, Cache, false);
2051          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
2052                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
2053       }
2054    }
2055   
2056    if (InstallPackages(Cache, false, true) == false)
2057       return _error->Error(_("Failed to process build dependencies"));
2058
2059    // CNC:2003-03-06
2060    if (CheckOnly(Cache) == true)
2061       return true;
2062    
2063    return true;
2064 }
2065                                                                         /*}}}*/
2066
2067 // DoMoo - Never Ask, Never Tell                                        /*{{{*/
2068 // ---------------------------------------------------------------------
2069 /* */
2070 bool DoMoo(CommandLine &CmdL)
2071 {
2072    cout << 
2073       "         (__) \n"
2074       "         (oo) \n"
2075       "   /------\\/ \n"
2076       "  / |    ||   \n" 
2077       " *  /\\---/\\ \n"
2078       "    ~~   ~~   \n"
2079       "....\"Have you mooed today?\"...\n";
2080                             
2081    return true;
2082 }
2083                                                                         /*}}}*/
2084
2085 // CNC:2003-03-18
2086 // DoScript - Scripting stuff.                                          /*{{{*/
2087 // ---------------------------------------------------------------------
2088 /* */
2089 #ifdef WITH_LUA
2090 bool DoScript(CommandLine &CmdL)
2091 {
2092    for (const char **I = CmdL.FileList+1; *I != 0; I++)
2093       _config->Set("Scripts::AptGet::Script::", *I);
2094
2095    _lua->SetGlobal("commit_ask", 1);
2096    _lua->RunScripts("Scripts::AptGet::Script");
2097    double Ask = _lua->GetGlobalNum("commit_ask");
2098    _lua->ResetGlobals();
2099
2100    AptGetLuaCache *LuaCache = (AptGetLuaCache*) _lua->GetCacheControl();
2101    if (LuaCache && LuaCache->Cache) {
2102       CacheFile &Cache = *LuaCache->Cache;
2103       if (CheckOnly(Cache))
2104          return true;
2105       if ((*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
2106          return InstallPackages(Cache, false, Ask);
2107    }
2108
2109    return true;
2110 }
2111 #endif
2112                                                                         /*}}}*/
2113
2114 // ShowHelp - Show a help screen                                        /*{{{*/
2115 // ---------------------------------------------------------------------
2116 /* */
2117 bool ShowHelp(CommandLine &CmdL)
2118 {
2119    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
2120             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
2121             
2122    if (_config->FindB("version") == true)
2123    {
2124       cout << _("Supported Modules:") << endl;
2125       
2126       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
2127       {
2128          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
2129          if (_system != 0 && _system->VS == VS)
2130             cout << '*';
2131          else
2132             cout << ' ';
2133          cout << "Ver: " << VS->Label << endl;
2134          
2135          /* Print out all the packaging systems that will work with 
2136             this VS */
2137          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
2138          {
2139             pkgSystem *Sys = pkgSystem::GlobalList[J];
2140             if (_system == Sys)
2141                cout << '*';
2142             else
2143                cout << ' ';
2144             if (Sys->VS->TestCompatibility(*VS) == true)
2145                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2146          }
2147       }
2148       
2149       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2150       {
2151          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2152          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2153       }      
2154       
2155       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2156       {
2157          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2158          cout << " Idx: " << Type->Label << endl;
2159       }      
2160       
2161       return true;
2162    }
2163    
2164    cout << 
2165     _("Usage: apt-get [options] command\n"
2166       "       apt-get [options] install|remove pkg1 [pkg2 ...]\n"
2167       "       apt-get [options] source pkg1 [pkg2 ...]\n"
2168       "\n"
2169       "apt-get is a simple command line interface for downloading and\n"
2170       "installing packages. The most frequently used commands are update\n"
2171       "and install.\n"   
2172       "\n"
2173       "Commands:\n"
2174       "   update - Retrieve new lists of packages\n"
2175       "   upgrade - Perform an upgrade\n"
2176 // CNC:2003-02-20 - Use .rpm extension in documentation.
2177       "   install - Install new packages (pkg is libc6 not libc6.rpm)\n"
2178       "   remove - Remove packages\n"
2179       "   source - Download source archives\n"
2180       "   build-dep - Configure build-dependencies for source packages\n"
2181       "   dist-upgrade - Distribution upgrade, see apt-get(8)\n"
2182 // CNC:2002-08-01
2183 //      "   dselect-upgrade - Follow dselect selections\n"
2184       "   clean - Erase downloaded archive files\n"
2185       "   autoclean - Erase old downloaded archive files\n"
2186       "   check - Verify that there are no broken dependencies\n"
2187 // CNC:2003-03-16
2188       );
2189 #ifdef WITH_LUA
2190       _lua->RunScripts("Scripts::AptGet::Help::Command");
2191 #endif
2192       cout << _(
2193       "\n"
2194       "Options:\n"
2195       "  -h  This help text.\n"
2196       "  -q  Loggable output - no progress indicator\n"
2197       "  -qq No output except for errors\n"
2198       "  -d  Download only - do NOT install or unpack archives\n"
2199       "  -s  No-act. Perform ordering simulation\n"
2200       "  -y  Assume Yes to all queries and do not prompt\n"
2201       "  -f  Attempt to continue if the integrity check fails\n"
2202       "  -m  Attempt to continue if archives are unlocatable\n"
2203       "  -u  Show a list of upgraded packages as well\n"
2204       "  -b  Build the source package after fetching it\n"
2205 // CNC:2002-08-02
2206       "  -D  When removing packages, remove dependencies as possible\n"
2207       "  -V  Show verbose version numbers\n"
2208       "  -c=? Read this configuration file\n"
2209       "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2210       "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
2211       "pages for more information and options.\n"
2212       "                       This APT has Super Cow Powers.\n");
2213    return true;
2214 }
2215                                                                         /*}}}*/
2216 // GetInitialize - Initialize things for apt-get                        /*{{{*/
2217 // ---------------------------------------------------------------------
2218 /* */
2219 void GetInitialize()
2220 {
2221    _config->Set("quiet",0);
2222    _config->Set("help",false);
2223    _config->Set("APT::Get::Download-Only",false);
2224    _config->Set("APT::Get::Simulate",false);
2225    _config->Set("APT::Get::Assume-Yes",false);
2226    _config->Set("APT::Get::Fix-Broken",false);
2227    _config->Set("APT::Get::Force-Yes",false);
2228    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
2229 }
2230                                                                         /*}}}*/
2231
2232 int main(int argc,const char *argv[])
2233 {
2234    CommandLine::Args Args[] = {
2235       {'h',"help","help",0},
2236       {'v',"version","version",0},
2237       {'V',"verbose-versions","APT::Get::Show-Versions",0},
2238       {'q',"quiet","quiet",CommandLine::IntLevel},
2239       {'q',"silent","quiet",CommandLine::IntLevel},
2240       {'d',"download-only","APT::Get::Download-Only",0},
2241       {'b',"compile","APT::Get::Compile",0},
2242       {'b',"build","APT::Get::Compile",0},
2243       {'s',"simulate","APT::Get::Simulate",0},
2244       {'s',"just-print","APT::Get::Simulate",0},
2245       {'s',"recon","APT::Get::Simulate",0},
2246       {'s',"dry-run","APT::Get::Simulate",0},
2247       {'s',"no-act","APT::Get::Simulate",0},
2248       {'y',"yes","APT::Get::Assume-Yes",0},
2249       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
2250       {'f',"fix-broken","APT::Get::Fix-Broken",0},
2251       {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
2252       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
2253       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
2254       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
2255       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
2256       {0,"download","APT::Get::Download",0},
2257       {0,"fix-missing","APT::Get::Fix-Missing",0},
2258       {0,"ignore-hold","APT::Ignore-Hold",0},      
2259       {0,"upgrade","APT::Get::upgrade",0},
2260       {0,"force-yes","APT::Get::force-yes",0},
2261       {0,"print-uris","APT::Get::Print-URIs",0},
2262       {0,"purge","APT::Get::Purge",0},
2263       {0,"list-cleanup","APT::Get::List-Cleanup",0},
2264       {0,"reinstall","APT::Get::ReInstall",0},
2265       {0,"trivial-only","APT::Get::Trivial-Only",0},
2266       {0,"remove","APT::Get::Remove",0},
2267       {0,"only-source","APT::Get::Only-Source",0},
2268       {0,"arch-only","APT::Get::Arch-Only",0},
2269       {0,"check-only","APT::Get::Check-Only",0}, // CNC:2003-03-06
2270       {0,"root","RPM::RootDir",CommandLine::HasArg},
2271       {'c',"config-file",0,CommandLine::ConfigFile},
2272       {'o',"option",0,CommandLine::ArbItem},
2273       {0,0,0,0}};
2274    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
2275                                    {"upgrade",&DoUpgrade},
2276                                    {"install",&DoInstall},
2277                                    // CNC:2004-03-22
2278                                    {"reinstall",&DoInstall},
2279                                    {"remove",&DoInstall},
2280                                    {"dist-upgrade",&DoDistUpgrade},
2281                                    {"build-dep",&DoBuildDep},
2282                                    {"clean",&DoClean},
2283                                    {"autoclean",&DoAutoClean},
2284                                    {"check",&DoCheck},
2285                                    {"source",&DoSource},
2286                                    {"moo",&DoMoo},
2287                                    {"help",&ShowHelp},
2288 // CNC:2003-03-19
2289 #ifdef WITH_LUA
2290                                    {"script",&DoScript},
2291 #endif
2292                                    {0,0}};
2293
2294    // Set up gettext support
2295    setlocale(LC_ALL,"");
2296    textdomain(PACKAGE);
2297
2298    // Parse the command line and initialize the package library
2299    CommandLine CmdL(Args,_config);
2300    if (pkgInitConfig(*_config) == false ||
2301        CmdL.Parse(argc,argv) == false ||
2302        pkgInitSystem(*_config,_system) == false)
2303    {
2304       if (_config->FindB("version") == true)
2305          ShowHelp(CmdL);
2306          
2307       _error->DumpErrors();
2308       return 100;
2309    }
2310
2311    // See if the help should be shown
2312    if (_config->FindB("help") == true ||
2313        _config->FindB("version") == true ||
2314        CmdL.FileSize() == 0)
2315    {
2316       ShowHelp(CmdL);
2317       return 0;
2318    }
2319    
2320    // CNC:2003-11-21
2321    if (CmdL.FileSize() > 1)
2322    {
2323       // CNC:2003-11-23
2324       vector<string> URLLst;
2325       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2326       {
2327          if (strstr(*I, "://") != NULL)
2328          {
2329             URLLst.push_back(*I);
2330             *I = strrchr(*I, '/')+1;
2331          }
2332       }
2333
2334       if (URLLst.empty() == false && DownloadPackages(URLLst) == false)
2335       {
2336             _error->DumpErrors();
2337             return 100;
2338       }
2339
2340       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2341          _config->Set("APT::Arguments::", *I);
2342    }
2343
2344    // Deal with stdout not being a tty
2345    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
2346       _config->Set("quiet","1");
2347
2348    // Setup the output streams
2349    c0out.rdbuf(cout.rdbuf());
2350    c1out.rdbuf(cout.rdbuf());
2351    c2out.rdbuf(cout.rdbuf());
2352    if (_config->FindI("quiet",0) > 0)
2353       c0out.rdbuf(devnull.rdbuf());
2354    if (_config->FindI("quiet",0) > 1)
2355       c1out.rdbuf(devnull.rdbuf());
2356
2357    // Setup the signals
2358    signal(SIGPIPE,SIG_IGN);
2359    signal(SIGWINCH,SigWinch);
2360    SigWinch(0);
2361
2362 // CNC:2003-11-23
2363 #ifdef WITH_LUA
2364    AptGetLuaCache LuaCache;
2365    _lua->SetCacheControl(&LuaCache);
2366    
2367    double Consume = 0;
2368    if (argc > 1 && _lua->HasScripts("Scripts::AptGet::Command") == true)
2369    {
2370       _lua->SetGlobal("commit_ask", 1);
2371       _lua->SetGlobal("command_args", CmdL.FileList);
2372       _lua->SetGlobal("command_consume", 0.0);
2373       _lua->RunScripts("Scripts::AptGet::Command");
2374       Consume = _lua->GetGlobalNum("command_consume");
2375       double Ask = _lua->GetGlobalNum("commit_ask");
2376       _lua->ResetGlobals();
2377       _lua->ResetCaches();
2378
2379       if (Consume == 1 && LuaCache.Cache)
2380       {
2381          CacheFile &Cache = *LuaCache.Cache;
2382          if (CheckOnly(Cache) == false &&
2383              (*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
2384             InstallPackages(Cache, false, Ask);
2385       }
2386    }
2387
2388    if (Consume == 0)
2389 #endif
2390    // Match the operation
2391    CmdL.DispatchArg(Cmds);
2392
2393    // Print any errors or warnings found during parsing
2394    if (_error->empty() == false)
2395    {
2396       bool Errors = _error->PendingError();
2397       _error->DumpErrors();
2398       return Errors == true?100:0;
2399    }
2400    
2401    return 0;   
2402 }
2403
2404 // vim:sts=3:sw=3