]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/depcache.cc
* cmdline/apt-mark:
[apt.git] / apt-pkg / depcache.cc
index 4e94881217dc7730f5301a706e531157f1741e41..7663d38814b16de97ad0a2fa62deb34edd6cee24 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <iostream>
 #include <sstream>    
+#include <set>
 
 #include <apti18n.h>    
 
@@ -180,28 +181,71 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)
 
 bool pkgDepCache::writeStateFile(OpProgress *prog)
 {
-   FileFd StateFile;
-   string state = _config->FindDir("Dir::State") + "extended_states";
-
    if(_config->FindB("Debug::pkgAutoRemove",false))
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 
-   if(!StateFile.Open(state, FileFd::WriteEmpty))
-      return _error->Error(_("Failed to write StateFile %s"),
+   FileFd StateFile;
+   string state = _config->FindDir("Dir::State") + "extended_states";
+   if(!StateFile.Open(state, FileFd::ReadOnly))
+      return _error->Error(_("Failed to open StateFile %s"),
                           state.c_str());
 
+   FILE *OutFile;
+   string outfile = state + ".tmp";
+   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
+      return _error->Error(_("Failed to write temporary StateFile %s"),
+                          outfile.c_str());
+
+   // first merge with the existing sections
+   pkgTagFile tagfile(&StateFile);
+   pkgTagSection section;
+   std::set<string> pkgs_seen;
+   const char *nullreorderlist[] = {0};
+   while(tagfile.Step(section)) {
+        string pkgname = section.FindS("Package");
+        // Silently ignore unknown packages and packages with no actual
+        // version.
+        pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+        if(pkg.end() || pkg.VersionList().end()) 
+           continue;
+        bool oldAuto = section.FindI("Auto-Installed");
+        bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
+        if(_config->FindB("Debug::pkgAutoRemove",false))
+           std::clog << "Update exisiting AutoInstall info: " 
+                     << pkg.Name() << std::endl;
+        TFRewriteData rewrite[2];
+        rewrite[0].Tag = "Auto-Installed";
+        rewrite[0].Rewrite = newAuto ? "1" : "0";
+        rewrite[0].NewTag = 0;
+        rewrite[1].Tag = 0;
+        TFRewrite(OutFile, section, nullreorderlist, rewrite);
+        fprintf(OutFile,"\n");
+        pkgs_seen.insert(pkgname);
+   }
+   
+   // then write the ones we have not seen yet
    std::ostringstream ostr;
-   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end();pkg++) {
-
+   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
       if(PkgState[pkg->ID].Flags & Flag::Auto) {
+        if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
+           if(_config->FindB("Debug::pkgAutoRemove",false))
+              std::clog << "Skipping already written " << pkg.Name() << std::endl;
+           continue;
+        }
         if(_config->FindB("Debug::pkgAutoRemove",false))
-           std::clog << "AutoInstall: " << pkg.Name() << std::endl;
+           std::clog << "Writing new AutoInstall: " 
+                     << pkg.Name() << std::endl;
         ostr.str(string(""));
         ostr << "Package: " << pkg.Name() 
              << "\nAuto-Installed: 1\n\n";
-        StateFile.Write(ostr.str().c_str(), ostr.str().size());
+        fprintf(OutFile,ostr.str().c_str());
+        fprintf(OutFile,"\n");
       }
    }
+
+   // move the outfile over the real file
+   rename(outfile.c_str(), state.c_str());
+
    return true;
 }