mirror of
https://github.com/archlinux/aur.git
synced 2026-03-14 23:16:48 +01:00
325 lines
12 KiB
Python
Executable file
325 lines
12 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
## CODE TAKEN FROM github:peakwinter/python-pacman
|
|
## DEPENDS ON python-requests, git, pacman-contrib, python
|
|
|
|
## yauri, the gayest AUR helper ever, all fitting into 1 file.
|
|
|
|
import requests
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import shlex
|
|
import colorama
|
|
|
|
VERSION = "1.1"
|
|
AUR_RPC_URL = f"https://aur.archlinux.org/rpc/?v=5"
|
|
SCRIPTDIR = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
lang_en_CA = {
|
|
"UPDATE_FAILED": "Updating in Pacman has failed.",
|
|
"START_AUR_UPDATE": "Beginning update of AUR packages.",
|
|
"NO_AUR_PACKAGES": "No AUR packages installed!",
|
|
"INSTALLING_AUR_UPDATES": "Installing updates from AUR...",
|
|
"PACKAGE_NOT_FOUND": "Package not found!",
|
|
"UP_TO_DATE": "AUR packages up to date!",
|
|
"REPOSITORY": "Repository",
|
|
"NAME": "Name",
|
|
"VERSION": "Version",
|
|
"DESCRIPTION": "Description",
|
|
"URL": "URL",
|
|
"LICENSES": "Licenses",
|
|
"OUTDATED": "Is outdated?",
|
|
"SUBMITTER": "Submitter",
|
|
"MAINTAINER": "Maintainer",
|
|
"MAKE_DEPENDS_ON": "Make depends on",
|
|
"DEPENDS_ON": "Depends on",
|
|
"OPT_DEPENDS": "Optionally depends",
|
|
"POPULARITY": "Popularity",
|
|
"DESC_PACKAGEMANAGER": "yauri, the gayest aur helper ever, all fitting into 1 file.",
|
|
"UPDATE_PACKAGES": "Update package(s)",
|
|
"INSTALL_PACKAGE": "Install package(s)",
|
|
"PACKAGES_TO_INSTALL": "Packages to install",
|
|
"REMOVE_PACKAGE": "Remove package(s)",
|
|
"PACKAGES_TO_REMOVE": "Packages to remove",
|
|
"SEARCH_PACKAGE": "Search for packages",
|
|
"PACKAGES_TO_SEARCH_FOR": "Packages to search for",
|
|
"INFO_PACKAGE": "Get info about a package",
|
|
"INFO_ABOUT_PACKAGES": "Package to get info about",
|
|
"AUTOREMOVE": "Remove orphaned packages.",
|
|
"CACHECLEAR": "Clear cache.",
|
|
"DISPLAY_VERSION_AND_EXIT": "Display version and exit.",
|
|
"AUR_PACKAGES_REMOVED": "Cached AUR packages removed."
|
|
}
|
|
|
|
languages = {
|
|
"en_CA": lang_en_CA
|
|
}
|
|
|
|
cur_lang: dict
|
|
|
|
## UTILITY FUNCTIONS
|
|
|
|
def load_language():
|
|
global cur_lang
|
|
lang_name = os.getenv("LANG")
|
|
if lang_name not in languages:
|
|
cur_lang = languages["en_CA"]
|
|
else:
|
|
cur_lang = languages[lang_name]
|
|
|
|
|
|
def get_installed_aur_packages():
|
|
"""Lists every package. (Not from official repos**)"""
|
|
aur_packages = list()
|
|
result = pacman("-Qm")
|
|
output = result["stdout"]
|
|
if result["code"] != 0:
|
|
return None
|
|
packages = output.splitlines()
|
|
nonstandard_packages = [pkg.split()[0] for pkg in packages]
|
|
for pkg in nonstandard_packages:
|
|
if is_aur(pkg):
|
|
aur_packages.append(pkg)
|
|
return aur_packages
|
|
|
|
def pacman(flags, pkgs=[], eflgs=[], sudo=False, interactive=False):
|
|
"""Subprocess wrapper, get all data"""
|
|
if not pkgs:
|
|
if sudo:
|
|
cmd = ["sudo", "pacman", "--noconfirm", flags]
|
|
else:
|
|
cmd = ["pacman", "--noconfirm", flags]
|
|
elif type(pkgs) == list:
|
|
if sudo:
|
|
cmd = ["sudo", "pacman", "--noconfirm", flags]
|
|
else:
|
|
cmd = ["pacman", "--noconfirm", flags]
|
|
cmd += [shlex.quote(s) for s in pkgs]
|
|
else:
|
|
if sudo:
|
|
cmd = ["sudo", "pacman", "--noconfirm", flags, pkgs]
|
|
else:
|
|
cmd = ["pacman", "--noconfirm", flags, pkgs]
|
|
if eflgs and any(eflgs):
|
|
eflgs = [x for x in eflgs if x]
|
|
cmd += eflgs
|
|
if interactive == False:
|
|
p = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
data = {"code": p.returncode, "stdout": p.stdout.decode(),
|
|
"stderr": p.stderr.decode()}
|
|
else:
|
|
p = subprocess.run(cmd)
|
|
data = {"code": p.returncode}
|
|
return data
|
|
|
|
def is_aur(package):
|
|
'''
|
|
Return True if the given package is an AUR package.
|
|
'''
|
|
response = requests.get(AUR_RPC_URL + "&type=search&arg=" + package)
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
if result['resultcount'] > 0:
|
|
return True
|
|
return False
|
|
|
|
def is_pacman(package):
|
|
# Run the pacman search command
|
|
result = subprocess.run(
|
|
['pacman', '-Si', package],
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## MAIN COMMANDLINE FUNCTIONS
|
|
|
|
def search(query):
|
|
"""
|
|
Searches for packages in the AUR and Pacman.
|
|
|
|
:param query: Search query
|
|
"""
|
|
# Search in the AUR
|
|
url = f"{AUR_RPC_URL}&type=search&arg={query}"
|
|
response = requests.get(url)
|
|
if response.status_code == 200:
|
|
aur_results = response.json().get('results', [])
|
|
else:
|
|
aur_results = None
|
|
|
|
# Pacman search
|
|
pacman_search = pacman("-Ss", query)
|
|
lines = pacman_search["stdout"].splitlines()
|
|
|
|
for result in aur_results:
|
|
lines.append(f"{colorama.Fore.BLUE}aur{colorama.Fore.RESET}/{result["Name"]} {result["Version"]}")
|
|
lines.append(f" {result["Description"]}")
|
|
|
|
for line in lines:
|
|
print(line)
|
|
|
|
def update():
|
|
output = pacman("-Syu", sudo=True, interactive=True)
|
|
output_Fy = pacman("-Fy", sudo=True, interactive=True)
|
|
if output["code"] != 0 or output_Fy["code"] != 0:
|
|
print(colorama.Fore.RED + cur_lang["UPDATE_FAILED"] + colorama.Fore.RESET)
|
|
exit(1)
|
|
return
|
|
|
|
print(cur_lang["START_AUR_UPDATE"])
|
|
installed_aur_packages = get_installed_aur_packages()
|
|
if installed_aur_packages == None:
|
|
print(cur_lang["NO_AUR_PACKAGES"])
|
|
exit(1)
|
|
return
|
|
|
|
aur_info_url = f"{AUR_RPC_URL}&type=info&arg[]="
|
|
for package in installed_aur_packages:
|
|
aur_info_url += f"{package}&arg[]="
|
|
response = requests.get(aur_info_url)
|
|
updates = []
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
for pkg in result['results']:
|
|
local_version = pacman('-Qm', pkg['Name'])["stdout"].split()[1]
|
|
if pkg['Version'] != local_version:
|
|
updates.append(pkg['Name'])
|
|
|
|
if updates != []:
|
|
print(cur_lang["INSTALLING_AUR_UPDATES"])
|
|
install(" ".join(updates))
|
|
else:
|
|
print(colorama.Fore.LIGHTGREEN_EX + cur_lang["UP_TO_DATE"] + colorama.Fore.RESET)
|
|
|
|
def install(package):
|
|
pacman_packages = list()
|
|
aur_packages = list()
|
|
list_of_pkg = shlex.split(package)
|
|
for pkg in list_of_pkg:
|
|
if is_pacman(pkg):
|
|
pacman_packages.append(pkg)
|
|
elif is_aur(pkg):
|
|
aur_packages.append(pkg)
|
|
else:
|
|
print(colorama.Fore.RED + cur_lang["PACKAGE_NOT_FOUND"] + colorama.Fore.RESET)
|
|
exit(1)
|
|
return
|
|
if len(pacman_packages) != 0:
|
|
pacman("-Sy", pacman_packages, sudo=True, interactive=True)
|
|
if len(aur_packages) != 0:
|
|
for aur_package in aur_packages:
|
|
if os.path.exists(os.path.expanduser(f"~/.cache/yauri/{aur_package}")):
|
|
# I don't wanna hear a word about it.
|
|
subprocess.run(shlex.split(f"rm -rf {os.path.expanduser(f"~/.cache/yauri/{aur_package}")}"))
|
|
subprocess.run(shlex.split(f"git clone https://aur.archlinux.org/{aur_package}.git {os.path.expanduser(f"~/.cache/yauri/{aur_package}")}"))
|
|
subprocess.run(shlex.split(f"makepkg -sCci"), cwd=os.path.expanduser(f"~/.cache/yauri/{aur_package}"))
|
|
else:
|
|
print(colorama.Fore.RED + cur_lang["PACKAGE_NOT_FOUND"] + colorama.Fore.RESET)
|
|
exit(1)
|
|
return
|
|
|
|
def remove(packages):
|
|
pacman("-Rc", shlex.split(packages), sudo=True)
|
|
|
|
def info(package):
|
|
if is_pacman(package):
|
|
pacman("-Si", package, interactive=True)
|
|
elif is_aur(package):
|
|
aur_info_url = f"{AUR_RPC_URL}&type=info&arg[]={package}"
|
|
response = requests.get(aur_info_url)
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
package_data = result["results"][0]
|
|
print(f"{cur_lang["REPOSITORY"]} : {colorama.Fore.BLUE}aur{colorama.Fore.RESET}")
|
|
print(f"{cur_lang["NAME"]} : {package}")
|
|
print(f"{cur_lang["VERSION"]} : {package_data["Version"] if "Version" in package_data else None}")
|
|
print(f"{cur_lang["DESCRIPTION"]} : {package_data["Description"] if "Description" in package_data else None}")
|
|
print(f"{cur_lang["URL"]} : {package_data["URL"] if "URL" in package_data else None}")
|
|
print(f"{cur_lang["LICENSES"]} : {package_data["License"] if "License" in package_data else None}")
|
|
print(f"{cur_lang["OUTDATED"]} : {package_data["OutOfDate"] if "OutOfDate" in package_data else None}")
|
|
print(f"{cur_lang["SUBMITTER"]} : {package_data["Submitter"] if "Submitter" in package_data else None}")
|
|
print(f"{cur_lang["MAINTAINER"]} : {package_data["Maintainer"] if "Maintainer" in package_data else None}")
|
|
print(f"{cur_lang["MAKE_DEPENDS_ON"]} : {package_data["MakeDepends"] if "MakeDepends" in package_data else None}")
|
|
print(f"{cur_lang["DEPENDS_ON"]} : {package_data["Depends"] if "Depends" in package_data else None}")
|
|
print(f"{cur_lang["OPT_DEPENDS"]} : {package_data["OptDepends"] if "OptDepends" in package_data else None}")
|
|
print(f"{cur_lang["POPULARITY"]} : {package_data["Popularity"] if "Popularity" in package_data else None}")
|
|
else:
|
|
print(colorama.Fore.RED + cur_lang["PACKAGE_NOT_FOUND"] + colorama.Fore.RESET)
|
|
|
|
def cacheclear():
|
|
os.system("bash -c 'sudo paccache -rk0'")
|
|
pkgs = os.listdir(f"{os.path.expanduser('~')}/.cache/yauri/")
|
|
for pkg in pkgs:
|
|
os.system(f"rm -rf {os.path.expanduser('~')}/.cache/yauri/{pkg}")
|
|
|
|
print(f"{len(pkgs)} {colorama.Fore.BLUE}{cur_lang["AUR_PACKAGES_REMOVED"]}{colorama.Fore.RESET}")
|
|
|
|
def main():
|
|
colorama.init()
|
|
load_language()
|
|
parser = argparse.ArgumentParser(description=cur_lang["DESC_PACKAGEMANAGER"])
|
|
parser.add_argument('-v', '--version', action='store_true', help=cur_lang["DISPLAY_VERSION_AND_EXIT"])
|
|
subparsers = parser.add_subparsers(dest='command', help='commands')
|
|
|
|
# Update command
|
|
subparsers.add_parser('update', help=cur_lang["UPDATE_PACKAGES"])
|
|
|
|
# Cacheclear command
|
|
subparsers.add_parser('clearcache', help=cur_lang["CACHECLEAR"])
|
|
|
|
# Install command
|
|
install_parser = subparsers.add_parser('install', help=cur_lang["INSTALL_PACKAGE"])
|
|
install_parser.add_argument('package', type=str, nargs="+", help=cur_lang["PACKAGES_TO_INSTALL"])
|
|
|
|
# Remove command
|
|
remove_parser = subparsers.add_parser('remove', help=cur_lang["REMOVE_PACKAGE"])
|
|
remove_parser.add_argument('package', type=str, nargs="+", help='PACKAGES_TO_REMOVE')
|
|
|
|
# Search command
|
|
search_parser = subparsers.add_parser('search', help=cur_lang["SEARCH_PACKAGE"])
|
|
search_parser.add_argument('package', type=str, help=cur_lang["PACKAGES_TO_SEARCH_FOR"])
|
|
|
|
# Info command
|
|
info_parser = subparsers.add_parser('info', help=cur_lang["INFO_PACKAGE"])
|
|
info_parser.add_argument('package', type=str, help=cur_lang["INFO_ABOUT_PACKAGES"])
|
|
|
|
# Autoremove command
|
|
auto_remove_parser = subparsers.add_parser('autoremove', help=cur_lang["AUTOREMOVE"])
|
|
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
if args.version:
|
|
print(VERSION)
|
|
exit(0)
|
|
if args.command == 'update':
|
|
update()
|
|
elif args.command == 'clearcache':
|
|
cacheclear()
|
|
elif args.command == 'install':
|
|
install(" ".join(args.package))
|
|
elif args.command == 'remove':
|
|
remove(args.package)
|
|
elif args.command == 'search':
|
|
search(args.package)
|
|
elif args.command == "info":
|
|
info(args.package)
|
|
elif args.command == "autoremove":
|
|
os.system("sudo pacman -Rns $(pacman -Qdtq)")
|
|
else:
|
|
parser.print_help()
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
if not os.path.exists(os.path.expanduser("~/.cache/yauri")):
|
|
os.mkdir(os.path.expanduser("~/.cache/yauri"))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|