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