* cmdline/apt-mark.cc:
authorDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 21 Apr 2011 14:46:28 +0000 (16:46 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 21 Apr 2011 14:46:28 +0000 (16:46 +0200)
  - reimplement apt-mark in c++

cmdline/apt-mark [deleted file]
cmdline/apt-mark.cc [new file with mode: 0644]
cmdline/makefile
debian/apt.lintian-overrides [deleted file]
debian/changelog
test/integration/framework

diff --git a/cmdline/apt-mark b/cmdline/apt-mark
deleted file mode 100755 (executable)
index c64d435..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/python
-
-from optparse import OptionParser
-
-import sys
-import os.path
-    
-try:
-    import apt_pkg
-except ImportError:
-    print >> sys.stderr, "Error importing apt_pkg, is python-apt installed?"
-    sys.exit(1)
-    
-actions = { "markauto" : 1,
-            "unmarkauto": 0
-          }
-
-def show_automatic(filename):
-    if not os.path.exists(STATE_FILE):
-        return
-    auto = set()
-    tagfile = apt_pkg.TagFile(open(STATE_FILE))
-    for section in tagfile:
-        pkgname = section.get("Package")
-        autoInst = section.get("Auto-Installed")
-        if int(autoInst):
-            auto.add(pkgname)
-    print "\n".join(sorted(auto))
-    
-
-def mark_unmark_automatic(filename, action, pkgs):
-    " mark or unmark automatic flag"
-    # open the statefile
-    if os.path.exists(STATE_FILE):
-        try:
-            tagfile = apt_pkg.TagFile(open(STATE_FILE))
-            outfile = open(STATE_FILE+".tmp","w")
-        except IOError, msg:
-            print "%s, are you root?" % (msg)
-            sys.exit(1)
-        for section in tagfile:
-            pkgname = section.get("Package")
-            autoInst = section.get("Auto-Installed")
-            if pkgname in pkgs:
-                if options.verbose:
-                    print "changing %s to %s" % (pkgname,action)
-                newsec = apt_pkg.rewrite_section(section,
-                                       [],
-                                       [ ("Auto-Installed",str(action)) ])
-                pkgs.remove(pkgname)
-                outfile.write(newsec+"\n")
-            else:
-                outfile.write(str(section)+"\n")
-        if action == 1:
-            for pkgname in pkgs:
-                if options.verbose:
-                    print "changing %s to %s" % (pkgname,action)
-                outfile.write("Package: %s\nAuto-Installed: %d\n\n" % (pkgname, action))
-        # all done, rename the tmpfile
-        os.chmod(outfile.name, 0644)
-        os.rename(outfile.name, STATE_FILE)
-        os.chmod(STATE_FILE, 0644)
-
-
-if __name__ == "__main__":
-    apt_pkg.init()
-
-    # option parsing
-    parser = OptionParser()
-    parser.usage = "%prog [options] {markauto|unmarkauto} packages..."
-    parser.epilog = "apt-mark is deprecated, use apt-get markauto/unmarkauto."
-    parser.add_option("-f", "--file", action="store", type="string",
-                      dest="filename",
-                      help="read/write a different file")
-    parser.add_option("-v", "--verbose",
-                      action="store_true", dest="verbose", default=False,
-                      help="print verbose status messages to stdout")
-    (options, args) = parser.parse_args()
-
-    if not args:
-        parser.print_help()
-        sys.exit(1)
-
-    # get the state-file
-    if not options.filename:
-        STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states"
-    else:
-        STATE_FILE=options.filename
-
-    if len(args) == 0:
-        parser.error("first argument must be 'markauto', 'unmarkauto' or 'showauto'")
-
-    if args[0] == "showauto":
-        show_automatic(STATE_FILE)
-    else:
-        # get pkgs to change
-        if args[0] not in actions.keys():
-            parser.error("first argument must be 'markauto', 'unmarkauto' or 'showauto'")
-        pkgs = args[1:]
-        action = actions[args[0]]
-        mark_unmark_automatic(STATE_FILE, action, pkgs)
diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc
new file mode 100644 (file)
index 0000000..a5dc45a
--- /dev/null
@@ -0,0 +1,257 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+/* #####################################################################
+   apt-mark - show and change auto-installed bit information
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/cacheset.h>
+#include <apt-pkg/cmndline.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/strutl.h>
+
+#include <config.h>
+#include <apti18n.h>
+
+#include <algorithm>
+                                                                       /*}}}*/
+using namespace std;
+
+ostream c0out(0);
+ostream c1out(0);
+ostream c2out(0);
+ofstream devnull("/dev/null");
+/* DoAuto - mark packages as automatically/manually installed          {{{*/
+bool DoAuto(CommandLine &CmdL)
+{
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgDepCache *DepCache = CacheFile.GetDepCache();
+   if (unlikely(Cache == NULL || DepCache == NULL))
+      return false;
+
+   APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
+   if (pkgset.empty() == true)
+      return _error->Error(_("No packages found"));
+
+   bool MarkAuto = strcasecmp(CmdL.FileList[0],"auto") == 0;
+   int AutoMarkChanged = 0;
+
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   {
+      if (Pkg->CurrentVer == 0)
+      {
+        ioprintf(c1out,_("%s can not be marked as it is not installed.\n"), Pkg.FullName(true).c_str());
+        continue;
+      }
+      else if ((((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto)
+      {
+        if (MarkAuto == false)
+           ioprintf(c1out,_("%s was already set to manually installed.\n"), Pkg.FullName(true).c_str());
+        else
+           ioprintf(c1out,_("%s was already set to automatically installed.\n"), Pkg.FullName(true).c_str());
+        continue;
+      }
+
+      if (MarkAuto == false)
+        ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.FullName(true).c_str());
+      else
+        ioprintf(c1out,_("%s set to automatically installed.\n"), Pkg.FullName(true).c_str());
+
+      DepCache->MarkAuto(Pkg, MarkAuto);
+      ++AutoMarkChanged;
+   }
+   if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false)
+      return DepCache->writeStateFile(NULL);
+   return true;
+}
+                                                                       /*}}}*/
+/* DoMarkAuto - mark packages as automatically/manually installed      {{{*/
+/* Does the same as DoAuto but tries to do it exactly the same why as
+   the python implementation did it so it can be a drop-in replacement */
+bool DoMarkAuto(CommandLine &CmdL)
+{
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgDepCache *DepCache = CacheFile.GetDepCache();
+   if (unlikely(Cache == NULL || DepCache == 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 MarkAuto = strcasecmp(CmdL.FileList[0],"markauto") == 0;
+   bool const Verbose = _config->FindB("APT::MarkAuto::Verbose", false);
+   int AutoMarkChanged = 0;
+
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   {
+      if (Pkg->CurrentVer == 0 ||
+         (((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto)
+        continue;
+
+      if (Verbose == true)
+        ioprintf(c1out, "changing %s to %d\n", Pkg.Name(), (MarkAuto == false) ? 0 : 1);
+
+      DepCache->MarkAuto(Pkg, MarkAuto);
+      ++AutoMarkChanged;
+   }
+   if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false)
+      return DepCache->writeStateFile(NULL);
+
+   _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
+
+   return true;
+}
+                                                                       /*}}}*/
+/* ShowAuto - show automatically installed packages (sorted)           {{{*/
+bool ShowAuto(CommandLine &CmdL)
+{
+   pkgCacheFile CacheFile;
+   pkgCache *Cache = CacheFile.GetPkgCache();
+   pkgDepCache *DepCache = CacheFile.GetDepCache();
+   if (unlikely(Cache == NULL || DepCache == NULL))
+      return false;
+
+   std::vector<string> packages;
+
+   bool const ShowAuto = strcasecmp(CmdL.FileList[0],"showauto") == 0;
+
+   if (CmdL.FileList[1] == 0)
+   {
+      packages.reserve(Cache->HeaderP->PackageCount / 3);
+      for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
+        if (P->CurrentVer != 0 &&
+            (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)
+           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->CurrentVer != 0 &&
+            (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)
+           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                                       /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool ShowHelp(CommandLine &CmdL)
+{
+   ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
+           COMMON_ARCH,__DATE__,__TIME__);
+
+   cout <<
+    _("Usage: apt-mark [options] {auto|manual} pkg1 [pkg2 ...]\n"
+      "\n"
+      "apt-mark is a simple command line interface for marking packages\n"
+      "as manual or automatical installed. It can also list marks.\n"
+      "\n"
+      "Commands:\n"
+      "   auto - Mark the given packages as automatically installed\n"
+      "   manual - Mark the given packages as manually installed\n"
+      "\n"
+      "Options:\n"
+      "  -h  This help text.\n"
+      "  -q  Loggable output - no progress indicator\n"
+      "  -qq No output except for errors\n"
+      "  -s  No-act. Just prints what would be done.\n"
+      "  -f  read/write auto/manual marking in the given file\n"
+      "  -c=? Read this configuration file\n"
+      "  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
+      "See the apt-mark(8) and apt.conf(5) manual pages for more information.")
+      << std::endl;
+   return true;
+}
+                                                                       /*}}}*/
+int main(int argc,const char *argv[])                                  /*{{{*/
+{
+   CommandLine::Args Args[] = {
+      {'h',"help","help",0},
+      {0,"version","version",0},
+      {'q',"quiet","quiet",CommandLine::IntLevel},
+      {'q',"silent","quiet",CommandLine::IntLevel},
+      {'v',"verbose","APT::MarkAuto::Verbose",0},
+      {'s',"simulate","APT::Mark::Simulate",0},
+      {'s',"just-print","APT::Mark::Simulate",0},
+      {'s',"recon","APT::Mark::Simulate",0},
+      {'s',"dry-run","APT::Mark::Simulate",0},
+      {'s',"no-act","APT::Mark::Simulate",0},
+      {'f',"file","Dir::State::extended_states",CommandLine::HasArg},
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0,0,0,0}};
+   CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
+                                  {"auto",&DoAuto},
+                                  {"manual",&DoAuto},
+                                  {"showauto",&ShowAuto},
+                                  {"showmanual",&ShowAuto},
+                                  // obsolete commands for compatibility
+                                  {"markauto", &DoMarkAuto},
+                                  {"unmarkauto", &DoMarkAuto},
+                                   {0,0}};
+
+   // Set up gettext support
+   setlocale(LC_ALL,"");
+   textdomain(PACKAGE);
+
+   // Parse the command line and initialize the package library
+   CommandLine CmdL(Args,_config);
+   if (pkgInitConfig(*_config) == false ||
+       CmdL.Parse(argc,argv) == false ||
+       pkgInitSystem(*_config,_system) == false)
+   {
+      if (_config->FindB("version") == true)
+        ShowHelp(CmdL);
+      _error->DumpErrors();
+      return 100;
+   }
+
+   // See if the help should be shown
+   if (_config->FindB("help") == true ||
+       _config->FindB("version") == true ||
+       CmdL.FileSize() == 0)
+   {
+      ShowHelp(CmdL);
+      return 0;
+   }
+
+   // Deal with stdout not being a tty
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
+      _config->Set("quiet","1");
+
+   // Setup the output streams
+   c0out.rdbuf(cout.rdbuf());
+   c1out.rdbuf(cout.rdbuf());
+   c2out.rdbuf(cout.rdbuf());
+   if (_config->FindI("quiet",0) > 0)
+      c0out.rdbuf(devnull.rdbuf());
+   if (_config->FindI("quiet",0) > 1)
+      c1out.rdbuf(devnull.rdbuf());
+
+   // Match the operation
+   CmdL.DispatchArg(Cmds);
+
+   // Print any errors or warnings found during parsing
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
+      _error->DumpErrors();
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
+}
+                                                                       /*}}}*/
index 917ccc9..e867dae 100644 (file)
@@ -54,10 +54,11 @@ TARGET=program
 include $(COPY_H)
 
 # The apt-mark program
-SOURCE=apt-mark
-TO=$(BIN)
-TARGET=program
-include $(COPY_H)
+PROGRAM=apt-mark
+SLIBS = -lapt-pkg $(INTLLIBS)
+LIB_MAKES = apt-pkg/makefile
+SOURCE = apt-mark.cc
+include $(PROGRAM_H)
 
 # The apt-report-mirror-failure program
 #SOURCE=apt-report-mirror-failure
diff --git a/debian/apt.lintian-overrides b/debian/apt.lintian-overrides
deleted file mode 100644 (file)
index 828b369..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# apt-mark is rarely used auxiliary script, we don't want to depend on
-# python-apt only for it. 
-apt binary: python-script-but-no-python-dep usr/bin/apt-mark
index 7626883..1658bd0 100644 (file)
@@ -19,12 +19,12 @@ apt (0.8.14.2) UNRELEASED; urgency=low
     - replace obsolete usleep with nanosleep
   * debian/apt{,-utils}.symbols:
     - update both experimental symbol-files to reflect 0.8.14 state
-  * debian/apt.lintian-overrides:
-    - update the missing-python-dep override to the lintian 2.5 way
   * debian/rules:
     - remove unused embedded jquery by doxygen from libapt-pkg-doc
+  * cmdline/apt-mark.cc:
+    - reimplement apt-mark in c++
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Tue, 19 Apr 2011 20:57:52 +0200
+ -- David Kalnischkies <kalnischkies@gmail.com>  Thu, 21 Apr 2011 16:43:16 +0200
 
 apt (0.8.14.1) unstable; urgency=low
 
index 50c5157..b257738 100644 (file)
@@ -695,7 +695,7 @@ testmarkedauto() {
                while [ -n "$1" ]; do echo "$1"; shift; done | sort > $COMPAREFILE
        else
                msgtest 'Test for correctly marked as auto-installed' 'no package'
-               echo > $COMPAREFILE
+               echo -n > $COMPAREFILE
        fi
        aptmark showauto 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail
 }