From: Julian Andres Klode <jak@debian.org>
Date: Wed, 21 Nov 2018 07:41:28 +0000
Subject: cnf-update-db: Add support for Contents files

---
 CommandNotFound/db/creator.py | 67 +++++++++++++++++++++++++++++++++++++++++--
 cnf-update-db                 |  2 +-
 data/50command-not-found      |  1 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/CommandNotFound/db/creator.py b/CommandNotFound/db/creator.py
index 75d01f1..08564f5 100755
--- a/CommandNotFound/db/creator.py
+++ b/CommandNotFound/db/creator.py
@@ -5,6 +5,7 @@ import json
 import logging
 import os
 import sqlite3
+import subprocess
 import sys
 import time
 
@@ -134,8 +135,15 @@ class DbCreator:
         return meta
     def _fill_commands(self, con):
         for f in self.files:
-            with open(f) as fp:
-                self._parse_single_commands_file(con, fp)
+            proc = None
+            if "Contents" in f:
+                proc = subprocess.Popen(["/usr/lib/apt/apt-helper", "cat-file", f], stdout=subprocess.PIPE)
+            with proc or open(f) as fp:
+                if "Contents" in f:
+                    self._parse_single_contents_file(con, f, fp.stdout)
+                    fp.stdout.close()
+                else:
+                    self._parse_single_commands_file(con, fp)
         self.stats["total_time"] = time.time() - self.stats["total_time"]
         logging.info("processed %i packages in %.2fs" % (
             self.stats["total"], self.stats["total_time"]))
@@ -223,10 +231,63 @@ class DbCreator:
                         pkg_id = self._insert_package(con, pkgname, version, component, priority)
                 with measure("sql_insert_cmd", self.stats):
                     self._insert_command(con, command, pkg_id)
+    def _parse_single_contents_file(self, con, f, fp):
+        # read header
+        suite=None      # FIXME
+
+        for l in fp:
+            l = l.decode("utf-8")
+            if not (l.startswith('usr/sbin') or l.startswith('usr/bin') or
+                    l.startswith('bin') or l.startswith('sbin')):
+                continue
+            try:
+                command, pkgnames = l.split(None, 1)
+            except ValueError:
+                continue
+
+            command = os.path.basename(command)
+		
+            for pkgname in pkgnames.split(','):
+                try:
+                    section, pkgname = pkgname.strip().rsplit('/', 1)
+                except ValueError:
+                    pkgname = pkgname.strip()
+                    section = "unknown"
+                if len(section.split('/')) == 2:
+                    component, section = section.split('/')
+                else:
+                    component = 'main'
+
+                # FIXME - Don't really know how.
+                version = None
+                # see if we have the command already
+                with measure("sql_already_db", self.stats):
+                    already_in_db=self._in_db(con, command, pkgname)
+                if already_in_db:
+                    # we found a version that is higher what we have
+                    # in the DB -> remove current, insert higher
+                    if False and apt_pkg.version_compare(version, already_in_db[2]) > 0:
+                        logging.debug("replacing exiting %s in DB (higher version)" % command)
+                        with measure("sql_delete_already_in_db", self.stats):
+                            self._delete_pkgid(con, already_in_db[0])
+                    else:
+                        logging.debug("skipping %s from %s (lower/same version)" % (command, suite))
+                        continue
+                logging.debug("adding %s from %s/%s (%s)" % (
+                    command, pkgname, version, suite))
+                # insert new data
+                with measure("sql_have_pkg", self.stats):
+                    pkg_id = self._get_pkgid(con, pkgname)
+                if not pkg_id:
+                    priority = component_priorities[component]
+                    with measure("sql_insert_pkg", self.stats):
+                        pkg_id = self._insert_package(con, pkgname, version, component, priority)
+                with measure("sql_insert_cmd", self.stats):
+                    self._insert_command(con, command, pkg_id)
 
 
 if __name__ == "__main__":
-    logging.basicConfig(level=logging.INFO)
+    logging.basicConfig(level=logging.DEBUG)
     if len(sys.argv) < 3:
         print("usage: %s <output-db-path> <files...>" % sys.argv[0])
         print(" e.g.: %s commands.db ./dists/*/*/*/Commands-*" % sys.argv[0])
diff --git a/cnf-update-db b/cnf-update-db
index 18cba1e..6f66e3d 100755
--- a/cnf-update-db
+++ b/cnf-update-db
@@ -20,7 +20,7 @@ if __name__ == "__main__":
         print("datbase directory %s not writable" % db)
         sys.exit(0)
 
-    command_files = glob.glob("/var/lib/apt/lists/*Commands-*")
+    command_files = glob.glob("/var/lib/apt/lists/*Contents*")
     if len(command_files) > 0:
         col = DbCreator(command_files)
         col.create(db)
diff --git a/data/50command-not-found b/data/50command-not-found
index 320662b..8a75a68 100644
--- a/data/50command-not-found
+++ b/data/50command-not-found
@@ -7,6 +7,7 @@ Acquire::IndexTargets {
         MetaKey "$(COMPONENT)/cnf/Commands-$(NATIVE_ARCHITECTURE)";
         ShortDescription "Commands-$(NATIVE_ARCHITECTURE)";
         Description "$(RELEASE)/$(COMPONENT) $(NATIVE_ARCHITECTURE) c-n-f Metadata";
+        DefaultEnabled "false";
     };
 };
 
