diff --git a/README.md b/README.md index 5a0fce4..2ade480 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # tarstall +Feature-rich package management for archives! + ![tarstall Terminal Interface](readme-images/terminal.png) ![tarstall GUI Interface](readme-images/gui.png) diff --git a/config.py b/config.py index 4168c16..f1030fb 100644 --- a/config.py +++ b/config.py @@ -22,8 +22,8 @@ ###VERSIONS### -version = "1.6.0" -prog_internal_version = 108 +version = "1.6.1" +prog_internal_version = 110 file_version = 17 ############# diff --git a/generic.py b/generic.py index 14387e1..acedfbb 100644 --- a/generic.py +++ b/generic.py @@ -171,6 +171,8 @@ def easy_get_action(options, replacements=[]): selector = selector.upper() gui_labels.append(option["gui-label"]) options_list.append(option["shorthand"]) + if config.mode == "gui": + selector = option["gui-label"] msg += "\n" + selector + " - " + option["description"] for replacement in replacements: msg = msg.replace(list(replacement.keys())[0], list(replacement.values())[0]) @@ -289,7 +291,7 @@ def progress(val, should_show=True): Updates a progress bar (if we have a GUI) as tarstall processes run Args: - val (int): Value to update the progress bar to. + val (int/float): Value to update the progress bar to. should_show (bool): If set to False, don't show the bar in CLI. Defaults to True. """ @@ -299,7 +301,7 @@ def progress(val, should_show=True): elif config.mode == "cli" and not config.verbose and should_show: try: columns = int(os.popen('stty size', 'r').read().split()[1]) - start_chars = "Progress: " + start_chars = "Progress ({}%): ".format(str(int(val))) end_chars = " " full_squares = int(val * 0.01 * (columns - len(start_chars) - len(end_chars))) empty_squares = columns - len(start_chars) - len(end_chars) - full_squares diff --git a/install_tarstall b/install_tarstall index 364d04b..4116e83 100755 --- a/install_tarstall +++ b/install_tarstall @@ -173,7 +173,9 @@ def setup(): # Pass control to tarstall status("Running tarstall installation") - run([sys.executable, "./tarstall_execs/tarstall", "-f"]) + if not run([sys.executable, "./tarstall_execs/tarstall", "-f"]): + status("Error installing tarstall! Please view the information above!!!") + sys.exit(1) # Removing tarstall setup directory try: diff --git a/prog_manage.py b/prog_manage.py index d9f5b8a..b4e83f1 100644 --- a/prog_manage.py +++ b/prog_manage.py @@ -37,6 +37,79 @@ c_out = DEVNULL +def wget_with_progress(url, start_percent, end_percent, show_progress=True): + """Wget with Progress. + + The wget version of git_clone_with_progress() + + Args: + url (str): URL to file to grab + start_percent (int): Where generic.progress() last was + end_percent (int): Where generic.progress() should end up + show_progress (bool, optional): Whether to show progress if not verbose. Defaults to True. + + Returns: + int: Exit code from wget + + """ + if config.verbose: + process = Popen(["wget", url]) + else: + process = Popen(["wget", url], stdout=PIPE, stderr=STDOUT) + if not config.verbose and show_progress: + while process.poll() is None: + p_status = process.stdout.readline().decode("utf-8") + try: + percent_complete = int(p_status[p_status.rfind("%")-2:p_status.rfind("%")].strip()) + if percent_complete > 0: + generic.progress(start_percent + ((end_percent - start_percent) * (percent_complete / 100))) + except (TypeError, ValueError): + pass + else: + process.wait() + return process.poll() + + +def git_clone_with_progress(url, start_percent, end_percent, branch=None): + """Performs a Git Clone with Progress. + + Args: + url (str): URL to git clone from + start_percent (int): Starting value for generic.progress() + end_percent (int): Ending value for generic.progress() + branch (str): If specified, use a custom branch to clone from. Defaults to None. + + Returns: + [int: Exit code from git + """ + command = ["git", "clone"] + if branch is not None: + command.append("--branch") + command.append(branch) + command.append(url) + if config.verbose: + err = call(command) + else: + command.append("--progress") + process = Popen(command, stderr=STDOUT, stdout=PIPE, universal_newlines=True) + multiplier = end_percent - start_percent + while process.poll() is None: + p_status = process.stdout.readline() + try: + percent_complete = int(p_status[p_status.rfind("%")-2:p_status.rfind("%")].strip()) + if percent_complete > 0: + if "Resolving deltas:" in p_status: + generic.progress(start_percent + int(multiplier * 0.6) + (int(multiplier * 0.4) * (percent_complete / 100))) + elif "Receiving objects:" in p_status: + generic.progress(start_percent + (int(multiplier * 0.6) * (percent_complete / 100))) + elif "Unpacking objects:" in p_status: + generic.progress(start_percent + (multiplier * (percent_complete / 100))) + except (TypeError, ValueError): + pass + err = process.poll() + return err + + def reinstall_deps(): """Reinstall Dependencies @@ -58,7 +131,7 @@ def reinstall_deps(): generic.progress(5) config.vprint("Obtaining tarstall installer...") url = "https://raw.githubusercontent.com/hammy3502/tarstall/{}/install_tarstall".format(config.db["version"]["branch"]) - err = call(["wget", url], stdout=c_out, stderr=c_out) + err = wget_with_progress(url, 5, 60) if err != 0: return "Wget error" generic.progress(60) @@ -92,7 +165,7 @@ def repair_db(): """Attempts to Repair Tarstall DB. WARNING: THIS SHOULD NOT BE USED UNLESS THE DATABASE CANNOT BE RECOVERED OTHERWISE - BECAUSE OF LIMITED KNOWLEDGE OF THE CODE ITSELF, THINGS SUCH AS PROGRAM TYPE HAVE TO BE ASSUMEDF + BECAUSE OF LIMITED KNOWLEDGE OF THE CODE ITSELF, THINGS SUCH AS PROGRAM TYPE HAVE TO BE ASSUMED THIS ONLY EXISTS AS A LAST RESORT OPTION!!!!!!! """ config.vprint("Attempting repair of database, things are going to get crazy!") @@ -203,22 +276,7 @@ def wget_program(program, show_progress=False, progress_modifier=1): generic.progress(10 / progress_modifier, show_progress) config.vprint("Downloading archive...") url = config.db["programs"][program]["update_url"] - if config.verbose: - process = Popen(["wget", url]) - else: - process = Popen(["wget", url], stdout=PIPE, stderr=STDOUT) - if not config.verbose: - while process.poll() is None: - p_status = process.stdout.readline().decode("utf-8") - try: - percent_complete = int(p_status[p_status.rfind("%")-2:p_status.rfind("%")].strip()) - if percent_complete > 0: - generic.progress((10 + (55 * (percent_complete / 100))) / progress_modifier, show_progress) - except (TypeError, ValueError): - pass - else: - process.wait() - err = process.poll() + err = wget_with_progress(url, 10 / progress_modifier, 65 / progress_modifier, show_progress=show_progress) if err != 0: return "Wget error" generic.progress(65 / progress_modifier, show_progress) @@ -521,18 +579,18 @@ def tarstall_startup(start_fts=False, del_lock=False, old_upgrade=False, force_f generic.progress(100) print("We're done! Continuing tarstall execution...") - if config.db == {}: - if force_fix: - pass - else: - return "DB Broken" - if start_fts: # Check if -f or --first is supplied return first_time_setup() if not(config.exists('~/.tarstall/tarstall_execs/tarstall')): # Make sure tarstall is installed return "Not installed" + if config.db == {}: + if force_fix: + pass + else: + return "DB Broken" + file_version = get_file_version('file') while config.get_version('file_version') > file_version: # Lingering upgrades check config.vprint("Upgrading files and database from {} to {}.".format(file_version, config.get_version("file_version"))) @@ -863,7 +921,7 @@ def create_desktop(program_internal_name, name, program_file, comment="", should desktop_name = name path = config.full(path) if config.exists("~/.local/share/applications/{}.desktop".format(desktop_name)): - print("Desktop file already exists!") + config.vprint("Desktop file already exists!") return "Already exists" if "Video" in cats or "Audio" in cats and "AudioVideo" not in cats: cats.append("AudioVideo") @@ -924,10 +982,7 @@ def gitinstall(git_url, program_internal_name, overwrite=False, reinstall=False) else: os.chdir(config.full("~/.tarstall/bin")) generic.progress(5) - if config.verbose: - err = call(["git", "clone", git_url]) - else: - err = call(["git", "clone", git_url], stderr=DEVNULL) + err = git_clone_with_progress(git_url, 5, 65) if err != 0: return "Error" generic.progress(65) @@ -1009,7 +1064,7 @@ def update(force_update=False, show_progress=True): or "Failed" if it failed. """ - if not can_update: + if not can_update and not force_update: config.vprint("requests isn't installed.") return "No requests" elif not config.check_bin("git"): @@ -1017,9 +1072,9 @@ def update(force_update=False, show_progress=True): return "No git" generic.progress(5, show_progress) prog_version_internal = config.get_version('prog_internal_version') - config.vprint("Checking version on GitHub") - final_version = get_online_version('prog') if not force_update: + config.vprint("Checking version on GitHub") + final_version = get_online_version('prog') if final_version == -1: generic.progress(100, show_progress) return "No requests" @@ -1038,10 +1093,7 @@ def update(force_update=False, show_progress=True): os.mkdir("tarstall-update") os.chdir("/tmp/tarstall-update") config.vprint("Cloning tarstall repository from git") - if config.verbose: - err = call(["git", "clone", "--branch", config.branch, "https://github.com/hammy3502/tarstall.git"]) - else: - err = call(["git", "clone", "--branch", config.branch, "https://github.com/hammy3502/tarstall.git"], stderr=c_out) + err = git_clone_with_progress("https://github.com/hammy3502/tarstall.git", 10, 55, config.branch) if err != 0: generic.progress(100, show_progress) return "Failed" @@ -1050,29 +1102,38 @@ def update(force_update=False, show_progress=True): os.chdir(config.full("~/.tarstall/")) files = os.listdir() to_keep = ["bin", "database", ".bashrc", ".fishrc"] + progress = 55 + adder = 15 / int(len(files) - len(to_keep)) for f in files: if f not in to_keep: if os.path.isdir(config.full("~/.tarstall/{}".format(f))): rmtree(config.full("~/.tarstall/{}".format(f))) else: os.remove(config.full("~/.tarstall/{}".format(f))) + progress += adder + generic.progress(progress, show_progress) generic.progress(70, show_progress) config.vprint("Moving in new tarstall files") os.chdir("/tmp/tarstall-update/tarstall/") files = os.listdir() to_ignore = [".git", ".gitignore", "README.md", "readme-images", "COPYING", "requirements.txt", "requirements-gui.txt", "tests", "install_tarstall", "version"] + progress = 70 + adder = 25 / int(len(files) - len(to_ignore)) for f in files: if f not in to_ignore: move("/tmp/tarstall-update/tarstall/{}".format(f), config.full("~/.tarstall/{}".format(f))) - generic.progress(85, show_progress) + progress += adder + generic.progress(progress, show_progress) + generic.progress(95, show_progress) config.vprint("Removing old tarstall temp directory") os.chdir(config.full("~/.tarstall/")) try: rmtree("/tmp/tarstall-update") except FileNotFoundError: pass - config.db["version"]["prog_internal_version"] = final_version - config.write_db() + if not force_update: + config.db["version"]["prog_internal_version"] = final_version + config.write_db() generic.progress(100, show_progress) return "Updated" elif final_version < prog_version_internal: @@ -1253,23 +1314,25 @@ def create_command(file_extension, program): if file_extension == '.tar.gz' or file_extension == '.tar.xz': command_to_go = "tar " + vflag + "xf " + program + " -C /tmp/tarstall-temp/" if which("tar") is None: - print("tar not installed; please install it to install .tar.gz and .tar.xz files!") + config.vprint("tar not installed!") return "No tar" elif file_extension == '.zip': command_to_go = 'unzip ' + vflag + ' ' + program + ' -d /tmp/tarstall-temp/' if which("unzip") is None: - print("unzip not installed; please install it to install ZIP files!") + config.vprint("unzip not installed!") return "No unzip" elif file_extension == '.7z': command_to_go = '7z x ' + vflag + program + ' -o/tmp/tarstall-temp/' if which("7z") is None: + config.vprint("7z not installed!") return "No 7z" elif file_extension == '.rar': command_to_go = 'unrar x ' + vflag + program + ' /tmp/tarstall-temp/' if which("unrar") is None: + config.vprint("unrar not installed!") return "No unrar" else: - print('Error! File type not supported!') + config.vprint("Filetype {} not supported!".format(file_extension)) return "Bad Filetype" config.vprint("Running command: " + command_to_go) return command_to_go @@ -1312,8 +1375,7 @@ def install(program, overwrite=False, reinstall=False, show_progress=True): try: os.system(command_to_go) # Extracts program archive except: - print('Failed to run command: ' + command_to_go + "!") - print("Program installation halted!") + config.vprint('Failed to run command: ' + command_to_go + "! Program installation halted!") return "Error" generic.progress(50, show_progress) config.vprint('Checking for folder in folder') @@ -1426,17 +1488,21 @@ def uninstall(program): return "Not installed" config.vprint("Removing program files") rmtree(config.full("~/.tarstall/bin/" + program + '/')) - generic.progress(20) + generic.progress(40) config.vprint("Removing program from PATH and any binlinks for the program") config.remove_line(program, "~/.tarstall/.bashrc", 'poundword') - generic.progress(30) + generic.progress(50) config.vprint("Removing program desktop files") if config.db["programs"][program]["desktops"]: + progress = 50 + adder = int(30 / len(config.db["programs"][program]["desktops"])) for d in config.db["programs"][program]["desktops"]: try: os.remove(config.full("~/.local/share/applications/{}.desktop".format(d))) except FileNotFoundError: pass + progress += adder + generic.progress(progress) generic.progress(80) config.vprint("Removing program from tarstall list of programs") del config.db["programs"][program] @@ -1466,7 +1532,7 @@ def get_online_version(type_of_replacement, branch=config.branch): int: The specified version, -1 if requests is missing, or -2 if not connected to the internet. """ if not can_update: - print("requests library not installed! Exiting...") + config.vprint("requests library not installed! Exiting...") return -1 version_url = "https://raw.githubusercontent.com/hammy3502/tarstall/{}/version".format(branch) try: diff --git a/version b/version index 08a730c..29e74ff 100644 --- a/version +++ b/version @@ -1 +1 @@ -17.108 \ No newline at end of file +17.110 \ No newline at end of file