Просмотр исходного кода

provide a 'dpkg --set-selections' wrapper to set/release holds

David Kalnischkies лет назад: 15
Родитель
Сommit
a09e4489c7
3 измененных файлов с 141 добавлено и 1 удалено
  1. 116 0
      cmdline/apt-mark.cc
  2. 2 1
      debian/changelog
  3. 23 0
      doc/apt-mark.8.xml

+ 116 - 0
cmdline/apt-mark.cc

@@ -141,6 +141,115 @@ bool ShowAuto(CommandLine &CmdL)
 
 
    std::sort(packages.begin(), packages.end());
    std::sort(packages.begin(), packages.end());
 
 
+   for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I)
+      std::cout << *I << std::endl;
+
+   return true;
+}
+									/*}}}*/
+/* DoHold - mark packages as hold by dpkg				{{{*/
+bool DoHold(CommandLine &CmdL)
+{
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   if (pkgset.empty() == true)
+      return _error->Error(_("No packages found"));
+
+   bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
+
+   for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   {
+      if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
+      {
+	 if (MarkHold == true)
+	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
+	 else
+	    ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
+	 pkgset.erase(Pkg);
+	 continue;
+      }
+   }
+
+   if (pkgset.empty() == true)
+      return true;
+
+   if (_config->FindB("APT::Mark::Simulate", false) == true)
+   {
+      for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+      {
+	 if (MarkHold == false)
+	    ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
+	 else
+	    ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
+      }
+      return true;
+   }
+
+   string dpkgcall = _config->Find("Dir::Bin::dpkg", "dpkg");
+   std::vector<string> const dpkgoptions = _config->FindVector("DPkg::options");
+   for (std::vector<string>::const_iterator o = dpkgoptions.begin();
+	o != dpkgoptions.end(); ++o)
+      dpkgcall.append(" ").append(*o);
+   dpkgcall.append(" --set-selections");
+   FILE *dpkg = popen(dpkgcall.c_str(), "w");
+   if (dpkg == NULL)
+      return _error->Errno("DoHold", "fdopen on dpkg stdin failed");
+
+   for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   {
+      if (MarkHold == true)
+      {
+	 fprintf(dpkg, "%s hold\n", Pkg.FullName(true).c_str());
+	 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
+      }
+      else
+      {
+	 fprintf(dpkg, "%s install\n", Pkg.FullName(true).c_str());
+	 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
+      }
+   }
+
+   int const status = pclose(dpkg);
+   if (status == -1)
+      return _error->Errno("DoHold", "dpkg execution failed in the end");
+   if (WIFEXITED(status) == false || WEXITSTATUS(status) != 0)
+      return _error->Error(_("Executing dpkg failed. Are you root?"));
+   return true;
+}
+									/*}}}*/
+/* ShowHold - show packages set on hold in dpkg status			{{{*/
+bool ShowHold(CommandLine &CmdL)
+{
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   if (unlikely(Cache == NULL))
+      return false;
+
+   std::vector<string> packages;
+
+   if (CmdL.FileList[1] == 0)
+   {
+      packages.reserve(50); // how many holds are realistic? I hope just a few…
+      for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
+	 if (P->SelectedState == pkgCache::State::Hold)
+	    packages.push_back(P.FullName(true));
+   }
+   else
+   {
+      APT::CacheSetHelper helper(false); // do not show errors
+      APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
+      packages.reserve(pkgset.size());
+      for (APT::PackageSet::const_iterator P = pkgset.begin(); P != pkgset.end(); ++P)
+	 if (P->SelectedState == pkgCache::State::Hold)
+	    packages.push_back(P.FullName(true));
+   }
+
+   std::sort(packages.begin(), packages.end());
+
    for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I)
    for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I)
       std::cout << *I << std::endl;
       std::cout << *I << std::endl;
 
 
@@ -198,8 +307,15 @@ int main(int argc,const char *argv[])					/*{{{*/
    CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
    CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
 				   {"auto",&DoAuto},
 				   {"auto",&DoAuto},
 				   {"manual",&DoAuto},
 				   {"manual",&DoAuto},
+				   {"hold",&DoHold},
+				   {"unhold",&DoHold},
 				   {"showauto",&ShowAuto},
 				   {"showauto",&ShowAuto},
 				   {"showmanual",&ShowAuto},
 				   {"showmanual",&ShowAuto},
+				   {"showhold",&ShowHold},
+				   // be nice and forgive the typo
+				   {"showholds",&ShowHold},
+				   // be nice and forgive it as it is technical right
+				   {"install",&DoHold},
 				   // obsolete commands for compatibility
 				   // obsolete commands for compatibility
 				   {"markauto", &DoMarkAuto},
 				   {"markauto", &DoMarkAuto},
 				   {"unmarkauto", &DoMarkAuto},
 				   {"unmarkauto", &DoMarkAuto},

+ 2 - 1
debian/changelog

@@ -24,6 +24,7 @@ apt (0.8.14.2) UNRELEASED; urgency=low
   * cmdline/apt-mark.cc:
   * cmdline/apt-mark.cc:
     - reimplement apt-mark in c++
     - reimplement apt-mark in c++
     - provide a 'showmanual' command (Closes: #582791)
     - provide a 'showmanual' command (Closes: #582791)
+    - provide a 'dpkg --set-selections' wrapper to set/release holds
   * cmdline/apt-get.cc:
   * cmdline/apt-get.cc:
     - deprecate mostly undocumented 'markauto' in favor of 'apt-mark'
     - deprecate mostly undocumented 'markauto' in favor of 'apt-mark'
   * cmdline/apt-cache.cc:
   * cmdline/apt-cache.cc:
@@ -31,7 +32,7 @@ apt (0.8.14.2) UNRELEASED; urgency=low
   * apt-pkg/pkgcache.cc:
   * apt-pkg/pkgcache.cc:
     - really ignore :arch in FindPkg() in non-multiarch environment
     - really ignore :arch in FindPkg() in non-multiarch environment
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 25 Apr 2011 13:49:47 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Tue, 26 Apr 2011 17:29:14 +0200
 
 
 apt (0.8.14.1) unstable; urgency=low
 apt (0.8.14.1) unstable; urgency=low
 
 

+ 23 - 0
doc/apt-mark.8.xml

@@ -82,6 +82,22 @@
        </para></listitem>
        </para></listitem>
        </varlistentry>
        </varlistentry>
 
 
+       <varlistentry><term>hold</term>
+	 <listitem><para><literal>hold</literal> is used to mark a
+       package as hold back, which will prevent the package from being
+       automatically installed, upgraded or removed.
+       The command is only a wrapper around <command>dpkg --set-selections</command>
+       and the state is therefore maintained by &dpkg; and not effected
+       by the <option>--filename</option> option.
+       </para></listitem>
+       </varlistentry>
+
+       <varlistentry><term>unhold</term>
+	 <listitem><para><literal>unhold</literal> is used to cancel a
+       previously set hold on a package to allow all actions again.
+       </para></listitem>
+       </varlistentry>
+
        <varlistentry><term>showauto</term>
        <varlistentry><term>showauto</term>
 	 <listitem><para><literal>showauto</literal> is used to print a
 	 <listitem><para><literal>showauto</literal> is used to print a
      list of automatically installed packages with each package on a new line.
      list of automatically installed packages with each package on a new line.
@@ -97,6 +113,13 @@
        </para></listitem>
        </para></listitem>
        </varlistentry>
        </varlistentry>
 
 
+       <varlistentry><term>showhold</term>
+	 <listitem><para><literal>showhold</literal> is used to print a list
+     of packages on hold in the same way as for the other show commands.
+       </para></listitem>
+       </varlistentry>
+
+
      </variablelist>
      </variablelist>
  </refsect1>
  </refsect1>