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