Skip to content

Instantly share code, notes, and snippets.

@tobwen
Forked from huitseeker/mindeps.py
Last active April 8, 2023 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tobwen/f010b680f9920186aad1ac6d1f8882db to your computer and use it in GitHub Desktop.
Save tobwen/f010b680f9920186aad1ac6d1f8882db to your computer and use it in GitHub Desktop.
Minimizes a list of debian packages by removing those implied as dependencies of the others
#!/usr/bin/env python3
#######################################################################
# 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 2 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 #
# General Public License for more details. #
# #
# Written and (c) by Francois Garillot #
# Contact <francois@garillot.net> for comment & bug reports #
#######################################################################
import re
import sys
import subprocess
def getpipeoutput(cmds, *, quiet=False):
cmd_str = " | ".join(cmds)
if not quiet:
print(f">> {cmd_str}", end=" ")
sys.stdout.flush()
output = subprocess.check_output(cmd_str, shell=True).decode().rstrip("\n")
return output
def get_crazyformat_reqs(pack, dependtypes):
cmd = f"apt-cache depends {pack} 2> /dev/null"
folist = getpipeoutput([cmd], quiet=True).split("\n")
foreqs = {}
for req in dependtypes:
reqlist = [s for s in folist if req in s]
foreqs[req] = [s.rpartition(": ")[2].strip() for s in reqlist]
return foreqs
def get_saneformat_stg(pack):
cmd = f"apt-cache showpkg {pack} 2> /dev/null | grep -A 1 Dependencies | tail -n 1"
fostr = getpipeoutput([cmd], quiet=True)
fostr = fostr.partition(" - ")[2]
return re.sub(r"\s\(\d+\s.*?\)\s", " ", fostr).split()
def build_graph(vertexes):
wanted = {"Depends"}
fodepends = set()
for pack in vertexes:
crazydepends = get_crazyformat_reqs(pack, wanted)
sanedeps = set(get_saneformat_stg(pack))
for d in wanted:
sanedeps = sanedeps.intersection(set(crazydepends[d]))
fodepends |= sanedeps
packs = " ".join(fodepends)
cmd = f"apt-rdepends {packs} 2> /dev/null | grep -v Depends"
deps = getpipeoutput([cmd], quiet=True).split("\n")
newdeps = set(deps) & set(vertexes)
return list(newdeps)
def main(args):
implied = set(build_graph(args))
print(" ".join([x for x in args if x not in implied]))
if __name__ == "__main__":
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment