summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2011-04-26 17:29:54 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2011-04-26 17:29:54 +0200
commita09e4489c7bd097d051db44b5e3487963b7a36c0 (patch)
treec0baba7ef48ba50c2a67cf1127c47ee89601ed71
parent254b8ebb92e82e0d7cf5aa1391bcfbbeb23d534e (diff)
provide a 'dpkg --set-selections' wrapper to set/release holds
-rw-r--r--cmdline/apt-mark.cc116
-rw-r--r--debian/changelog3
-rw-r--r--doc/apt-mark.8.xml23
3 files changed, 141 insertions, 1 deletions
diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc
index a5dc45a10..b2c664979 100644
--- a/cmdline/apt-mark.cc
+++ b/cmdline/apt-mark.cc
@@ -147,6 +147,115 @@ bool ShowAuto(CommandLine &CmdL)
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)
+ std::cout << *I << std::endl;
+
+ return true;
+}
+ /*}}}*/
// ShowHelp - Show a help screen /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -198,8 +307,15 @@ int main(int argc,const char *argv[]) /*{{{*/
CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
{"auto",&DoAuto},
{"manual",&DoAuto},
+ {"hold",&DoHold},
+ {"unhold",&DoHold},
{"showauto",&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
{"markauto", &DoMarkAuto},
{"unmarkauto", &DoMarkAuto},
diff --git a/debian/changelog b/debian/changelog
index 58b6a289d..82037ea34 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -24,6 +24,7 @@ apt (0.8.14.2) UNRELEASED; urgency=low
* cmdline/apt-mark.cc:
- reimplement apt-mark in c++
- provide a 'showmanual' command (Closes: #582791)
+ - provide a 'dpkg --set-selections' wrapper to set/release holds
* cmdline/apt-get.cc:
- deprecate mostly undocumented 'markauto' in favor of 'apt-mark'
* cmdline/apt-cache.cc:
@@ -31,7 +32,7 @@ apt (0.8.14.2) UNRELEASED; urgency=low
* apt-pkg/pkgcache.cc:
- 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
diff --git a/doc/apt-mark.8.xml b/doc/apt-mark.8.xml
index 592a8b97d..01c8665dd 100644
--- a/doc/apt-mark.8.xml
+++ b/doc/apt-mark.8.xml
@@ -82,6 +82,22 @@
</para></listitem>
</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>
<listitem><para><literal>showauto</literal> is used to print a
list of automatically installed packages with each package on a new line.
@@ -97,6 +113,13 @@
</para></listitem>
</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>
</refsect1>