Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 111 lines (98 sloc) 2.55 KB
#!/usr/bin/env python3
import sys
import os
import subprocess
import argparse
P = argparse.ArgumentParser(description="declarative apt")
P.add_argument("path", type=str, help="Path to requirements file")
P.add_argument("--act", default=False, action='store_true',
help="Actually do install and remove packages")
assert __name__ == "__main__"
TO_INSTALL = set()
TO_REMOVE = set()
DEB_LINES = set()
ALL_GREEN = True
def register(line):
if line.startswith("R "):
TO_REMOVE.add(line[2:])
elif line.startswith("DEB "):
DEB_LINES.add(line[4:])
else:
TO_INSTALL.add(line)
# Read configuration
ARGS = P.parse_args()
with open(ARGS.path) as fh:
for line in fh:
i = line.find("#")
if i >= 0:
line = line[:i]
if not line:
continue
register(line.strip())
# Should update sources?
_SOURCE_PATH="/etc/apt/sources.list.d/requirements.list"
deb_lines_current = set()
if os.path.exists(_SOURCE_PATH):
with open(_SOURCE_PATH) as fh:
for line in fh:
if not line.startswith("deb"):
continue
deb_lines_current.add(line[4:].strip())
if DEB_LINES.difference(deb_lines_current):
if ARGS.act:
with open(_SOURCE_PATH, "w") as fh:
for l in sorted(DEB_LINES):
fh.write("deb ")
fh.write(l)
fh.write("\n")
else:
print("For /etc/apt/sources.list.d/requirements.list")
for l in sorted(DEB_LINES):
print(l)
print()
def error(msg):
global ALL_GREEN
ALL_GREEN = False
print("Error:", msg)
both = TO_INSTALL.intersection(TO_REMOVE)
if both:
error("remove AND install? "+" ".join(both))
exit(1)
def precheck(pkgs, short_cmd, op):
op = op + " "
pkgs = " ".join(pkgs)
cmd = "apt-get %s -s -y %s" % (short_cmd, pkgs)
try:
output = subprocess.check_output(cmd.split())
except subprocess.CalledProcessError:
error(cmd)
return
for line in output.decode("utf8").split("\n"):
if line.startswith(op):
pkg = line.split()[1]
yield pkg
# Check removals
removals = set(precheck(TO_REMOVE, "remove", "Remv"))
for pkg in removals:
if pkg in TO_INSTALL:
error("Would remove '%s', which shall be installed" % pkg)
# Check installs
installs = set(precheck(TO_INSTALL, "install", "Inst"))
for pkg in installs:
if pkg in TO_REMOVE:
error("Would install '%s', which shall be removed" % pkg)
removals = removals.intersection(TO_REMOVE)
installs = installs.intersection(TO_INSTALL)
if ALL_GREEN:
if (removals):
cmd = "apt-get remove " + " ".join(removals)
print(cmd)
if ARGS.act:
os.system("sudo %s -y"%cmd)
if (installs):
cmd = "apt-get install " + " ".join(installs)
print(cmd)
if ARGS.act:
os.system("sudo %s -y "%cmd)
else:
exit(1)