Base squeleton for blueprinting script
This commit is contained in:
commit
ec9cf757fc
7
blueprinting.py
Normal file
7
blueprinting.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import pacman
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
packages = pacman.list_installed_packages()
|
||||||
|
config_files = pacman.list_modified_config_files()
|
138
pacman.py
Normal file
138
pacman.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PACKAGE_BASE_PATH = "/var/cache/pacman/pkg/"
|
||||||
|
ARCH = "x86_64"
|
||||||
|
|
||||||
|
|
||||||
|
def is_installed(package):
|
||||||
|
"""
|
||||||
|
Check whether the specified package is installed or not.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
subprocess.check_output(["pacman", "-Qs", package])
|
||||||
|
return True
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_from_package(file):
|
||||||
|
"""
|
||||||
|
Get the specified file from the corresponding package archive from pacman
|
||||||
|
cache.
|
||||||
|
|
||||||
|
Returns None and print an error message if unable to find the archive in the
|
||||||
|
pacman cache.
|
||||||
|
"""
|
||||||
|
# /var/cache/pacman/pkg/lvm2-2.02.116-1-x86_64.pkg.tar.xz
|
||||||
|
# Find the package
|
||||||
|
try:
|
||||||
|
pacman_raw = subprocess.check_output(["pacman", "-Qo", file])
|
||||||
|
pacman_raw = pacman_raw.decode("utf-8").strip()
|
||||||
|
package, version = pacman_raw.split(" ")[-2:]
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print("Unable to find a package owning file " + file + ".",
|
||||||
|
file=sys.stderr)
|
||||||
|
return None
|
||||||
|
# Remove leading / if present
|
||||||
|
file = file.lstrip("/")
|
||||||
|
# Get the path to the package
|
||||||
|
package_archive = package + "-" + version + "-" + ARCH + ".pkg.tar.xz"
|
||||||
|
package_path = PACKAGE_BASE_PATH + package_archive
|
||||||
|
# Untar the package file
|
||||||
|
try:
|
||||||
|
raw = subprocess.check_output(["bsdtar", "-xOf", package_path, file],
|
||||||
|
stderr=open(os.devnull, 'w'))
|
||||||
|
raw = raw.decode("utf-8")
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
try:
|
||||||
|
package_path = package_path.replace(ARCH, "any")
|
||||||
|
raw = subprocess.check_output(["bsdtar", "-xOf", package_path, file],
|
||||||
|
stderr=open(os.devnull, 'w'))
|
||||||
|
raw = raw.decode("utf-8")
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print("Unable to untar package archive " + package_path + ".",
|
||||||
|
file=sys.stderr)
|
||||||
|
return None
|
||||||
|
return raw
|
||||||
|
|
||||||
|
|
||||||
|
def list_packages_in_group(group):
|
||||||
|
"""
|
||||||
|
List all the packages member of a given group.
|
||||||
|
"""
|
||||||
|
pacman_raw = subprocess.check_output(["pacman", "-Sg", group])
|
||||||
|
pacman_raw = pacman_raw.decode("utf-8").strip()
|
||||||
|
return [i.split(" ")[1] for i in pacman_raw.split("\n")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def list_modified_config_files(packages=[]):
|
||||||
|
"""
|
||||||
|
List all the manually modified configuration files.
|
||||||
|
|
||||||
|
packages is an optionnal filtering list of packages. Defaults to [] which
|
||||||
|
means "all the packages".
|
||||||
|
|
||||||
|
Returns a dict with modified configuration files as keys and diffs as
|
||||||
|
values.
|
||||||
|
"""
|
||||||
|
pacman_raw = subprocess.check_output(["pacman", "-Qii"] + packages)
|
||||||
|
pacman_raw = pacman_raw.decode("utf-8").strip()
|
||||||
|
modified_list = [i.split("\t")[1]
|
||||||
|
for i in pacman_raw.split("\n")
|
||||||
|
if i.startswith("MODIFIED")]
|
||||||
|
modified_files = {}
|
||||||
|
for i in modified_list:
|
||||||
|
package_file = get_file_from_package(i)
|
||||||
|
with open(i, 'r') as fh:
|
||||||
|
fs_file = fh.read()
|
||||||
|
modified_files[i] = None
|
||||||
|
return modified_files
|
||||||
|
|
||||||
|
|
||||||
|
def list_installed_packages():
|
||||||
|
"""
|
||||||
|
List all the installed packages (native, not AUR).
|
||||||
|
|
||||||
|
If a group of packages is completely installed, those packages will be
|
||||||
|
replaced by the matching group name.
|
||||||
|
"""
|
||||||
|
# Get a list of all the explicitly installed packages
|
||||||
|
pacman_packages_raw = subprocess.check_output(["pacman", "-Qenq"])
|
||||||
|
pacman_packages_raw = pacman_packages_raw.decode("utf-8").strip()
|
||||||
|
packages_list = pacman_packages_raw.split("\n")
|
||||||
|
# Get a list of all the explicitly installed packages, part of a group
|
||||||
|
pacman_groups_raw = subprocess.check_output(["pacman", "-Qgenq"])
|
||||||
|
pacman_groups_raw = pacman_groups_raw.decode("utf-8").strip()
|
||||||
|
# Store the installed packages of each group
|
||||||
|
groups_packages = {}
|
||||||
|
for i in pacman_groups_raw.split("\n"):
|
||||||
|
group, package = i.split(" ")
|
||||||
|
if group in groups_packages:
|
||||||
|
groups_packages[group] += [package]
|
||||||
|
else:
|
||||||
|
groups_packages[group] = [package]
|
||||||
|
# Check if the whole group has been installed
|
||||||
|
for group in groups_packages:
|
||||||
|
# List of packages in the group not explicitly installed
|
||||||
|
diff = set(list_packages_in_group(group)).difference(
|
||||||
|
set(groups_packages[group]))
|
||||||
|
# Check that they are installed anyway
|
||||||
|
diff_are_all_installed = True
|
||||||
|
for package in diff:
|
||||||
|
if not is_installed(package):
|
||||||
|
diff_are_all_installed = False
|
||||||
|
break
|
||||||
|
if diff_are_all_installed:
|
||||||
|
# If the whole group has been installed, replace its packages in
|
||||||
|
# the packages list by itself
|
||||||
|
for package in groups_packages[group]:
|
||||||
|
try:
|
||||||
|
packages_list.remove(package)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
packages_list.append(group)
|
||||||
|
return packages_list
|
Loading…
Reference in New Issue
Block a user