]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
In SingleArch environments we don't need the arch "all" pseudo package
[apt.git] / cmdline / apt-get.cc
index d3972ad81b94b2fb4acd12ac6e13f15c3042a449..343226bc3f82954f33485cd0a753e6e4a9cf8f71 100644 (file)
@@ -227,6 +227,17 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList)
    return false;
 }
                                                                        /*}}}*/
+// ShowPkg - display a package name                                    /*{{{*/
+// ---------------------------------------------------------------------
+/* Displays the package name and maybe also the architecture
+   if it is not the main architecture */
+string ShowPkg(pkgCache::PkgIterator const Pkg) {
+       string p = Pkg.Name();
+       if (strcmp(Pkg.Arch(),"all") != 0 && _config->Find("APT::Architecture") != Pkg.Arch())
+               p.append(":").append(Pkg.Arch());
+       return p;
+}
+                                                                       /*}}}*/
 // ShowBroken - Debugging aide                                         /*{{{*/
 // ---------------------------------------------------------------------
 /* This prints out the names of all the packages that are broken along
@@ -258,8 +269,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 << " " << ShowPkg(I) << " :";
+      unsigned const Indent = ShowPkg(I).size() + 3;
       bool First = true;
       pkgCache::VerIterator Ver;
       
@@ -312,7 +323,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
               out << ' ' << End.DepType() << ": ";
            FirstOr = false;
            
-           out << Start.TargetPkg().Name();
+           out << ShowPkg(Start.TargetPkg());
         
            // Show a quick summary of the version requirements
            if (Start.TargetVer() != 0)
@@ -374,7 +385,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 += ShowPkg(I) + " ";
          VersionsList += string(Cache[I].CandVersion) + "\n";
       }
    }
@@ -396,10 +409,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 += ShowPkg(I) + "* ";
         else
-           List += string(I.Name()) + " ";
+           List += ShowPkg(I) + " ";
      
      VersionsList += string(Cache[I].CandVersion)+ "\n";
       }
@@ -424,7 +439,7 @@ void ShowKept(ostream &out,CacheFile &Cache)
          I->CurrentVer == 0 || Cache[I].Delete() == true)
         continue;
       
-      List += string(I.Name()) + " ";
+      List += ShowPkg(I) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
@@ -444,8 +459,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 += ShowPkg(I) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
@@ -465,8 +482,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 += ShowPkg(I) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
@@ -484,7 +503,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 += ShowPkg(I) + " ";
                 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
       }
    }
@@ -518,7 +537,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
         if (Added[I->ID] == false)
         {
            Added[I->ID] = true;
-           List += string(I.Name()) + " ";
+           List += ShowPkg(I) + " ";
         //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
         }
       }
@@ -566,6 +585,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
@@ -862,14 +884,21 @@ 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 ||
-                        unsigned(Stat.f_type) != RAMFS_MAGIC)
+         if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+             || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+             )
             return _error->Error(_("You don't have enough free space in %s."),
                 OutputDir.c_str());
       }
@@ -1046,17 +1075,42 @@ 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.Name(),Pkg.Name());
+        Pkg = Prov;
+      }
    }
-   
+
    // Handle the no-upgrade case
    if (_config->FindB("APT::Get::upgrade",true) == false &&
        Pkg->CurrentVer != 0)
@@ -1215,126 +1269,131 @@ 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 TmpSrc = Name;
-   string::size_type Slash = TmpSrc.rfind('=');
-
-   // honor default release
-   string DefRel = _config->Find("APT::Default-Release");
-   pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
-
-   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)
-   {
-      // 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++)
-      {
-        for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
-             VF++)
-        {
-           /* 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)) 
-           {
-              VerTag = Ver.VerStr();
-              break;
-           }
-        }
-      }
-   }
-
-   /* 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)
-      {
-        pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
-        if (Ver.end() == false)
-        {
-           pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
-           Src = Parse.SourcePkg();
-        }
-      }   
-   }
-
-   // 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)
-   {
-      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)
-      {
-        /* Don't want to fall through because we are doing exact version 
-           matching. */
-        if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
-           continue;
-        
-        Last = Parse;
-        Offset = Parse->Offset();
-        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 || Last->Jump(Offset) == false)
-      return 0;
-   
-   return Last;
+       string VerTag;
+       string DefRel = _config->Find("APT::Default-Release");
+       string TmpSrc = Name;
+       const size_t found = TmpSrc.find_last_of("/=");
+
+       // extract the version/release from the pkgname
+       if (found != string::npos) {
+               if (TmpSrc[found] == '/')
+                       DefRel = TmpSrc.substr(found+1);
+               else
+                       VerTag = TmpSrc.substr(found+1);
+               TmpSrc = TmpSrc.substr(0,found);
+       }
+
+       /* 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) {
+               if(VerTag.empty() == false || DefRel.empty() == 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++) {
+                               for (pkgCache::VerFileIterator VF = Ver.FileList();
+                                    VF.end() == false; VF++) {
+                                       /* 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;
+
+                                       // We match against a concrete version (or a part of this version)
+                                       if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)
+                                               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();
+                                               if (VerTag.empty() == true)
+                                                       VerTag = Parse.SourceVer();
+                                               break;
+                                       }
+                               }
+                       }
+                       if (Src.empty() == true) {
+                               if (VerTag.empty() == false)
+                                       _error->Warning(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+                               else
+                                       _error->Warning(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
+                               VerTag.clear();
+                               DefRel.clear();
+                       }
+               }
+               if (VerTag.empty() == true && DefRel.empty() == true) {
+                       // if we don't have a version or default release, use the CandidateVer to find the Source
+                       pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
+                       if (Ver.end() == false) {
+                               pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
+                               Src = Parse.SourcePkg();
+                               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;
+
+       /* Iterate over all of the hits, which includes the resulting
+          binary packages in the search */
+       pkgSrcRecords::Parser *Parse;
+       while (true) {
+               SrcRecs.Restart();
+               while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0) {
+                       const string Ver = Parse->Version();
+
+                       // Ignore all versions which doesn't fit
+                       if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.c_str(), VerTag.size()) != 0)
+                               continue;
+
+                       // 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;
+               }
+               if (Last != 0 || VerTag.empty() == true)
+                       break;
+               //if (VerTag.empty() == false && Last == 0)
+               _error->Warning(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+               VerTag.clear();
+       }
+
+       if (Last == 0 || Last->Jump(Offset) == false)
+               return 0;
+
+       return Last;
 }
                                                                        /*}}}*/
 // DoUpdate - Update the package lists                                 /*{{{*/
@@ -2195,14 +2254,21 @@ 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 || 
-           unsigned(Stat.f_type) != RAMFS_MAGIC) 
+       if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+           || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+           ) 
           return _error->Error(_("You don't have enough free space in %s"),
               OutputDir.c_str());
       }
@@ -2572,7 +2638,10 @@ bool DoBuildDep(CommandLine &CmdL)
       
       // Now we check the state of the packages,
       if (Cache->BrokenCount() != 0)
-         return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      {
+        ShowBroken(cout, Cache, false);
+        return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      }
    }
   
    if (InstallPackages(Cache, false, true) == false)
@@ -2752,6 +2821,7 @@ int main(int argc,const char *argv[])                                     /*{{{*/
       {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},