Created
October 10, 2023 19:23
-
-
Save ispanos/4e5dfeae98adccf71b42906c049d8abe to your computer and use it in GitHub Desktop.
dnf 'exclusively' installed packages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import re | |
import sys | |
def get_pks_repoquery(): | |
# Use repoquery to create a list of userinstalled packages | |
return set(subprocess.check_output( | |
'dnf repoquery --userinstalled --qf "%{name}"', shell=True, text=True | |
).splitlines()) | |
def line_to_packages(line): | |
_, command = line.split(':', 1) | |
command = command.strip() | |
arguments = command.split() | |
if "install" in arguments: | |
arguments.remove("install") | |
if "remove" in arguments: | |
arguments.remove("remove") | |
if "autoremove" in arguments: | |
arguments.remove("autoremove") | |
if "-y" in arguments: | |
arguments.remove("-y") | |
# remove flags from arguments | |
packages = [arg for arg in arguments if arg[0:2] != "--"] | |
return packages | |
def get_trans_dict(): | |
# Get the list of transaction IDs where packages were installed | |
transactions = subprocess.check_output( | |
"dnf history", shell=True, text=True | |
).splitlines() | |
transactions_dict = {} | |
# Ignore 1st transaction (made by anaconda?) | |
for transaction in transactions[1:]: | |
if re.match(r'^-+$', transaction) is not None: | |
continue | |
line = transaction.split('|') | |
id = int(line[0]) | |
date = line[2].strip() | |
action = line[3].strip() | |
transactions_dict[id] = {'date': date, 'action': action} | |
return transactions_dict | |
def get_pkgs_in_trans(id): | |
transaction = subprocess.check_output( | |
f"dnf history info {id}", shell=True, text=True).splitlines() | |
for line in transaction: | |
if "User" in line and "System <unset>" in line: | |
# Special kinds of packages that | |
# are installed by "shadow" transactions. | |
return None | |
if "Command Line" in line: | |
if "--disablerepo=*" in line or "groupupdate" in line: | |
print(f"Transaction id: {id}", file=sys.stderr) | |
print("Ignoring the following dnf command:", file=sys.stderr) | |
print(line, file=sys.stderr) | |
return None | |
return line_to_packages(line) | |
def get_pkgs_from_history(): | |
transactions_dict = get_trans_dict() | |
installed_packages = set() | |
removed_packages = set() | |
for i in range(2, 1+max(transactions_dict.keys())): | |
if transactions_dict[i]['action'] not in ['Removed', 'Install']: | |
continue | |
packages = get_pkgs_in_trans(i) | |
if not packages: | |
continue | |
if transactions_dict[i]['action'] == 'Install': | |
installed_packages.update(packages) | |
if transactions_dict[i]['action'] == 'Removed': | |
for package in packages: | |
if package not in installed_packages: | |
removed_packages.update(packages) | |
else: | |
installed_packages.remove(package) | |
return installed_packages, removed_packages | |
installed_packages, removed_packages = get_pkgs_from_history() | |
# print("Installed packages:") | |
# for p in sorted(installed_packages): | |
# # print(f"- \"{p}\"") | |
# print(f"- {p}") | |
# print() | |
# print("Removed packages:") | |
# for p in removed_packages: | |
# print(f"- {p}") | |
print("\n"*2) | |
print("history + repoquery - their intesection") | |
for i in get_pks_repoquery().symmetric_difference(installed_packages): | |
print(i) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment