cmdline/apt-get.cc: Add apt-get markauto, showauto and unmarkauto commands.
[ntk/apt.git] / cmdline / apt-get.cc
index 384953a..8f9faf1 100644 (file)
@@ -258,8 +258,8 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
       }
       
       // Print out each package and the failed dependencies
-      out <<"  " <<  I.Name() << ":";
-      unsigned Indent = strlen(I.Name()) + 3;
+      out << " " << I.FullName(true) << " :";
+      unsigned const Indent = I.FullName(true).size() + 3;
       bool First = true;
       pkgCache::VerIterator Ver;
       
@@ -312,7 +312,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
               out << ' ' << End.DepType() << ": ";
            FirstOr = false;
            
-           out << Start.TargetPkg().Name();
+           out << Start.TargetPkg().FullName(true);
         
            // Show a quick summary of the version requirements
            if (Start.TargetVer() != 0)
@@ -374,7 +374,9 @@ void ShowNew(ostream &out,CacheFile &Cache)
    {
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].NewInstall() == true) {
-         List += string(I.Name()) + " ";
+        if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+           continue;
+         List += I.FullName(true) + " ";
          VersionsList += string(Cache[I].CandVersion) + "\n";
       }
    }
@@ -396,10 +398,12 @@ void ShowDel(ostream &out,CacheFile &Cache)
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].Delete() == true)
       {
+        if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+           continue;
         if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
-           List += string(I.Name()) + "* ";
+           List += I.FullName(true) + "* ";
         else
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
      
      VersionsList += string(Cache[I].CandVersion)+ "\n";
       }
@@ -424,7 +428,7 @@ void ShowKept(ostream &out,CacheFile &Cache)
          I->CurrentVer == 0 || Cache[I].Delete() == true)
         continue;
       
-      List += string(I.Name()) + " ";
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
@@ -444,8 +448,10 @@ void ShowUpgraded(ostream &out,CacheFile &Cache)
       // Not interesting
       if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
         continue;
-      
-      List += string(I.Name()) + " ";
+      if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+        continue;
+
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
@@ -465,8 +471,10 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache)
       // Not interesting
       if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
         continue;
-      
-      List += string(I.Name()) + " ";
+      if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+        continue;
+
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
@@ -484,7 +492,7 @@ bool ShowHold(ostream &out,CacheFile &Cache)
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
           I->SelectedState == pkgCache::State::Hold) {
-         List += string(I.Name()) + " ";
+         List += I.FullName(true) + " ";
                 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
       }
    }
@@ -518,7 +526,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
         if (Added[I->ID] == false)
         {
            Added[I->ID] = true;
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
         //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
         }
       }
@@ -542,7 +550,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
            Added[P->ID] = true;
            
            char S[300];
-           snprintf(S,sizeof(S),_("%s (due to %s) "),P.Name(),I.Name());
+           snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
            List += S;
         //VersionsList += "\n"; ???
         }       
@@ -566,6 +574,9 @@ void Stats(ostream &out,pkgDepCache &Dep)
    unsigned long ReInstall = 0;
    for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
    {
+      if (pkgCache::VerIterator(Dep, Dep[I].CandidateVer).Pseudo() == true)
+        continue;
+
       if (Dep[I].NewInstall() == true)
         Install++;
       else
@@ -681,7 +692,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    }
    else
    {
-      c1out << _("You might want to run `apt-get -f install' to correct these.") << endl;
+      c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl;
       ShowBroken(c1out,*this,true);
 
       return _error->Error(_("Unmet dependencies. Try using -f."));
@@ -800,20 +811,19 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    pkgRecords Recs(Cache);
    if (_error->PendingError() == true)
       return false;
-   
-   // Lock the archive directory
-   FileFd Lock;
-   if (_config->FindB("Debug::NoLocking",false) == false &&
-       _config->FindB("APT::Get::Print-URIs") == false)
-   {
-      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-      if (_error->PendingError() == true)
-        return _error->Error(_("Unable to lock the download directory"));
-   }
-   
+
    // Create the download object
+   pkgAcquire Fetcher;
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   if (_config->FindB("APT::Get::Print-URIs", false) == true)
+   {
+      // force a hashsum for compatibility reasons
+      _config->CndSet("Acquire::ForceHash", "md5sum");
+      if (Fetcher.Setup(&Stat, "") == false)
+        return false;
+   }
+   else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
+      return false;
 
    // Read the source list
    pkgSourceList List;
@@ -862,10 +872,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    {
       struct statvfs Buf;
       string OutputDir = _config->FindDir("Dir::Cache::Archives");
-      if (statvfs(OutputDir.c_str(),&Buf) != 0)
-        return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-                             OutputDir.c_str());
-      if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+      if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+        if (errno == EOVERFLOW)
+           return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+                                OutputDir.c_str());
+        else
+           return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+                                OutputDir.c_str());
+      } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
       {
          struct statfs Stat;
          if (statfs(OutputDir.c_str(),&Stat) != 0
@@ -1049,27 +1063,62 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
                  unsigned int &ExpectedInst,bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available 
-      provides */
-   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
-       Pkg.ProvidesList()->NextProvides == 0)
+   /* This is a pure virtual package and there is a single available
+      candidate providing it. */
+   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
    {
-      pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
-      ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-              Tmp.Name(),Pkg.Name());
-      Pkg = Tmp;
+      pkgCache::PkgIterator Prov;
+      bool found_one = false;
+
+      for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++)
+      {
+        pkgCache::VerIterator const PVer = P.OwnerVer();
+        pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+        /* Ignore versions that are not a candidate. */
+        if (Cache[PPkg].CandidateVer != PVer)
+            continue;
+
+        if (found_one == false)
+        {
+           Prov = PPkg;
+           found_one = true;
+        }
+        else if (PPkg != Prov)
+        {
+           found_one = false; // we found at least two
+           break;
+        }
+      }
+
+      if (found_one == true)
+      {
+        ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
+                 Prov.FullName(true).c_str(),Pkg.FullName(true).c_str());
+        Pkg = Prov;
+      }
    }
-   
+
    // Handle the no-upgrade case
    if (_config->FindB("APT::Get::upgrade",true) == false &&
        Pkg->CurrentVer != 0)
    {
       if (AllowFail == true)
         ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+                 Pkg.FullName(true).c_str());
+      return true;
+   }
+
+   // Ignore request for install if package would be new
+   if (_config->FindB("APT::Get::Only-Upgrade", false) == true &&
+       Pkg->CurrentVer == 0)
+   {
+      if (AllowFail == true)
+        ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
                  Pkg.Name());
       return true;
    }
-   
+
    // Check if there is something at all to install
    pkgDepCache::StateCache &State = Cache[Pkg];
    if (Remove == true && Pkg->CurrentVer == 0)
@@ -1083,7 +1132,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
       if (AllowFail == false)
         return false;
       
-      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
+      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
       return true;
    }
    
@@ -1095,30 +1144,37 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
       if (Pkg->ProvidesList != 0)
       {
         ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
-                 Pkg.Name());
+                 Pkg.FullName(true).c_str());
         
         pkgCache::PrvIterator I = Pkg.ProvidesList();
+        unsigned short provider = 0;
         for (; I.end() == false; I++)
         {
            pkgCache::PkgIterator Pkg = I.OwnerPkg();
            
            if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
            {
+              c1out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
               if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
-                 c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
-                 _(" [Installed]") << endl;
-              else
-                 c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
-           }      
+                 c1out << _(" [Installed]");
+              c1out << endl;
+              ++provider;
+           }
         }
-        c1out << _("You should explicitly select one to install.") << endl;
+        // if we found no candidate which provide this package, show non-candidates
+        if (provider == 0)
+           for (I = Pkg.ProvidesList(); I.end() == false; I++)
+              c1out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
+               << _(" [Not candidate version]") << endl;
+        else
+           c1out << _("You should explicitly select one to install.") << endl;
       }
       else
       {
         ioprintf(c1out,
         _("Package %s is not available, but is referred to by another package.\n"
           "This may mean that the package is missing, has been obsoleted, or\n"
-           "is only available from another source\n"),Pkg.Name());
+           "is only available from another source\n"),Pkg.FullName(true).c_str());
         
         string List;
         string VersionsList;
@@ -1132,13 +1188,13 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
            if (Seen[Dep.ParentPkg()->ID] == true)
               continue;
            Seen[Dep.ParentPkg()->ID] = true;
-           List += string(Dep.ParentPkg().Name()) + " ";
+           List += Dep.ParentPkg().FullName(true) + " ";
         //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
         }          
         ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
       }
       
-      _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
+      _error->Error(_("Package %s has no installation candidate"),Pkg.FullName(true).c_str());
       return false;
    }
 
@@ -1159,7 +1215,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
       {
         if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
            ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
-                    Pkg.Name());
+                    Pkg.FullName(true).c_str());
         else
            Cache.SetReInstall(Pkg,true);
       }      
@@ -1167,7 +1223,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
       {
         if (AllowFail == true)
            ioprintf(c1out,_("%s is already the newest version.\n"),
-                    Pkg.Name());
+                    Pkg.FullName(true).c_str());
       }      
    }   
    else
@@ -1196,18 +1252,23 @@ bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
    {
       if (IsRel == true)
         return _error->Error(_("Release '%s' for '%s' was not found"),
-                             VerTag,Pkg.Name());
+                             VerTag,Pkg.FullName(true).c_str());
       return _error->Error(_("Version '%s' for '%s' was not found"),
-                          VerTag,Pkg.Name());
+                          VerTag,Pkg.FullName(true).c_str());
    }
    
    if (strcmp(VerTag,Ver.VerStr()) != 0)
    {
       ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
-              Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
+              Ver.VerStr(),Ver.RelStr().c_str(),Pkg.FullName(true).c_str());
    }
    
    Cache.SetCandidateVersion(Ver);
+
+   // Set the all package to the same candidate
+   if (Ver.Pseudo() == true)
+      Cache.SetCandidateVersion(Match.Find(Pkg.Group().FindPkg("all")));
+
    return true;
 }
                                                                        /*}}}*/
@@ -1218,125 +1279,168 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
                               pkgSrcRecords &SrcRecs,string &Src,
                               pkgDepCache &Cache)
 {
-   // We want to pull the version off the package specification..
    string VerTag;
+   string DefRel = _config->Find("APT::Default-Release");
    string TmpSrc = Name;
-   string::size_type Slash = TmpSrc.rfind('=');
 
-   // honor default release
-   string DefRel = _config->Find("APT::Default-Release");
-   pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   // extract the version/release from the pkgname
+   const size_t found = TmpSrc.find_last_of("/=");
+   if (found != string::npos) {
+      if (TmpSrc[found] == '/')
+        DefRel = TmpSrc.substr(found+1);
+      else
+        VerTag = TmpSrc.substr(found+1);
+      TmpSrc = TmpSrc.substr(0,found);
+   }
 
-   if (Slash != string::npos)
-   {
-      VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
-      TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
-   } 
-   else  if(!Pkg.end() && DefRel.empty() == false)
+   /* Lookup the version of the package we would install if we were to
+      install a version and determine the source package name, then look
+      in the archive for a source package of the same name. */
+   bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
+   const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   if (MatchSrcOnly == false && Pkg.end() == false) 
    {
-      // we have a default release, try to locate the pkg. we do it like
-      // this because GetCandidateVer() will not "downgrade", that means
-      // "apt-get source -t stable apt" won't work on a unstable system
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; 
-          Ver++)
+      if(VerTag.empty() == false || DefRel.empty() == false) 
       {
-        for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
-             VF++)
+        bool fuzzy = false;
+        // we have a default release, try to locate the pkg. we do it like
+        // this because GetCandidateVer() will not "downgrade", that means
+        // "apt-get source -t stable apt" won't work on a unstable system
+        for (pkgCache::VerIterator Ver = Pkg.VersionList();; Ver++)
         {
-           /* If this is the status file, and the current version is not the
-              version in the status file (ie it is not installed, or somesuch)
-              then it is not a candidate for installation, ever. This weeds
-              out bogus entries that may be due to config-file states, or
-              other. */
-           if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 
-               pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
-           continue;
-           
-           //std::cout << VF.File().Archive() << std::endl;
-           if(VF.File().Archive() && (VF.File().Archive() == DefRel)) 
+           // try first only exact matches, later fuzzy matches
+           if (Ver.end() == true)
+           {
+              if (fuzzy == true)
+                 break;
+              fuzzy = true;
+              Ver = Pkg.VersionList();
+              // exit right away from the Pkg.VersionList() loop if we
+              // don't have any versions
+              if (Ver.end() == true)
+                 break;
+           }
+           // We match against a concrete version (or a part of this version)
+           if (VerTag.empty() == false &&
+               (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
+               (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
+              continue;
+
+           for (pkgCache::VerFileIterator VF = Ver.FileList();
+                VF.end() == false; VF++) 
            {
-              VerTag = Ver.VerStr();
+              /* If this is the status file, and the current version is not the
+                 version in the status file (ie it is not installed, or somesuch)
+                 then it is not a candidate for installation, ever. This weeds
+                 out bogus entries that may be due to config-file states, or
+                 other. */
+              if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
+                  pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
+                 continue;
+
+              // or we match against a release
+              if(VerTag.empty() == false ||
+                 (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) ||
+                 (VF.File().Codename() != 0 && VF.File().Codename() == DefRel)) 
+              {
+                 pkgRecords::Parser &Parse = Recs.Lookup(VF);
+                 Src = Parse.SourcePkg();
+                 // no SourcePkg name, so it is the "binary" name
+                 if (Src.empty() == true)
+                    Src = TmpSrc;
+                 // the Version we have is possibly fuzzy or includes binUploads,
+                 // so we use the Version of the SourcePkg (empty if same as package)
+                 VerTag = Parse.SourceVer();
+                 if (VerTag.empty() == true)
+                    VerTag = Ver.VerStr();
+                 break;
+              }
+           }
+           if (Src.empty() == false)
               break;
+        }
+        if (Src.empty() == true) 
+        {
+           // Sources files have no codename information
+           if (VerTag.empty() == true && DefRel.empty() == false) 
+           {
+              _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
+              return 0;
            }
         }
       }
-   }
-
-   /* Lookup the version of the package we would install if we were to
-      install a version and determine the source package name, then look
-      in the archive for a source package of the same name. */
-   bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
-   if (MatchSrcOnly == false)
-   {
-      if (Pkg.end() == false)
+      if (Src.empty() == true)
       {
+        // if we don't have found a fitting package yet so we will
+        // choose a good candidate and proceed with that.
+        // Maybe we will find a source later on with the right VerTag
         pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
-        if (Ver.end() == false)
+        if (Ver.end() == false) 
         {
            pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
            Src = Parse.SourcePkg();
+           if (VerTag.empty() == true)
+              VerTag = Parse.SourceVer();
         }
-      }   
+      }
+   }
+
+   if (Src.empty() == true)
+      Src = TmpSrc;
+   else 
+   {
+      /* if we have a source pkg name, make sure to only search
+        for srcpkg names, otherwise apt gets confused if there
+        is a binary package "pkg1" and a source package "pkg1"
+        with the same name but that comes from different packages */
+      MatchSrcOnly = true;
+      if (Src != TmpSrc) 
+      {
+        ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
+      }
    }
 
    // The best hit
    pkgSrcRecords::Parser *Last = 0;
    unsigned long Offset = 0;
    string Version;
-   bool IsMatch = false;
 
-   // No source package name..
-   if (Src.empty() == true)
-      Src = TmpSrc;
-   else 
-      // if we have a source pkg name, make sure to only search
-      // for srcpkg names, otherwise apt gets confused if there
-      // is a binary package "pkg1" and a source package "pkg1"
-      // with the same name but that comes from different packages
-      MatchSrcOnly = true;
-   
-   // If we are matching by version then we need exact matches to be happy
-   if (VerTag.empty() == false)
-      IsMatch = true;
-   
    /* Iterate over all of the hits, which includes the resulting
       binary packages in the search */
    pkgSrcRecords::Parser *Parse;
-   SrcRecs.Restart();
-   while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
+   while (true) 
    {
-      string Ver = Parse->Version();
-
-      // show name mismatches
-      if (IsMatch == true && Parse->Package() != Src)       
-        ioprintf(c1out,  _("No source package '%s' picking '%s' instead\n"), Parse->Package().c_str(), Src.c_str());
-      
-      if (VerTag.empty() == false)
+      SrcRecs.Restart();
+      while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0) 
       {
-        /* Don't want to fall through because we are doing exact version 
-           matching. */
-        if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
+        const string Ver = Parse->Version();
+
+        // Ignore all versions which doesn't fit
+        if (VerTag.empty() == false &&
+            Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match
            continue;
-        
-        Last = Parse;
-        Offset = Parse->Offset();
-        break;
+
+        // Newer version or an exact match? Save the hit
+        if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) {
+           Last = Parse;
+           Offset = Parse->Offset();
+           Version = Ver;
+        }
+
+        // was the version check above an exact match? If so, we don't need to look further
+        if (VerTag.empty() == false && VerTag.size() == Ver.size())
+           break;
       }
-                                 
-      // Newer version or an exact match
-      if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 || 
-         (Parse->Package() == Src && IsMatch == false))
-      {
-        IsMatch = Parse->Package() == Src;
-        Last = Parse;
-        Offset = Parse->Offset();
-        Version = Ver;
-      }      
+      if (Last != 0 || VerTag.empty() == true)
+        break;
+      //if (VerTag.empty() == false && Last == 0)
+      _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+      return 0;
    }
-   
+
    if (Last == 0 || Last->Jump(Offset) == false)
       return 0;
-   
+
    return Last;
 }
                                                                        /*}}}*/
@@ -1353,23 +1457,19 @@ bool DoUpdate(CommandLine &CmdL)
    if (List.ReadMainList() == false)
       return false;
 
-   // Lock the list directory
-   FileFd Lock;
-   if (_config->FindB("Debug::NoLocking",false) == false)
-   {
-      Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
-      if (_error->PendingError() == true)
-        return _error->Error(_("Unable to lock the list directory"));
-   }
-   
    // Create the progress
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
       
    // Just print out the uris an exit if the --print-uris flag was used
    if (_config->FindB("APT::Get::Print-URIs") == true)
    {
+      // force a hashsum for compatibility reasons
+      _config->CndSet("Acquire::ForceHash", "md5sum");
+
       // get a fetcher
-      pkgAcquire Fetcher(&Stat);
+      pkgAcquire Fetcher;
+      if (Fetcher.Setup(&Stat) == false)
+        return false;
 
       // Populate it with the source selection and get all Indexes 
       // (GetAll=true)
@@ -1433,7 +1533,7 @@ bool DoAutomaticRemove(CacheFile &Cache)
       {
         if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
            if(Debug)
-              std::cout << "We could delete %s" <<  Pkg.Name() << std::endl;
+              std::cout << "We could delete %s" <<  Pkg.FullName(true).c_str() << std::endl;
 
         if (doAutoRemove)
         {
@@ -1448,12 +1548,11 @@ bool DoAutomaticRemove(CacheFile &Cache)
            // only show stuff in the list that is not yet marked for removal
            if(Cache[Pkg].Delete() == false) 
            {
+              ++autoRemoveCount;
               // we don't need to fill the strings if we don't need them
-              if (smallList == true)
-                 ++autoRemoveCount;
-              else
+              if (smallList == false)
               {
-                autoremovelist += string(Pkg.Name()) + " ";
+                autoremovelist += Pkg.FullName(true) + " ";
                 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
               }
            }
@@ -1464,9 +1563,12 @@ bool DoAutomaticRemove(CacheFile &Cache)
    if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
    {
       if (smallList == false)
-        ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+        ShowList(c1out, P_("The following package is automatically installed and is no longer required:",
+                 "The following packages were automatically installed and are no longer required:",
+                 autoRemoveCount), autoremovelist, autoremoveversions);
       else
-        ioprintf(c1out, _("%lu packages were automatically installed and are no longer required.\n"), autoRemoveCount);
+        ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
+                 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
    }
    // Now see if we had destroyed anything (if we had done anything)
@@ -1686,11 +1788,14 @@ bool DoInstall(CommandLine &CmdL)
         
            // Run over the matches
            bool Hit = false;
-           for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
+           for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp)
            {
-              if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
+              if (regexec(&Pattern,Grp.Name(),0,0,0) != 0)
                  continue;
-           
+              Pkg = Grp.FindPkg("native");
+              if (unlikely(Pkg.end() == true))
+                 continue;
+
               ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
                        Pkg.Name(),S);
            
@@ -1720,10 +1825,12 @@ bool DoInstall(CommandLine &CmdL)
            if(!Remove && 
               Cache[Pkg].Install() == false && 
               (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
-              _config->FindB("APT::Get::ReInstall",false) == false)
+              _config->FindB("APT::Get::ReInstall",false) == false &&
+              _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+              _config->FindB("APT::Get::Download-Only",false) == false)
            {
               ioprintf(c1out,_("%s set to manually installed.\n"),
-                       Pkg.Name());
+                       Pkg.FullName(true).c_str());
               Cache->MarkAuto(Pkg,false);
               AutoMarkChanged++;
            }
@@ -1735,7 +1842,7 @@ bool DoInstall(CommandLine &CmdL)
         packages */
       if (BrokenFix == true && Cache->BrokenCount() != 0)
       {
-        c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
+        c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl;
         ShowBroken(c1out,Cache,false);
 
         return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
@@ -1792,7 +1899,7 @@ bool DoInstall(CommandLine &CmdL)
                break;
         
         if (*J == 0) {
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
            VersionsList += string(Cache[I].CandVersion) + "\n";
         }
       }
@@ -1828,7 +1935,7 @@ bool DoInstall(CommandLine &CmdL)
            for(;;)
            {
               /* Skip if package is  installed already, or is about to be */
-              string target = string(Start.TargetPkg().Name()) + " ";
+              string target = Start.TargetPkg().FullName(true) + " ";
               
               if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
                   || Cache[Start.TargetPkg()].Install())
@@ -1906,6 +2013,60 @@ bool DoInstall(CommandLine &CmdL)
 
    return InstallPackages(Cache,false);   
 }
+
+/* show automatically installed packages. */
+bool DoShowAuto(CommandLine &CmdL)
+{
+   OpProgress progress;
+   pkgCacheFile Cache;
+   if (Cache.Open(progress, false) == false)
+      return false;
+
+   for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
+      if (Cache[P].Flags & pkgCache::Flag::Auto)
+          ioprintf(c1out,_("%s\n"), P.Name());
+   return true;
+}
+
+/* mark packages as automatically/manually installed. */
+bool DoMarkAuto(CommandLine &CmdL)
+{
+   bool Action = true;
+   int AutoMarkChanged = 0;
+   OpTextProgress progress;
+   CacheFile Cache;
+   if (Cache.Open() == false)
+      return false;
+
+   if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
+      Action = true;
+   else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
+      Action = false;
+
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      const char *S = *I;
+      // Locate the package
+      pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+      if (Pkg.end() == true) {
+         return _error->Error(_("Couldn't find package %s"),S);
+      }
+      else
+      {
+         if (!Action)
+            ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
+         else
+            ioprintf(c1out,_("%s set to automatically installed.\n"),
+                      Pkg.Name());
+
+         Cache->MarkAuto(Pkg,Action);
+         AutoMarkChanged++;
+      }
+   }
+   if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
+      return Cache->writeStateFile(NULL);
+   return false;
+}
                                                                        /*}}}*/
 // DoDistUpgrade - Automatic smart upgrader                            /*{{{*/
 // ---------------------------------------------------------------------
@@ -2114,7 +2275,9 @@ bool DoSource(CommandLine &CmdL)
 
    // Create the download object
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat) == false)
+      return false;
 
    DscFile *Dsc = new DscFile[CmdL.FileSize()];
    
@@ -2198,10 +2361,14 @@ bool DoSource(CommandLine &CmdL)
    // Check for enough free space
    struct statvfs Buf;
    string OutputDir = ".";
-   if (statvfs(OutputDir.c_str(),&Buf) != 0)
-      return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-                          OutputDir.c_str());
-   if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+   if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+      if (errno == EOVERFLOW)
+        return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+                               OutputDir.c_str());
+      else
+        return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+                               OutputDir.c_str());
+   } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
      {
        struct statfs Stat;
        if (statfs(OutputDir.c_str(),&Stat) != 0
@@ -2225,6 +2392,7 @@ bool DoSource(CommandLine &CmdL)
    {
       for (unsigned I = 0; I != J; I++)
         ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
+      delete[] Dsc;
       return true;
    }
    
@@ -2235,6 +2403,7 @@ bool DoSource(CommandLine &CmdL)
       for (; I != Fetcher.UriEnd(); I++)
         cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
               I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
+      delete[] Dsc;
       return true;
    }
    
@@ -2260,6 +2429,7 @@ bool DoSource(CommandLine &CmdL)
    if (_config->FindB("APT::Get::Download-only",false) == true)
    {
       c1out << _("Download complete and in download only mode") << endl;
+      delete[] Dsc;
       return true;
    }
 
@@ -2321,7 +2491,8 @@ bool DoSource(CommandLine &CmdL)
       
       _exit(0);
    }
-   
+   delete[] Dsc;
+
    // Wait for the subprocess
    int Status = 0;
    while (waitpid(Process,&Status,0) != Process)
@@ -2363,7 +2534,9 @@ bool DoBuildDep(CommandLine &CmdL)
 
    // Create the download object
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat) == false)
+      return false;
 
    unsigned J = 0;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
@@ -2375,7 +2548,7 @@ bool DoBuildDep(CommandLine &CmdL)
             
       // Process the build-dependencies
       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
-      if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
+      if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",true)) == false)
        return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
    
       // Also ensure that build-essential packages are present
@@ -2474,7 +2647,7 @@ bool DoBuildDep(CommandLine &CmdL)
             for (; Prv.end() != true; Prv++)
            {
                if (_config->FindB("Debug::BuildDeps",false) == true)
-                    cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
+                    cout << "  Checking provider " << Prv.OwnerPkg().FullName() << endl;
 
               if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
                  break;
@@ -2515,7 +2688,7 @@ bool DoBuildDep(CommandLine &CmdL)
                if (Prv.end() == false)
                {
                   if (_config->FindB("Debug::BuildDeps",false) == true)
-                     cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
+                     cout << "  Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
                   skipAlternatives = hasAlternatives;
                   continue;
                }
@@ -2540,7 +2713,7 @@ bool DoBuildDep(CommandLine &CmdL)
                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
                                        Last->BuildDepType((*D).Type),
                                        Src.c_str(),
-                                       Pkg.Name());
+                                       Pkg.FullName(true).c_str());
                }
             }
 
@@ -2589,7 +2762,6 @@ bool DoBuildDep(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
-
 // DoMoo - Never Ask, Never Tell                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -2680,6 +2852,9 @@ bool ShowHelp(CommandLine &CmdL)
       "   clean - Erase downloaded archive files\n"
       "   autoclean - Erase old downloaded archive files\n"
       "   check - Verify that there are no broken dependencies\n"
+      "   markauto - Mark the given packages as automatically installed\n"
+      "   unmarkauto - Mark the given packages as manually installed\n"
+      "   showauto - Display a list of automatically installed packages\n"
       "\n"
       "Options:\n"
       "  -h  This help text.\n"
@@ -2758,9 +2933,11 @@ int main(int argc,const char *argv[])                                    /*{{{*/
       {0,"fix-missing","APT::Get::Fix-Missing",0},
       {0,"ignore-hold","APT::Ignore-Hold",0},      
       {0,"upgrade","APT::Get::upgrade",0},
+      {0,"only-upgrade","APT::Get::Only-Upgrade",0},
       {0,"force-yes","APT::Get::force-yes",0},
       {0,"print-uris","APT::Get::Print-URIs",0},
       {0,"diff-only","APT::Get::Diff-Only",0},
+      {0,"debian-only","APT::Get::Diff-Only",0},
       {0,"tar-only","APT::Get::Tar-Only",0},
       {0,"dsc-only","APT::Get::Dsc-Only",0},
       {0,"purge","APT::Get::Purge",0},
@@ -2784,6 +2961,9 @@ int main(int argc,const char *argv[])                                     /*{{{*/
                                    {"purge",&DoInstall},
                                   {"autoremove",&DoInstall},
                                   {"purge",&DoInstall},
+                                  {"showauto",&DoShowAuto},
+                                  {"markauto",&DoMarkAuto},
+                                  {"unmarkauto",&DoMarkAuto},
                                    {"dist-upgrade",&DoDistUpgrade},
                                    {"dselect-upgrade",&DoDSelectUpgrade},
                                   {"build-dep",&DoBuildDep},