0576ace9ee3ce44600129771aec908c8cb7eba30
[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 // DoDSelectUpgrade - Do an upgrade by following dselects selections    /*{{{*/
1527 // ---------------------------------------------------------------------
1528 /* Follows dselect's selections */
1529 bool DoDSelectUpgrade(CommandLine &CmdL)
1530 {
1531    CacheFile Cache;
1532    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1533       return false;
1534    
1535    // Install everything with the install flag set
1536    pkgCache::PkgIterator I = Cache->PkgBegin();
1537    for (;I.end() != true; I++)
1538    {
1539       /* Install the package only if it is a new install, the autoupgrader
1540          will deal with the rest */
1541       if (I->SelectedState == pkgCache::State::Install)
1542          Cache->MarkInstall(I,false);
1543    }
1544
1545    /* Now install their deps too, if we do this above then order of
1546       the status file is significant for | groups */
1547    for (I = Cache->PkgBegin();I.end() != true; I++)
1548    {
1549       /* Install the package only if it is a new install, the autoupgrader
1550          will deal with the rest */
1551       if (I->SelectedState == pkgCache::State::Install)
1552          Cache->MarkInstall(I,true);
1553    }
1554    
1555    // Apply erasures now, they override everything else.
1556    for (I = Cache->PkgBegin();I.end() != true; I++)
1557    {
1558       // Remove packages 
1559       if (I->SelectedState == pkgCache::State::DeInstall ||
1560           I->SelectedState == pkgCache::State::Purge)
1561          Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
1562    }
1563
1564    /* Resolve any problems that dselect created, allupgrade cannot handle
1565       such things. We do so quite agressively too.. */
1566    if (Cache->BrokenCount() != 0)
1567    {      
1568       pkgProblemResolver Fix(Cache);
1569
1570       // Hold back held packages.
1571       if (_config->FindB("APT::Ignore-Hold",false) == false)
1572       {
1573          for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1574          {
1575             if (I->SelectedState == pkgCache::State::Hold)
1576             {
1577                Fix.Protect(I);
1578                Cache->MarkKeep(I);
1579             }
1580          }
1581       }
1582    
1583       if (Fix.Resolve() == false)
1584       {
1585          ShowBroken(c1out,Cache,false);
1586          return _error->Error("Internal Error, problem resolver broke stuff");
1587       }
1588    }
1589
1590    // Now upgrade everything
1591    if (pkgAllUpgrade(Cache) == false)
1592    {
1593       ShowBroken(c1out,Cache,false);
1594       return _error->Error("Internal Error, problem resolver broke stuff");
1595    }
1596
1597    // CNC:2003-03-06
1598    if (CheckOnly(Cache) == true)
1599       return true;
1600    
1601    return InstallPackages(Cache,false);
1602 }
1603                                                                         /*}}}*/
1604 // DoClean - Remove download archives                                   /*{{{*/
1605 // ---------------------------------------------------------------------
1606 /* */
1607 bool DoClean(CommandLine &CmdL)
1608 {
1609    return cmdDoClean(CmdL);
1610 }
1611                                                                         /*}}}*/
1612 bool DoAutoClean(CommandLine &CmdL)
1613 {
1614    // Lock the archive directory
1615    FileFd Lock;
1616    if (_config->FindB("Debug::NoLocking",false) == false)
1617    {
1618       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1619       if (_error->PendingError() == true)
1620          return _error->Error(_("Unable to lock the download directory"));
1621    }
1622    
1623    CacheFile Cache;
1624    if (Cache.Open() == false)
1625       return false;
1626    
1627    LogCleaner Cleaner;
1628    
1629    return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1630       Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1631 }
1632                                                                         /*}}}*/
1633 // DoCheck - Perform the check operation                                /*{{{*/
1634 // ---------------------------------------------------------------------
1635 /* Opening automatically checks the system, this command is mostly used
1636    for debugging */
1637 bool DoCheck(CommandLine &CmdL)
1638 {
1639    CacheFile Cache;
1640    Cache.Open();
1641    Cache.CheckDeps();
1642    
1643    return true;
1644 }
1645                                                                         /*}}}*/
1646 // DoSource - Fetch a source archive                                    /*{{{*/
1647 // ---------------------------------------------------------------------
1648 /* Fetch souce packages */
1649 struct DscFile
1650 {
1651    string Package;
1652    string Version;
1653    string Dsc;
1654 };
1655
1656 bool DoSource(CommandLine &CmdL)
1657 {
1658    CacheFile Cache;
1659    if (Cache.Open(false) == false)
1660       return false;
1661
1662    if (CmdL.FileSize() <= 1)
1663       return _error->Error(_("Must specify at least one package to fetch source for"));
1664    
1665    // Read the source list
1666    pkgSourceList List;
1667    if (List.ReadMainList() == false)
1668       return _error->Error(_("The list of sources could not be read."));
1669    
1670    // Create the text record parsers
1671    pkgRecords Recs(Cache);
1672    pkgSrcRecords SrcRecs(List);
1673    if (_error->PendingError() == true)
1674       return false;
1675
1676    // Create the download object
1677    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1678    pkgAcquire Fetcher(&Stat);
1679
1680    DscFile *Dsc = new DscFile[CmdL.FileSize()];
1681    
1682    // Load the requestd sources into the fetcher
1683    unsigned J = 0;
1684    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1685    {
1686       // CNC:2004-09-23 - Try to handle unknown file items.
1687       size_t Length = strlen(*I);
1688       char S[300];
1689       if (Length >= sizeof(S))
1690         continue;
1691       strcpy(S,*I);
1692
1693       if (S[0] == '/')
1694       {
1695          pkgRecords Recs(Cache);
1696          if (_error->PendingError() == true)
1697             return false;
1698          pkgCache::PkgIterator Pkg = (*Cache).PkgBegin();
1699          for (; Pkg.end() == false; Pkg++)
1700          {
1701             // Should we try on all versions?
1702             pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1703             if (Ver.end() == false)
1704             {
1705                pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1706                if (Parse.HasFile(S)) {
1707                   ioprintf(c1out,_("Selecting %s for '%s'\n"),
1708                            Pkg.Name(),S);
1709                   strcpy(S, Pkg.Name());
1710                   break;
1711                }
1712             }
1713          }
1714       }
1715
1716       string Src;
1717       pkgSrcRecords::Parser *Last = FindSrc(S,Recs,SrcRecs,Src,*Cache);
1718       
1719       if (Last == 0)
1720          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1721       
1722       // Back track
1723       vector<pkgSrcRecords::File> Lst;
1724       if (Last->Files(Lst) == false)
1725          return false;
1726
1727       // Load them into the fetcher
1728       for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1729            I != Lst.end(); I++)
1730       {
1731          if (I->Type == "srpm") {
1732             Dsc[J].Package = Last->Package();
1733             Dsc[J].Version = Last->Version();
1734             Dsc[J].Dsc = flNotDir(I->Path);
1735          } else {
1736             continue;
1737          }
1738          
1739          new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
1740                         I->MD5Hash,I->Size,
1741                         Last->Index().SourceInfo(*Last,*I),Src);
1742       }
1743    }
1744    
1745    // Display statistics
1746    double FetchBytes = Fetcher.FetchNeeded();
1747    double FetchPBytes = Fetcher.PartialPresent();
1748    double DebBytes = Fetcher.TotalNeeded();
1749
1750    // Check for enough free space
1751    struct statvfs Buf;
1752    string OutputDir = ".";
1753    if (statvfs(OutputDir.c_str(),&Buf) != 0)
1754       return _error->Errno("statvfs","Couldn't determine free space in %s",
1755                            OutputDir.c_str());
1756    // CNC:2002-07-12
1757    if (unsigned(Buf.f_bavail) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1758       return _error->Error(_("You don't have enough free space in %s"),
1759                            OutputDir.c_str());
1760    
1761    // Number of bytes
1762    if (DebBytes != FetchBytes)
1763       ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
1764                SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
1765    else
1766       ioprintf(c1out,_("Need to get %sB of source archives.\n"),
1767                SizeToStr(DebBytes).c_str());
1768    
1769    if (_config->FindB("APT::Get::Simulate",false) == true)
1770    {
1771       for (unsigned I = 0; I != J; I++)
1772          ioprintf(cout,_("Fetch Source %s\n"),Dsc[I].Package.c_str());
1773       return true;
1774    }
1775    
1776    // Just print out the uris an exit if the --print-uris flag was used
1777    if (_config->FindB("APT::Get::Print-URIs") == true)
1778    {
1779       pkgAcquire::UriIterator I = Fetcher.UriBegin();
1780       for (; I != Fetcher.UriEnd(); I++)
1781          cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
1782                I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1783       return true;
1784    }
1785    
1786    // Run it
1787    if (Fetcher.Run() == pkgAcquire::Failed)
1788       return false;
1789
1790    // Print error messages
1791    bool Failed = false;
1792    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1793    {
1794       if ((*I)->Status == pkgAcquire::Item::StatDone &&
1795           (*I)->Complete == true)
1796          continue;
1797       
1798       fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
1799               (*I)->ErrorText.c_str());
1800       Failed = true;
1801    }
1802    if (Failed == true)
1803       return _error->Error(_("Failed to fetch some archives."));
1804    
1805    if (_config->FindB("APT::Get::Download-only",false) == true)
1806    {
1807       c1out << _("Download complete and in download only mode") << endl;
1808       return true;
1809    }
1810
1811    // Unpack the sources
1812    pid_t Process = ExecFork();
1813    
1814    if (Process == 0)
1815    {
1816       for (unsigned I = 0; I != J; I++)
1817       {
1818          string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
1819          
1820          if (Dsc[I].Dsc.empty() == true)
1821             continue;
1822
1823          if (_config->FindB("APT::Get::Compile",false) == true)
1824          {
1825             char S[500];
1826             snprintf(S,sizeof(S),"%s %s %s",
1827                      _config->Find("RPM::Source::Build-Command","rpmbuild --rebuild").c_str(),
1828                      _config->Find("RPM::Source::Build-Options","").c_str(),
1829                      Dsc[I].Dsc.c_str());
1830             if (system(S) != 0)
1831             {
1832                fprintf(stderr,_("Build command '%s' failed.\n"),S);
1833                _exit(1);
1834             }       
1835          }
1836          else
1837          {
1838             char S[500];
1839             snprintf(S,sizeof(S),"%s %s",
1840                      _config->Find("RPM::Source::Install-Command","rpm -ivh").c_str(),
1841                      Dsc[I].Dsc.c_str());
1842             if (system(S) != 0)
1843             {
1844                fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
1845                _exit(1);
1846             }       
1847          } 
1848       }
1849       
1850       _exit(0);
1851    }
1852    
1853    // Wait for the subprocess
1854    int Status = 0;
1855    while (waitpid(Process,&Status,0) != Process)
1856    {
1857       if (errno == EINTR)
1858          continue;
1859       return _error->Errno("waitpid","Couldn't wait for subprocess");
1860    }
1861
1862    if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1863       return _error->Error(_("Child process failed"));
1864    
1865    return true;
1866 }
1867                                                                         /*}}}*/
1868 // DoBuildDep - Install/removes packages to satisfy build dependencies  /*{{{*/
1869 // ---------------------------------------------------------------------
1870 /* This function will look at the build depends list of the given source 
1871    package and install the necessary packages to make it true, or fail. */
1872 bool DoBuildDep(CommandLine &CmdL)
1873 {
1874    CacheFile Cache;
1875    // CNC:2004-04-06
1876    if (Cache.OpenForInstall() == false || 
1877        Cache.CheckDeps() == false)
1878       return false;
1879
1880    if (CmdL.FileSize() <= 1)
1881       return _error->Error(_("Must specify at least one package to check builddeps for"));
1882    
1883    // Read the source list
1884    pkgSourceList List;
1885    if (List.ReadMainList() == false)
1886       return _error->Error(_("The list of sources could not be read."));
1887    
1888    // Create the text record parsers
1889    pkgRecords Recs(Cache);
1890    pkgSrcRecords SrcRecs(List);
1891    if (_error->PendingError() == true)
1892       return false;
1893
1894    // Create the download object
1895    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
1896    pkgAcquire Fetcher(&Stat);
1897
1898    unsigned J = 0;
1899    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1900    {
1901       string Src;
1902       pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
1903       if (Last == 0)
1904          return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
1905             
1906       // Process the build-dependencies
1907       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
1908       if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
1909         return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1910    
1911       // Also ensure that build-essential packages are present
1912       Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1913       if (Opts) 
1914          Opts = Opts->Child;
1915       for (; Opts; Opts = Opts->Next)
1916       {
1917          if (Opts->Value.empty() == true)
1918             continue;
1919
1920          pkgSrcRecords::Parser::BuildDepRec rec;
1921          rec.Package = Opts->Value;
1922          rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1923          rec.Op = 0;
1924          BuildDeps.push_back(rec);
1925       }
1926
1927       if (BuildDeps.size() == 0)
1928       {
1929          ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1930          continue;
1931       }
1932       
1933       // Install the requested packages
1934       unsigned int ExpectedInst = 0;
1935       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1936       pkgProblemResolver Fix(Cache);
1937       bool skipAlternatives = false; // skip remaining alternatives in an or group
1938       for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
1939       {
1940          bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1941
1942          if (skipAlternatives == true)
1943          {
1944             if (!hasAlternatives)
1945                skipAlternatives = false; // end of or group
1946             continue;
1947          }
1948
1949          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1950              (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1951          {
1952             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1953             // Build-conflicts on unknown packages are silently ignored
1954             if (Pkg.end() == true)
1955                continue;
1956
1957             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1958
1959             /* 
1960              * Remove if we have an installed version that satisfies the 
1961              * version criteria
1962              */
1963             if (IV.end() == false && 
1964                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1965                TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
1966          }
1967          else // BuildDep || BuildDepIndep
1968          {
1969             if (_config->FindB("Debug::BuildDeps",false) == true)
1970                  cout << "Looking for " << (*D).Package << "...\n";
1971
1972             pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
1973
1974             // CNC:2003-11-21 - Try to handle unknown file deps.
1975             if (Pkg.end() == true && (*D).Package[0] == '/')
1976             {
1977                const char *File = (*D).Package.c_str();
1978                Pkg = (*Cache).PkgBegin();
1979                for (; Pkg.end() == false; Pkg++)
1980                {
1981                   // Should we try on all versions?
1982                   pkgCache::VerIterator Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1983                   if (Ver.end() == false)
1984                   {
1985                      pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1986                      if (Parse.HasFile(File))
1987                         break;
1988                   }
1989                }
1990             }
1991
1992             if (Pkg.end() == true)
1993             {
1994                if (_config->FindB("Debug::BuildDeps",false) == true)
1995                     cout << " (not found)" << (*D).Package << endl;
1996
1997                if (hasAlternatives)
1998                   continue;
1999
2000                return _error->Error(_("%s dependency for %s cannot be satisfied "
2001                                       "because the package %s cannot be found"),
2002                                     Last->BuildDepType((*D).Type),Src.c_str(),
2003                                     (*D).Package.c_str());
2004             }
2005
2006             /*
2007              * if there are alternatives, we've already picked one, so skip
2008              * the rest
2009              *
2010              * TODO: this means that if there's a build-dep on A|B and B is
2011              * installed, we'll still try to install A; more importantly,
2012              * if A is currently broken, we cannot go back and try B. To fix 
2013              * this would require we do a Resolve cycle for each package we 
2014              * add to the install list. Ugh
2015              */
2016                        
2017             /* 
2018              * If this is a virtual package, we need to check the list of
2019              * packages that provide it and see if any of those are
2020              * installed
2021              */
2022             pkgCache::PrvIterator Prv = Pkg.ProvidesList();
2023             for (; Prv.end() != true; Prv++)
2024             {
2025                if (_config->FindB("Debug::BuildDeps",false) == true)
2026                     cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
2027
2028                if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
2029                   break;
2030             }
2031             
2032             // Get installed version and version we are going to install
2033             pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2034
2035             if ((*D).Version[0] != '\0') {
2036                  // Versioned dependency
2037
2038                  pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
2039
2040                  for (; CV.end() != true; CV++)
2041                  {
2042                       if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2043                            break;
2044                  }
2045                  if (CV.end() == true)
2046                    if (hasAlternatives)
2047                    {
2048                       continue;
2049                    }
2050                    else
2051                    {
2052                       return _error->Error(_("%s dependency for %s cannot be satisfied "
2053                                              "because no available versions of package %s "
2054                                              "can satisfy version requirements"),
2055                                            Last->BuildDepType((*D).Type),Src.c_str(),
2056                                            (*D).Package.c_str());
2057                    }
2058             }
2059             else
2060             {
2061                // Only consider virtual packages if there is no versioned dependency
2062                if (Prv.end() == false)
2063                {
2064                   if (_config->FindB("Debug::BuildDeps",false) == true)
2065                      cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
2066                   skipAlternatives = hasAlternatives;
2067                   continue;
2068                }
2069             }
2070
2071             if (IV.end() == false)
2072             {
2073                if (_config->FindB("Debug::BuildDeps",false) == true)
2074                   cout << "  Is installed\n";
2075
2076                if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2077                {
2078                   skipAlternatives = hasAlternatives;
2079                   continue;
2080                }
2081
2082                if (_config->FindB("Debug::BuildDeps",false) == true)
2083                   cout << "    ...but the installed version doesn't meet the version requirement\n";
2084
2085                if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
2086                {
2087                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
2088                                        Last->BuildDepType((*D).Type),
2089                                        Src.c_str(),
2090                                        Pkg.Name());
2091                }
2092             }
2093
2094
2095             if (_config->FindB("Debug::BuildDeps",false) == true)
2096                cout << "  Trying to install " << (*D).Package << endl;
2097
2098             if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
2099             {
2100                // We successfully installed something; skip remaining alternatives
2101                skipAlternatives = hasAlternatives;
2102                continue;
2103             }
2104             else if (hasAlternatives)
2105             {
2106                if (_config->FindB("Debug::BuildDeps",false) == true)
2107                   cout << "  Unsatisfiable, trying alternatives\n";
2108                continue;
2109             }
2110             else
2111             {
2112                return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
2113                                     Last->BuildDepType((*D).Type),
2114                                     Src.c_str(),
2115                                     (*D).Package.c_str());
2116             }
2117          }             
2118       }
2119       
2120       Fix.InstallProtect();
2121       if (Fix.Resolve(true) == false)
2122          _error->Discard();
2123       
2124       // Now we check the state of the packages,
2125       if (Cache->BrokenCount() != 0)
2126       {
2127          // CNC:2004-07-05
2128          ShowBroken(c1out, Cache, false);
2129          return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
2130                                 "You might want to run `apt-get --fix-broken install' to correct these."),*I);
2131       }
2132    }
2133   
2134    if (InstallPackages(Cache, false, true) == false)
2135       return _error->Error(_("Failed to process build dependencies"));
2136
2137    // CNC:2003-03-06
2138    if (CheckOnly(Cache) == true)
2139       return true;
2140    
2141    return true;
2142 }
2143                                                                         /*}}}*/
2144
2145 // DoMoo - Never Ask, Never Tell                                        /*{{{*/
2146 // ---------------------------------------------------------------------
2147 /* */
2148 bool DoMoo(CommandLine &CmdL)
2149 {
2150    cout << 
2151       "         (__) \n"
2152       "         (oo) \n"
2153       "   /------\\/ \n"
2154       "  / |    ||   \n" 
2155       " *  /\\---/\\ \n"
2156       "    ~~   ~~   \n"
2157       "....\"Have you mooed today?\"...\n";
2158                             
2159    return true;
2160 }
2161                                                                         /*}}}*/
2162
2163 // CNC:2003-03-18
2164 // DoScript - Scripting stuff.                                          /*{{{*/
2165 // ---------------------------------------------------------------------
2166 /* */
2167 #ifdef WITH_LUA
2168 bool DoScript(CommandLine &CmdL)
2169 {
2170    for (const char **I = CmdL.FileList+1; *I != 0; I++)
2171       _config->Set("Scripts::AptGet::Script::", *I);
2172
2173    _lua->SetGlobal("commit_ask", 1);
2174    _lua->RunScripts("Scripts::AptGet::Script");
2175    double Ask = _lua->GetGlobalNum("commit_ask");
2176    _lua->ResetGlobals();
2177
2178    AptGetLuaCache *LuaCache = (AptGetLuaCache*) _lua->GetCacheControl();
2179    if (LuaCache && LuaCache->Cache) {
2180       CacheFile &Cache = *LuaCache->Cache;
2181       if (CheckOnly(Cache))
2182          return true;
2183       if ((*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
2184          return InstallPackages(Cache, false, Ask);
2185    }
2186
2187    return true;
2188 }
2189 #endif
2190                                                                         /*}}}*/
2191
2192 // ShowHelp - Show a help screen                                        /*{{{*/
2193 // ---------------------------------------------------------------------
2194 /* */
2195 bool ShowHelp(CommandLine &CmdL)
2196 {
2197    ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
2198             COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
2199             
2200    if (_config->FindB("version") == true)
2201    {
2202       cout << _("Supported Modules:") << endl;
2203       
2204       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
2205       {
2206          pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
2207          if (_system != 0 && _system->VS == VS)
2208             cout << '*';
2209          else
2210             cout << ' ';
2211          cout << "Ver: " << VS->Label << endl;
2212          
2213          /* Print out all the packaging systems that will work with 
2214             this VS */
2215          for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
2216          {
2217             pkgSystem *Sys = pkgSystem::GlobalList[J];
2218             if (_system == Sys)
2219                cout << '*';
2220             else
2221                cout << ' ';
2222             if (Sys->VS->TestCompatibility(*VS) == true)
2223                cout << "Pkg:  " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2224          }
2225       }
2226       
2227       for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2228       {
2229          pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2230          cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2231       }      
2232       
2233       for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2234       {
2235          pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2236          cout << " Idx: " << Type->Label << endl;
2237       }      
2238       
2239       return true;
2240    }
2241    
2242    cout << 
2243     _("Usage: apt-get [options] command\n"
2244       "       apt-get [options] install|remove pkg1 [pkg2 ...]\n"
2245       "       apt-get [options] source pkg1 [pkg2 ...]\n"
2246       "\n"
2247       "apt-get is a simple command line interface for downloading and\n"
2248       "installing packages. The most frequently used commands are update\n"
2249       "and install.\n"   
2250       "\n"
2251       "Commands:\n"
2252       "   update - Retrieve new lists of packages\n"
2253       "   upgrade - Perform an upgrade\n"
2254 // CNC:2003-02-20 - Use .rpm extension in documentation.
2255       "   install - Install new packages (pkg is libc6 not libc6.rpm)\n"
2256       "   remove - Remove packages\n"
2257       "   source - Download source archives\n"
2258       "   build-dep - Configure build-dependencies for source packages\n"
2259       "   dist-upgrade - Distribution upgrade, see apt-get(8)\n"
2260 // CNC:2002-08-01
2261 //      "   dselect-upgrade - Follow dselect selections\n"
2262       "   clean - Erase downloaded archive files\n"
2263       "   autoclean - Erase old downloaded archive files\n"
2264       "   check - Verify that there are no broken dependencies\n"
2265 // CNC:2003-03-16
2266       );
2267 #ifdef WITH_LUA
2268       _lua->RunScripts("Scripts::AptGet::Help::Command");
2269 #endif
2270       cout << _(
2271       "\n"
2272       "Options:\n"
2273       "  -h  This help text.\n"
2274       "  -q  Loggable output - no progress indicator\n"
2275       "  -qq No output except for errors\n"
2276       "  -d  Download only - do NOT install or unpack archives\n"
2277       "  -s  No-act. Perform ordering simulation\n"
2278       "  -y  Assume Yes to all queries and do not prompt\n"
2279       "  -f  Attempt to continue if the integrity check fails\n"
2280       "  -m  Attempt to continue if archives are unlocatable\n"
2281       "  -u  Show a list of upgraded packages as well\n"
2282       "  -b  Build the source package after fetching it\n"
2283 // CNC:2002-08-02
2284       "  -D  When removing packages, remove dependencies as possible\n"
2285       "  -V  Show verbose version numbers\n"
2286       "  -c=? Read this configuration file\n"
2287       "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
2288       "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
2289       "pages for more information and options.\n"
2290       "                       This APT has Super Cow Powers.\n");
2291    return true;
2292 }
2293                                                                         /*}}}*/
2294 // GetInitialize - Initialize things for apt-get                        /*{{{*/
2295 // ---------------------------------------------------------------------
2296 /* */
2297 void GetInitialize()
2298 {
2299    _config->Set("quiet",0);
2300    _config->Set("help",false);
2301    _config->Set("APT::Get::Download-Only",false);
2302    _config->Set("APT::Get::Simulate",false);
2303    _config->Set("APT::Get::Assume-Yes",false);
2304    _config->Set("APT::Get::Fix-Broken",false);
2305    _config->Set("APT::Get::Force-Yes",false);
2306    _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
2307 }
2308                                                                         /*}}}*/
2309
2310 int main(int argc,const char *argv[])
2311 {
2312    CommandLine::Args Args[] = {
2313       {'h',"help","help",0},
2314       {'v',"version","version",0},
2315       {'V',"verbose-versions","APT::Get::Show-Versions",0},
2316       {'q',"quiet","quiet",CommandLine::IntLevel},
2317       {'q',"silent","quiet",CommandLine::IntLevel},
2318       {'d',"download-only","APT::Get::Download-Only",0},
2319       {'b',"compile","APT::Get::Compile",0},
2320       {'b',"build","APT::Get::Compile",0},
2321       {'s',"simulate","APT::Get::Simulate",0},
2322       {'s',"just-print","APT::Get::Simulate",0},
2323       {'s',"recon","APT::Get::Simulate",0},
2324       {'s',"dry-run","APT::Get::Simulate",0},
2325       {'s',"no-act","APT::Get::Simulate",0},
2326       {'y',"yes","APT::Get::Assume-Yes",0},
2327       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
2328       {'f',"fix-broken","APT::Get::Fix-Broken",0},
2329       {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
2330       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
2331       {'D',"remove-deps","APT::Remove-Depends",0}, // CNC:2002-08-01
2332       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
2333       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
2334       {0,"download","APT::Get::Download",0},
2335       {0,"fix-missing","APT::Get::Fix-Missing",0},
2336       {0,"ignore-hold","APT::Ignore-Hold",0},      
2337       {0,"upgrade","APT::Get::upgrade",0},
2338       {0,"force-yes","APT::Get::force-yes",0},
2339       {0,"print-uris","APT::Get::Print-URIs",0},
2340       {0,"purge","APT::Get::Purge",0},
2341       {0,"list-cleanup","APT::Get::List-Cleanup",0},
2342       {0,"reinstall","APT::Get::ReInstall",0},
2343       {0,"trivial-only","APT::Get::Trivial-Only",0},
2344       {0,"remove","APT::Get::Remove",0},
2345       {0,"only-source","APT::Get::Only-Source",0},
2346       {0,"arch-only","APT::Get::Arch-Only",0},
2347       {0,"check-only","APT::Get::Check-Only",0}, // CNC:2003-03-06
2348       {0,"root","RPM::RootDir",CommandLine::HasArg},
2349       {'c',"config-file",0,CommandLine::ConfigFile},
2350       {'o',"option",0,CommandLine::ArbItem},
2351       {0,0,0,0}};
2352    CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
2353                                    {"upgrade",&DoUpgrade},
2354                                    {"install",&DoInstall},
2355                                    // CNC:2004-03-22
2356                                    {"reinstall",&DoInstall},
2357                                    {"remove",&DoInstall},
2358                                    {"dist-upgrade",&DoDistUpgrade},
2359                                    {"dselect-upgrade",&DoDSelectUpgrade},
2360                                    {"build-dep",&DoBuildDep},
2361                                    {"clean",&DoClean},
2362                                    {"autoclean",&DoAutoClean},
2363                                    {"check",&DoCheck},
2364                                    {"source",&DoSource},
2365                                    {"moo",&DoMoo},
2366                                    {"help",&ShowHelp},
2367 // CNC:2003-03-19
2368 #ifdef WITH_LUA
2369                                    {"script",&DoScript},
2370 #endif
2371                                    {0,0}};
2372
2373    // Set up gettext support
2374    setlocale(LC_ALL,"");
2375    textdomain(PACKAGE);
2376
2377    // Parse the command line and initialize the package library
2378    CommandLine CmdL(Args,_config);
2379    if (pkgInitConfig(*_config) == false ||
2380        CmdL.Parse(argc,argv) == false ||
2381        pkgInitSystem(*_config,_system) == false)
2382    {
2383       if (_config->FindB("version") == true)
2384          ShowHelp(CmdL);
2385          
2386       _error->DumpErrors();
2387       return 100;
2388    }
2389
2390    // See if the help should be shown
2391    if (_config->FindB("help") == true ||
2392        _config->FindB("version") == true ||
2393        CmdL.FileSize() == 0)
2394    {
2395       ShowHelp(CmdL);
2396       return 0;
2397    }
2398    
2399    // CNC:2003-11-21
2400    if (CmdL.FileSize() > 1)
2401    {
2402       // CNC:2003-11-23
2403       vector<string> URLLst;
2404       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2405       {
2406          if (strstr(*I, "://") != NULL)
2407          {
2408             URLLst.push_back(*I);
2409             *I = strrchr(*I, '/')+1;
2410          }
2411       }
2412
2413       if (URLLst.empty() == false && DownloadPackages(URLLst) == false)
2414       {
2415             _error->DumpErrors();
2416             return 100;
2417       }
2418
2419       for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2420          _config->Set("APT::Arguments::", *I);
2421    }
2422
2423    // Deal with stdout not being a tty
2424    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
2425       _config->Set("quiet","1");
2426
2427    // Setup the output streams
2428    c0out.rdbuf(cout.rdbuf());
2429    c1out.rdbuf(cout.rdbuf());
2430    c2out.rdbuf(cout.rdbuf());
2431    if (_config->FindI("quiet",0) > 0)
2432       c0out.rdbuf(devnull.rdbuf());
2433    if (_config->FindI("quiet",0) > 1)
2434       c1out.rdbuf(devnull.rdbuf());
2435
2436    // Setup the signals
2437    signal(SIGPIPE,SIG_IGN);
2438    signal(SIGWINCH,SigWinch);
2439    SigWinch(0);
2440
2441 // CNC:2003-11-23
2442 #ifdef WITH_LUA
2443    AptGetLuaCache LuaCache;
2444    _lua->SetCacheControl(&LuaCache);
2445    
2446    double Consume = 0;
2447    if (argc > 1 && _lua->HasScripts("Scripts::AptGet::Command") == true)
2448    {
2449       _lua->SetGlobal("commit_ask", 1);
2450       _lua->SetGlobal("command_args", CmdL.FileList);
2451       _lua->SetGlobal("command_consume", 0.0);
2452       _lua->RunScripts("Scripts::AptGet::Command");
2453       Consume = _lua->GetGlobalNum("command_consume");
2454       double Ask = _lua->GetGlobalNum("commit_ask");
2455       _lua->ResetGlobals();
2456       _lua->ResetCaches();
2457
2458       if (Consume == 1 && LuaCache.Cache)
2459       {
2460          CacheFile &Cache = *LuaCache.Cache;
2461          if (CheckOnly(Cache) == false &&
2462              (*Cache).InstCount() > 0 || (*Cache).DelCount() > 0)
2463             InstallPackages(Cache, false, Ask);
2464       }
2465    }
2466
2467    if (Consume == 0)
2468 #endif
2469    // Match the operation
2470    CmdL.DispatchArg(Cmds);
2471
2472    // Print any errors or warnings found during parsing
2473    if (_error->empty() == false)
2474    {
2475       bool Errors = _error->PendingError();
2476       _error->DumpErrors();
2477       return Errors == true?100:0;
2478    }
2479    
2480    return 0;   
2481 }
2482
2483 // vim:sts=3:sw=3