diff options
author | David Kalnischkies <kalnischkies@gmail.com> | 2011-04-26 17:29:54 +0200 |
---|---|---|
committer | David Kalnischkies <kalnischkies@gmail.com> | 2011-04-26 17:29:54 +0200 |
commit | a09e4489c7bd097d051db44b5e3487963b7a36c0 (patch) | |
tree | c0baba7ef48ba50c2a67cf1127c47ee89601ed71 | |
parent | 254b8ebb92e82e0d7cf5aa1391bcfbbeb23d534e (diff) |
provide a 'dpkg --set-selections' wrapper to set/release holds
-rw-r--r-- | cmdline/apt-mark.cc | 116 | ||||
-rw-r--r-- | debian/changelog | 3 | ||||
-rw-r--r-- | doc/apt-mark.8.xml | 23 |
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> |