summaryrefslogtreecommitdiff
path: root/extra/legacy
diff options
context:
space:
mode:
Diffstat (limited to 'extra/legacy')
-rwxr-xr-xextra/legacy/check-package-libraries.py193
1 files changed, 0 insertions, 193 deletions
diff --git a/extra/legacy/check-package-libraries.py b/extra/legacy/check-package-libraries.py
deleted file mode 100755
index bc2349b..0000000
--- a/extra/legacy/check-package-libraries.py
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2012 Michał Masłowski <mtjm@mtjm.eu>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-"""
-Check which libraries are provided or required by a package, store
-this in a database, update and list broken packages.
-
-Dependencies:
-
-- Python 3.2 or later with SQLite 3 support
-
-- ``bsdtar``
-
-- ``readelf``
-"""
-
-
-import os.path
-import re
-import sqlite3
-import subprocess
-import tempfile
-
-
-#: Regexp matching an interesting dynamic entry.
-_DYNAMIC = re.compile(r"^\s*[0-9a-fx]+"
- "\s*\((NEEDED|SONAME)\)[^:]*:\s*\[(.+)\]$")
-
-
-def make_db(path):
- """Make a new, empty, library database at *path*."""
- con = sqlite3.connect(path)
- con.executescript("""
-create table provided(
- library varchar not null,
- package varchar not null
-);
-create table used(
- library varchar not null,
- package varchar not null
-);
-""")
- con.close()
-
-
-def begin(database):
- """Connect to *database* and start a transaction."""
- con = sqlite3.connect(database)
- con.execute("begin exclusive")
- return con
-
-
-def add_provided(con, package, libraries):
- """Write that *package* provides *libraries*."""
- for library in libraries:
- con.execute("insert into provided (package, library) values (?,?)",
- (package, library))
-
-
-def add_used(con, package, libraries):
- """Write that *package* uses *libraries*."""
- for library in libraries:
- con.execute("insert into used (package, library) values (?,?)",
- (package, library))
-
-
-def remove_package(con, package):
- """Remove all entries for a package."""
- con.execute("delete from provided where package=?", (package,))
- con.execute("delete from used where package=?", (package,))
-
-
-def add_package(con, package):
- """Add entries from a named *package*."""
- # Extract to a temporary directory. This could be done more
- # efficiently, since there is no need to store more than one file
- # at once.
- with tempfile.TemporaryDirectory() as temp:
- tar = subprocess.Popen(("bsdtar", "xf", package, "-C", temp))
- tar.communicate()
- with open(os.path.join(temp, ".PKGINFO")) as pkginfo:
- for line in pkginfo:
- if line.startswith("pkgname ="):
- pkgname = line[len("pkgname ="):].strip()
- break
- # Don't list previously removed libraries.
- remove_package(con, pkgname)
- provided = set()
- used = set()
- # Search for ELFs.
- for dirname, dirnames, filenames in os.walk(temp):
- assert dirnames is not None # unused, avoid pylint warning
- for file_name in filenames:
- path = os.path.join(dirname, file_name)
- with open(path, "rb") as file_object:
- if file_object.read(4) != b"\177ELF":
- continue
- readelf = subprocess.Popen(("readelf", "-d", path),
- stdout=subprocess.PIPE)
- for line in readelf.communicate()[0].split(b"\n"):
- match = _DYNAMIC.match(line.decode("ascii"))
- if match:
- if match.group(1) == "SONAME":
- provided.add(match.group(2))
- elif match.group(1) == "NEEDED":
- used.add(match.group(2))
- else:
- raise AssertionError("unknown entry type "
- + match.group(1))
- add_provided(con, pkgname, provided)
- add_used(con, pkgname, used)
-
-
-def init(arguments):
- """Initialize."""
- make_db(arguments.database)
-
-
-def add(arguments):
- """Add packages."""
- con = begin(arguments.database)
- for package in arguments.packages:
- add_package(con, package)
- con.commit()
- con.close()
-
-
-def remove(arguments):
- """Remove packages."""
- con = begin(arguments.database)
- for package in arguments.packages:
- remove_package(con, package)
- con.commit()
- con.close()
-
-
-def check(arguments):
- """List broken packages."""
- con = begin(arguments.database)
- available = set(row[0] for row
- in con.execute("select library from provided"))
- for package, library in con.execute("select package, library from used"):
- if library not in available:
- print(package, "needs", library)
- con.close()
-
-
-def main():
- """Get arguments and run the command."""
- from argparse import ArgumentParser
- parser = ArgumentParser(prog="check-package-libraries.py",
- description="Check packages for "
- "provided/needed libraries")
- parser.add_argument("-d", "--database", type=str,
- help="Database file to use",
- default="package-libraries.sqlite")
- subparsers = parser.add_subparsers()
- subparser = subparsers.add_parser(name="init",
- help="initialize the database")
- subparser.set_defaults(command=init)
- subparser = subparsers.add_parser(name="add",
- help="add packages to database")
- subparser.add_argument("packages", nargs="+", type=str,
- help="package files to add")
- subparser.set_defaults(command=add)
- subparser = subparsers.add_parser(name="remove",
- help="remove packages from database")
- subparser.add_argument("packages", nargs="+", type=str,
- help="package names to remove")
- subparser.set_defaults(command=remove)
- subparser = subparsers.add_parser(name="check",
- help="list broken packages")
- subparser.set_defaults(command=check)
- arguments = parser.parse_args()
- arguments.command(arguments)
-
-
-if __name__ == "__main__":
- main()