From 01d309be051f18e173eef9273ae2bf34181a85b0 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 21 Aug 2022 23:28:11 -0400 Subject: fix installation issues and refactor some more --- README.md | 2 + hiccup.py | 170 ------------------------------------------------- pyproject.toml | 9 ++- src/hiccup/__init__.py | 14 ++++ src/hiccup/helpers.py | 117 ++++++++++++++++++++++++++++++++++ src/hiccup/hiccup.py | 44 +++++++++++++ 6 files changed, 181 insertions(+), 175 deletions(-) delete mode 100755 hiccup.py create mode 100644 src/hiccup/__init__.py create mode 100644 src/hiccup/helpers.py create mode 100644 src/hiccup/hiccup.py diff --git a/README.md b/README.md index ca377e4..401eb39 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,5 @@ hiccup only needs one command to install :) ```sh python setup.py install --user ``` + +or you can use the [aur package](https://aur.archlinux.org/packages/hiccup-git) diff --git a/hiccup.py b/hiccup.py deleted file mode 100755 index b3f2120..0000000 --- a/hiccup.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import json -import subprocess # nosec:b404 -import os - -CONFIG_FILE = os.path.join(os.environ["XDG_CONFIG_HOME"], "hiccup/config.json") -OS_RELEASE_PATH = "/etc/os-release" - - -class DistroNotSupportedError(Exception): - def __init__(self, name): - self.message = "{} isn't supported yet".format(name) - super().__init__(self.message) - - -class Distro: - def __init__(self, id: str, config_file: os.path): - try: - # read and store commands from config file - with open(config_file) as file: - data = json.load(file) - self.__system_update_cmds = data["system_update_cmds"] - self.__extra_cmds = data["extra_cmds"] - self.__clean_cmds = data["clean_cmds"] - self.__shell_plugin_cmds = data["shell_plugin_cmds"] - self.__other_cmds = data["other_cmds"] - except OSError: - raise OSError("no config file found!") - except json.JSONDecodeError: - raise json.JSONDecodeError("unable to parse json") - - self.id = id - - # get commands specific to current distro - if self.is_supported(): - self.update_cmd = self.get_update_cmd() - if self.has_clean_cmd(): - self.clean_cmd = self.get_clean_cmd() - if self.has_extra_cmd(): - self.extra_cmd = self.get_extra_cmd() - else: - raise DistroNotSupportedError(self.id) - - def __get_cmd(self, dct: dict): - return dct[self.id] - - # wrapper for subprocess.run that allows for easy privlage escalation, - # silencing, and variable shells - def __sys_cmd(self, cmd: str, shell="bash", silent=False, sudo=False): - args = list() - if silent: - cmd += " > /dev/null 2>&1" - if sudo: - args += ["/usr/bin/sudo"] - - args += [shell, "-c", cmd] - - return subprocess.run(args, check=True) # nosec:B603 - - # iterate through dict of commands, optionally allow for keys to - # determine the shell the command is run though - def __run_items(self, msg: str, dct: dict, name_as_shell=False): - shell = "bash" - for name, cmd in dct.items(): - print(msg.format(name)) - - if name_as_shell: - shell = name - self.__sys_cmd(cmd, shell=shell, silent=True) # nosec:B604 - - def is_supported(self): - return self.id in self.__system_update_cmds - - def has_clean_cmd(self): - return self.id in self.__clean_cmds - - def has_extra_cmd(self): - return self.id in self.__extra_cmds - - def get_update_cmd(self): - return self.__get_cmd(self.__system_update_cmds) - - def get_extra_cmd(self): - return self.__get_cmd(self.__extra_cmds) - - def get_clean_cmd(self): - return self.__get_cmd(self.__clean_cmds) - - def update_system(self): - self.__sys_cmd(self.update_cmd, sudo=True) - if self.has_extra_cmd(): - self.__sys_cmd(self.extra_cmd) - - def cleanup_system(self): - if self.has_clean_cmd(): - print("cleaning up system...") - return self.__sys_cmd(self.clean_cmd, sudo=True) - print("no cleanup command found for {}".format(self.id)) - - def update_shell_plugins(self): - msg = "updating {} plugins..." - return self.__run_items(msg, self.__shell_plugin_cmds, name_as_shell=True) - - def update_other(self): - msg = "updating {}..." - return self.__run_items(msg, self.__other_cmds) - - def update_all(self): - self.update_system() - self.update_shell_plugins() - self.update_other() - self.cleanup_system() - - -# reads id from an os-release file -def get_distro_id(filename: os.path): - with open(filename) as file: - for line in file.readlines(): - k, v = line.strip().split("=") - if k == "ID": - return v - - -def run(): - try: - current_distro = get_distro_id(OS_RELEASE_PATH) - except DistroNotSupportedError: - pass - distro = Distro(current_distro, CONFIG_FILE) - - parser = argparse.ArgumentParser( - description="a python script to help keep you up to date" - ) - parser.add_argument( - "--cleanonly", - "-c", - action="store_true", - default=False, - dest="clean_only", - help="cleanup unneeded dependencies", - ) - parser.add_argument( - "--systemonly", - "-s", - action="store_true", - default=False, - dest="system_only", - help="only update through the system's package manager", - ) - args = parser.parse_args() - - if args.clean_only: - return distro.cleanup_system() - if args.system_only: - return distro.update_system() - - return distro.update_all() - - -if __name__ == "__main__": - if os.geteuid() == 0: - print("please don't run this as root :(") - exit(1) - try: - run() - print("done!") - except Exception as e: - print(repr(e)) - exit(2) diff --git a/pyproject.toml b/pyproject.toml index 2e79d63..f34ead3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,9 +23,8 @@ classifiers = [ "Bug Tracker" = "https://github.com/getchoo/hiccup/issues" [project.scripts] -hiccup = "hiccup:run" +hiccup = "hiccup:main" -[tool.hatch.build] -include = [ - "hiccup.py" -] \ No newline at end of file +[tool.setuptools] +package-dir = {"" = "src"} +packages = ["hiccup"] diff --git a/src/hiccup/__init__.py b/src/hiccup/__init__.py new file mode 100644 index 0000000..170fa57 --- /dev/null +++ b/src/hiccup/__init__.py @@ -0,0 +1,14 @@ +import os +from .hiccup import run + + +def main(): + if os.geteuid() == 0: + print("please don't run this as root :(") + exit(1) + try: + run() + print("done!") + except Exception as e: + print(repr(e)) + exit(2) diff --git a/src/hiccup/helpers.py b/src/hiccup/helpers.py new file mode 100644 index 0000000..541fae4 --- /dev/null +++ b/src/hiccup/helpers.py @@ -0,0 +1,117 @@ +import json +import subprocess # nosec:b404 + + +class DistroNotSupportedError(Exception): + def __init__(self, name): + self.message = "{} isn't supported yet".format(name) + super().__init__(self.message) + + +class DistroHelper: + def __init__(self, id: str, config_file: str): + try: + # read and store commands from config file + with open(config_file) as file: + data = json.load(file) + self.__system_update_cmds = data["system_update_cmds"] + self.__extra_cmds = data["extra_cmds"] + self.__clean_cmds = data["clean_cmds"] + self.__shell_plugin_cmds = data["shell_plugin_cmds"] + self.__other_cmds = data["other_cmds"] + except OSError: + raise OSError("no config file found!") + except json.JSONDecodeError: + pass + + self.id = id + + # get commands specific to current distro + if self.is_supported(): + self.update_cmd = self.get_update_cmd() + if self.has_clean_cmd(): + self.clean_cmd = self.get_clean_cmd() + if self.has_extra_cmd(): + self.extra_cmd = self.get_extra_cmd() + else: + raise DistroNotSupportedError(self.id) + + def __get_cmd(self, dct: dict): + return dct[self.id] + + # wrapper for subprocess.run that allows for easy privlage escalation, + # silencing, and variable shells + def __sys_cmd(self, cmd: str, shell="bash", silent=False, sudo=False): + args = list() + if silent: + cmd += " > /dev/null 2>&1" + if sudo: + args += ["/usr/bin/sudo"] + + args += [shell, "-c", cmd] + + return subprocess.run(args, check=True) # nosec:B603 + + # iterate through dict of commands, optionally allow for keys to + # determine the shell the command is run though + def __run_items(self, msg: str, dct: dict, name_as_shell=False): + shell = "bash" + for name, cmd in dct.items(): + print(msg.format(name)) + + if name_as_shell: + shell = name + self.__sys_cmd(cmd, shell=shell, silent=True) # nosec:B604 + + def is_supported(self): + return self.id in self.__system_update_cmds + + def has_clean_cmd(self): + return self.id in self.__clean_cmds + + def has_extra_cmd(self): + return self.id in self.__extra_cmds + + def get_update_cmd(self): + return self.__get_cmd(self.__system_update_cmds) + + def get_extra_cmd(self): + return self.__get_cmd(self.__extra_cmds) + + def get_clean_cmd(self): + return self.__get_cmd(self.__clean_cmds) + + def update_system(self): + self.__sys_cmd(self.update_cmd, sudo=True) + if self.has_extra_cmd(): + self.__sys_cmd(self.extra_cmd) + + def cleanup_system(self): + if self.has_clean_cmd(): + print("cleaning up system...") + return self.__sys_cmd(self.clean_cmd, sudo=True) + print("no cleanup command found for {}".format(self.id)) + + def update_shell_plugins(self): + msg = "updating {} plugins..." + return self.__run_items(msg, self.__shell_plugin_cmds, name_as_shell=True) + + def update_other(self): + msg = "updating {}..." + return self.__run_items(msg, self.__other_cmds) + + def update_all(self): + self.update_system() + self.update_shell_plugins() + self.update_other() + self.cleanup_system() + + +# reads id from an os-release file +def get_distro_id(filename: str): + with open(filename) as file: + for line in file.readlines(): + k, v = line.strip().split("=") + if k == "ID": + return v + return "" diff --git a/src/hiccup/hiccup.py b/src/hiccup/hiccup.py new file mode 100644 index 0000000..3ba89cd --- /dev/null +++ b/src/hiccup/hiccup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import argparse +import os +from .helpers import DistroHelper, DistroNotSupportedError, get_distro_id + + +def run(): + CONFIG_FILE = os.path.join(os.environ["XDG_CONFIG_HOME"], "hiccup/config.json") + OS_RELEASE_PATH = "/etc/os-release" + + current_distro = str() + try: + current_distro = get_distro_id(OS_RELEASE_PATH) + except DistroNotSupportedError: + pass + distro = DistroHelper(current_distro, CONFIG_FILE) + + parser = argparse.ArgumentParser( + description="a python script to help keep you up to date" + ) + parser.add_argument( + "--cleanonly", + "-c", + action="store_true", + default=False, + dest="clean_only", + help="cleanup unneeded dependencies", + ) + parser.add_argument( + "--systemonly", + "-s", + action="store_true", + default=False, + dest="system_only", + help="only update through the system's package manager", + ) + args = parser.parse_args() + + if args.clean_only: + return distro.cleanup_system() + if args.system_only: + return distro.update_system() + + return distro.update_all() -- cgit v1.2.3