]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
move regex magic from apt-get to new FromRegEx method
[apt.git] / cmdline / apt-get.cc
index 4596c3d61f3a86a5a76c505d09a0d4c5a166a96f..1cffd67303d3bac0a41d3244f4faae62bf3f85c2 100644 (file)
@@ -40,7 +40,8 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
-    
+#include <apt-pkg/packageset.h>
+
 #include <config.h>
 #include <apti18n.h>
 
@@ -692,7 +693,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."));
@@ -811,20 +812,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;
@@ -1045,7 +1045,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
         return false;
       if (Res == pkgPackageManager::Completed)
-        return true;
+        break;
       
       // Reload the fetcher object and loop again for media swapping
       Fetcher.Shutdown();
@@ -1053,7 +1053,24 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
         return false;
       
       _system->Lock();
-   }   
+   }
+
+   std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
+   if (disappearedPkgs.empty() == true)
+      return true;
+
+   string disappear;
+   for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
+       d != disappearedPkgs.end(); ++d)
+      disappear.append(*d).append(" ");
+
+   ShowList(c1out, P_("The following package disappeared from your system as\n"
+       "all files have been overwritten by other packages:",
+       "The following packages disappeared from your system as\n"
+       "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
+   c0out << _("Note: This is done automatic and on purpose by dpkg.") << std::endl;
+
+   return true;
 }
                                                                        /*}}}*/
 // TryToInstall - Try to install a single package                      /*{{{*/
@@ -1109,7 +1126,17 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                  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)
@@ -1138,20 +1165,27 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                  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.FullName(true) << " " << I.OwnerVer().VerStr() <<
-                 _(" [Installed]") << endl;
-              else
-                 c1out << "  " << Pkg.FullName(true) << " " << 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
       {
@@ -1248,6 +1282,11 @@ bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
    }
    
    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;
 }
                                                                        /*}}}*/
@@ -1281,12 +1320,30 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
    {
       if(VerTag.empty() == false || DefRel.empty() == false) 
       {
+        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.end() == false; Ver++) 
+        for (pkgCache::VerIterator Ver = Pkg.VersionList();; Ver++)
         {
+           // 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++) 
            {
@@ -1299,10 +1356,6 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
                   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) ||
@@ -1313,10 +1366,9 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
                  // no SourcePkg name, so it is the "binary" name
                  if (Src.empty() == true)
                     Src = TmpSrc;
-                 // no Version, so we try the Version of the SourcePkg -
-                 // and after that the version of the binary package
-                 if (VerTag.empty() == true)
-                    VerTag = Parse.SourceVer();
+                 // 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;
@@ -1328,9 +1380,11 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
         if (Src.empty() == true) 
         {
            // Sources files have no codename information
-           if (VerTag.empty() == true && DefRel.empty() == false)
-              _error->Warning(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
-           DefRel.clear();
+           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;
+           }
         }
       }
       if (Src.empty() == true)
@@ -1380,7 +1434,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
         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)
+        if (VerTag.empty() == false &&
+            Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match
            continue;
 
         // Newer version or an exact match? Save the hit
@@ -1397,8 +1452,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
       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();
+      _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+      return 0;
    }
 
    if (Last == 0 || Last->Jump(Offset) == false)
@@ -1420,23 +1475,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)
@@ -1730,48 +1781,24 @@ bool DoInstall(CommandLine &CmdL)
         Packages++;
         if (Pkg.end() == true)
         {
-           // Check if the name is a regex
-           const char *I;
-           for (I = S; *I != 0; I++)
-              if (*I == '?' || *I == '*' || *I == '|' ||
-                  *I == '[' || *I == '^' || *I == '$')
-                 break;
-           if (*I == 0)
+           APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out);
+           if (pkgset.empty() == true)
               return _error->Error(_("Couldn't find package %s"),S);
 
            // Regexs must always be confirmed
            ExpectedInst += 1000;
-        
-           // Compile the regex pattern
-           regex_t Pattern;
-           int Res;
-           if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
-                              REG_NOSUB)) != 0)
-           {
-              char Error[300];     
-              regerror(Res,&Pattern,Error,sizeof(Error));
-              return _error->Error(_("Regex compilation error - %s"),Error);
-           }
-        
-           // Run over the matches
+
            bool Hit = false;
-           for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
+           for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
            {
-              if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
-                 continue;
-           
-              ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
-                       Pkg.Name(),S);
-           
               if (VerTag != 0)
                  if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
                     return false;
-           
+
               Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
                                   ExpectedInst,false);
            }
-           regfree(&Pattern);
-        
+
            if (Hit == false)
               return _error->Error(_("Couldn't find package %s"),S);
         }
@@ -1790,6 +1817,7 @@ bool DoInstall(CommandLine &CmdL)
               Cache[Pkg].Install() == false && 
               (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
               _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"),
@@ -1805,7 +1833,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)."));
@@ -1899,9 +1927,10 @@ bool DoInstall(CommandLine &CmdL)
            {
               /* Skip if package is  installed already, or is about to be */
               string target = Start.TargetPkg().FullName(true) + " ";
-              
-              if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
-                  || Cache[Start.TargetPkg()].Install())
+              pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
+              if (TarPkg->SelectedState == pkgCache::State::Install ||
+                  TarPkg->SelectedState == pkgCache::State::Hold ||
+                  Cache[Start.TargetPkg()].Install())
               {
                  foundInstalledInOrGroup=true;
                  break;
@@ -1976,6 +2005,46 @@ bool DoInstall(CommandLine &CmdL)
 
    return InstallPackages(Cache,false);   
 }
+
+/* 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                            /*{{{*/
 // ---------------------------------------------------------------------
@@ -2184,13 +2253,23 @@ 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()];
    
    // insert all downloaded uris into this set to avoid downloading them
    // twice
    set<string> queued;
+
+   // Diff only mode only fetches .diff files
+   bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
+   // Tar only mode only fetches .tar files
+   bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
+   // Dsc only mode only fetches .dsc files
+   bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
+
    // Load the requestd sources into the fetcher
    unsigned J = 0;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
@@ -2217,21 +2296,17 @@ bool DoSource(CommandLine &CmdL)
            Dsc[J].Version = Last->Version();
            Dsc[J].Dsc = flNotDir(I->Path);
         }
-        
-        // Diff only mode only fetches .diff files
-        if (_config->FindB("APT::Get::Diff-Only",false) == true &&
-            I->Type != "diff")
-           continue;
-        
-        // Tar only mode only fetches .tar files
-        if (_config->FindB("APT::Get::Tar-Only",false) == true &&
-            I->Type != "tar")
-           continue;
 
-        // Dsc only mode only fetches .dsc files
-        if (_config->FindB("APT::Get::Dsc-Only",false) == true &&
-            I->Type != "dsc")
-           continue;
+        // Handle the only options so that multiple can be used at once
+        if (diffOnly == true || tarOnly == true || dscOnly == true)
+        {
+           if ((diffOnly == true && I->Type == "diff") ||
+               (tarOnly == true && I->Type == "tar") ||
+               (dscOnly == true && I->Type == "dsc"))
+               ; // Fine, we want this file downloaded
+           else
+              continue;
+        }
 
         // don't download the same uri twice (should this be moved to
         // the fetcher interface itself?)
@@ -2299,6 +2374,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;
    }
    
@@ -2309,6 +2385,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;
    }
    
@@ -2334,6 +2411,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;
    }
 
@@ -2342,6 +2420,7 @@ bool DoSource(CommandLine &CmdL)
    
    if (Process == 0)
    {
+      bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
       for (unsigned I = 0; I != J; I++)
       {
         string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
@@ -2354,7 +2433,7 @@ bool DoSource(CommandLine &CmdL)
 
         // See if the package is already unpacked
         struct stat Stat;
-        if (stat(Dir.c_str(),&Stat) == 0 &&
+        if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 &&
             S_ISDIR(Stat.st_mode) != 0)
         {
            ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
@@ -2395,7 +2474,8 @@ bool DoSource(CommandLine &CmdL)
       
       _exit(0);
    }
-   
+   delete[] Dsc;
+
    // Wait for the subprocess
    int Status = 0;
    while (waitpid(Process,&Status,0) != Process)
@@ -2437,7 +2517,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++)
@@ -2753,6 +2835,8 @@ 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"
       "\n"
       "Options:\n"
       "  -h  This help text.\n"
@@ -2831,6 +2915,7 @@ 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},
@@ -2858,6 +2943,8 @@ int main(int argc,const char *argv[])                                     /*{{{*/
                                    {"purge",&DoInstall},
                                   {"autoremove",&DoInstall},
                                   {"purge",&DoInstall},
+                                  {"markauto",&DoMarkAuto},
+                                  {"unmarkauto",&DoMarkAuto},
                                    {"dist-upgrade",&DoDistUpgrade},
                                    {"dselect-upgrade",&DoDSelectUpgrade},
                                   {"build-dep",&DoBuildDep},