diff options
author | V3n3RiX <venerix@koprulu.sector> | 2024-02-26 13:02:07 +0000 |
---|---|---|
committer | V3n3RiX <venerix@koprulu.sector> | 2024-02-26 13:02:07 +0000 |
commit | 94c0bd2dfeb801087c7a03787a964b15b2a37bd8 (patch) | |
tree | 63a7276179e074609173b7c3a2540e2e290d0f26 /src/backend/autormpkgsrc.py | |
parent | 7d32051b5114160c66c354972f8a64a00d331c6c (diff) |
* extend https://bugs.redcorelinux.org/show_bug.cgi?id=143v6.2402.1
* improve the UX at package removal stage and orphan removal stage
* require double confirmation for a forced, unsafe removal of a package
Diffstat (limited to 'src/backend/autormpkgsrc.py')
-rw-r--r-- | src/backend/autormpkgsrc.py | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/src/backend/autormpkgsrc.py b/src/backend/autormpkgsrc.py index 3f0c852..d696757 100644 --- a/src/backend/autormpkgsrc.py +++ b/src/backend/autormpkgsrc.py @@ -1,8 +1,11 @@ #!/usr/bin/python3 import atexit +import fcntl import io +import os import signal +import selectors import subprocess import sys import sisyphus.checkenv @@ -11,6 +14,26 @@ import sisyphus.killemerge import sisyphus.syncdb +def set_nonblocking(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) + + +def spinner_animation(): + spinner = ['-', '\\', '|', '/'] + sel = selectors.DefaultSelector() + sel.register(sys.stdin, selectors.EVENT_READ) + + for _ in range(10): + for char in spinner: + sys.stdout.write('\b' + char) + sys.stdout.flush() + events = sel.select(timeout=0.1) + if events: + return + sys.stdout.write('\b') + + def sigint_handler(signal, frame): sys.exit(0) @@ -22,17 +45,46 @@ def start(gfx_ui=False): args = ['--quiet', '--depclean'] if sisyphus.checkenv.root() and not gfx_ui: - p_exe = subprocess.Popen(['emerge'] + args + ['--ask']) - try: - p_exe.wait() - sisyphus.syncdb.lcl_tbl() - except KeyboardInterrupt: - p_exe.terminate() - try: - p_exe.wait(1) - except subprocess.TimeoutExpired: - p_exe.kill() - sys.exit() + print("\n" + sisyphus.getclr.bright_white + "Orphaned, no longer needed packages are slated for" + sisyphus.getclr.reset + " " + + sisyphus.getclr.green + "'safe'" + sisyphus.getclr.reset + " " + sisyphus.getclr.bright_white + "removal." + sisyphus.getclr.reset + "\n") + while True: + user_input = input(sisyphus.getclr.bright_white + "Would you like to proceed?" + sisyphus.getclr.reset + " " + + "[" + sisyphus.getclr.bright_green + "Yes" + sisyphus.getclr.reset + "/" + sisyphus.getclr.bright_red + "No" + sisyphus.getclr.reset + "]" + " ") + if user_input.lower() in ['yes', 'y', '']: + p_exe = subprocess.Popen(['emerge'] + args) + try: + set_nonblocking(sys.stdout.fileno()) + spinner_animation() + + sel = selectors.DefaultSelector() + sel.register(sys.stdin, selectors.EVENT_READ) + + while True: + events = sel.select(timeout=0.1) + for key, mask in events: + if key.fileobj == sys.stdin: + line = sys.stdin.readline().strip() + if line.lower() == 'q': + sys.exit() + if p_exe.poll() is not None: + break + except KeyboardInterrupt: + p_exe.terminate() + try: + p_exe.wait(1) + except subprocess.TimeoutExpired: + p_exe.kill() + sys.exit() + finally: + p_exe.wait() + sisyphus.syncdb.lcl_tbl() + break + elif user_input.lower() in ['no', 'n']: + break + else: + print("\nSorry, response" + " " + "'" + + user_input + "'" + " " + "not understood.\n") + continue elif gfx_ui: p_exe = subprocess.Popen( ['emerge'] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |