From 373fdbbe86e8f8e0eb2b4149a7f40abb9357aeb0 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Thu, 29 Nov 2018 18:20:54 +0100 Subject: [PATCH 1/5] Make cfgs.py executable --- cfgs.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 cfgs.py diff --git a/cfgs.py b/cfgs.py old mode 100644 new mode 100755 From aaffe2ff52a2f819f0361cea753bc24603ef475b Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Nov 2018 12:38:28 +0100 Subject: [PATCH 2/5] Explicitly use python3 --- cfgs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfgs.py b/cfgs.py index 3ca43dc..087a4b9 100755 --- a/cfgs.py +++ b/cfgs.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys From d4b08cba0e716dfe1681c695a2219fcf56aab6bf Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Nov 2018 15:02:32 +0100 Subject: [PATCH 3/5] Refactor color handling into some functions --- cfgs.py | 106 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/cfgs.py b/cfgs.py index 087a4b9..ff55c26 100755 --- a/cfgs.py +++ b/cfgs.py @@ -36,23 +36,31 @@ class bcolors: # UI helper functions # ----------------------------------------- +def color_message(color, message, colorend=bcolors.ENDC, bold=False): + if bold: + return bcolors.BOLD + color_message(color, message, colorend, False) + + return color + message + colorend + +def print_color(color, message, colorend=bcolors.ENDC, bold=False): + print(color_message(color, message, colorend)) + def check_dependencies(): status = True try: subprocess.call(["git", "version"], stdout=subprocess.DEVNULL) except OSError: status = False - print(bcolors.FAIL + "git cannot be found on your system!" + bcolors.ENDC) + print_color(bcolors.FAIL, "git cannot be found on your system!") print("Install git: pacman -S git") return status - def print_splash(): - print(bcolors.HEADER + "---=== cfgs ===---" + bcolors.ENDC) + print_color(bcolors.HEADER, "---=== cfgs ===---") print("Version: " + CONFIG_SYNC_VERSION) print() - print(bcolors.HEADER + "---=== USAGE ===---" + bcolors.ENDC) + print_color(bcolors.HEADER, "---=== USAGE ===---") print("cfgs init") print("cfgs add ") print("cfgs remove ") @@ -63,36 +71,36 @@ def print_splash(): def init_dialog(): config = get_config() - print(bcolors.HEADER + "---=== Welcome to cfgs! ===---" + bcolors.ENDC) + print_color(bcolors.HEADER, "---=== Welcome to cfgs! ===---") print() if config['DEFAULT']['INITIALIZED']: - reinitialize = input(bcolors.WARNING + "WARNING: cfgs has already been initialized! Do you really want to change the configuration? [y/N]: " + bcolors.ENDC) + reinitialize = input(color_message(bcolors.WARNING, "WARNING: cfgs has already been initialized! Do you really want to change the configuration? [y/N]: ")) if not reinitialize or reinitialize != "y": print("Skipping new initialization!") sys.exit(0) - local_path = input(bcolors.OKBLUE + "Enter the local storage directory for configuration files [" + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "]: " + bcolors.ENDC) + local_path = input(color_message(bcolors.OKBLUE, "Enter the local storage directory for configuration files [" + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "]: ")) if not local_path: local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] = local_path - remote_repo = input(bcolors.OKBLUE + "Enter the remote repository url [" + config['GIT']['REMOTE_REPOSITORY'] + "]: " + bcolors.ENDC) + remote_repo = input(color_message(bcolors.OKBLUE, "Enter the remote repository url [" + config['GIT']['REMOTE_REPOSITORY'] + "]: ")) if not remote_repo: remote_repo = config['GIT']['REMOTE_REPOSITORY'] config['GIT']['REMOTE_REPOSITORY'] = remote_repo - git_ssh_key = input(bcolors.OKBLUE + "Enter the path to the ssh key to use [" + config['GIT']['SSHKEY'] + "]: " + bcolors.ENDC) + git_ssh_key = input(color_message(bcolors.OKBLUE, "Enter the path to the ssh key to use [" + config['GIT']['SSHKEY'] + "]: ")) if not git_ssh_key: git_ssh_key = config['GIT']['SSHKEY'] config['GIT']['SSHKEY'] = git_ssh_key - git_user = input(bcolors.OKBLUE + "Enter the git user name (displayname) [" + config['GIT']['USER'] + "]: " + bcolors.ENDC) + git_user = input(color_message(bcolors.OKBLUE, "Enter the git user name (displayname) [" + config['GIT']['USER'] + "]: ")) if not git_user: git_user = config['GIT']['USER'] config['GIT']['USER'] = git_user - git_email = input(bcolors.OKBLUE + "Enter the git user email address [" + config['GIT']['EMAIL'] + "]: " + bcolors.ENDC) + git_email = input(color_message(bcolors.OKBLUE, "Enter the git user email address [" + config['GIT']['EMAIL'] + "]: ")) if not git_email: git_email = config['GIT']['EMAIL'] config['GIT']['EMAIL'] = git_email @@ -108,7 +116,7 @@ def init_dialog(): def validate_or_create_config(config): if not os.path.exists(CONFIG_SYNC_FILE): - print(bcolors.OKBLUE + "Creating default configuration file: " + CONFIG_SYNC_FILE + bcolors.ENDC) + print_color(bcolors.OKBLUE, "Creating default configuration file: " + CONFIG_SYNC_FILE) config['DEFAULT'] = {} config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] = "/opt/cfgs/storage" config['DEFAULT']['INITIALIZED'] = "" @@ -136,10 +144,10 @@ def update_config(config): try: config.write(open(CONFIG_SYNC_FILE, 'w')) except PermissionError as e: - print(bcolors.FAIL + "Unable to write config file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write config file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write config file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write config file! Error: " + str(e)) sys.exit(1) @@ -148,19 +156,19 @@ def create_initialization_file(path): with open(path + "/cfgs.info", mode='w') as file: file.write('cfgs repo initialized: %s. host: %s\n' % ( datetime.datetime.now(), socket.gethostname() )) except PermissionError as e: - print(bcolors.FAIL + "Unable to write initialization file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write initialization file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write initialization file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write initialization file! Error: " + str(e)) sys.exit(1) try: open(path + "/cfgs.db", mode='a').close() except PermissionError as e: - print(bcolors.FAIL + "Unable to write database file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write database file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write database file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write database file! Error: " + str(e)) sys.exit(1) @@ -181,10 +189,10 @@ def add_file_to_db(file_path): with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", mode='a') as file: file.write('%s\n' % (file_path)) except PermissionError as e: - print(bcolors.FAIL + "Unable to write db file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write db file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write db file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write db file! Error: " + str(e)) sys.exit(1) @@ -199,10 +207,10 @@ def delete_file_from_db(file_path): search.write(line.rstrip() + "\n") search.truncate() except PermissionError as e: - print(bcolors.FAIL + "Unable to write db file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write db file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write db file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write db file! Error: " + str(e)) sys.exit(1) @@ -259,8 +267,8 @@ def git_pull(path): def git_check_status(status): config = get_config() if not status: - print(bcolors.FAIL + bcolors.BOLD + "FATAL: Git operation failed! Repository has to be recovered manually!" + bcolors.ENDC) - print(bcolors.FAIL + "FATAL: Repository path: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + bcolors.ENDC) + print_color(bcolors.FAIL, "FATAL: Git operation failed! Repository has to be recovered manually!", bold=True) + print_color(bcolors.FAIL, "FATAL: Repository path: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) sys.exit(1) @@ -273,11 +281,11 @@ def init_local_repo(): print("Setting up local repository.") if not os.path.exists(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']): - print(bcolors.OKBLUE + "Creating new directory: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + bcolors.ENDC) + print_color(bcolors.OKBLUE, "Creating new directory: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) try: os.makedirs(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) except OSError as e: - print(bcolors.FAIL + "Failed to create local repository directory: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Failed to create local repository directory: " + e.strerror) sys.exit(1) # init git repo @@ -294,8 +302,8 @@ def init_local_repo(): git_check_status(git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], "cfgs initialized")) git_check_status(git_pull(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'])) - print(bcolors.OKGREEN + "cfgs initialization successfull!" + bcolors.ENDC) - print(bcolors.OKBLUE + "You can now use cfgs to keep your config files up to date." + bcolors.ENDC) + print_color(bcolors.OKGREEN, "cfgs initialization successfull!") + print_color(bcolors.OKBLUE, "You can now use cfgs to keep your config files up to date.") def add_file(filepath): @@ -303,15 +311,15 @@ def add_file(filepath): abs_path = os.path.abspath(filepath) if not os.path.exists(abs_path): - print(bcolors.WARNING + "Invalid file, skipping!" + bcolors.ENDC) + print_color(bcolors.WARNING, "Invalid file, skipping!") sys.exit(1) else: - print(bcolors.OKBLUE + "Adding '" + abs_path + "' to cfgs..." + bcolors.ENDC) + print_color(bcolors.OKBLUE, "Adding '" + abs_path + "' to cfgs...") local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path if os.path.exists(local_path): - print(bcolors.WARNING + "File is already registered to cfgs, skipping!" + bcolors.ENDC) + print_color(bcolors.WARNING, "File is already registered to cfgs, skipping!") sys.exit(1) else: target_directory = os.path.abspath(os.path.join(local_path, os.pardir)) @@ -329,10 +337,10 @@ def add_file(filepath): with open(local_path + ".cfgs", mode='w') as file: file.write('%s;%s;%s;%s;%s;%s' % ( file_permissions, file_owner, file_group, file_owner_name, file_group_name, socket.gethostname() )) except PermissionError as e: - print(bcolors.FAIL + "Unable to write stat file! Error: " + e.strerror + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write stat file! Error: " + e.strerror) sys.exit(1) except Exception as e: - print(bcolors.FAIL + "Unable to write stat file! Error: " + str(e) + bcolors.ENDC) + print_color(bcolors.FAIL, "Unable to write stat file! Error: " + str(e)) sys.exit(1) shutil.copy2(abs_path, local_path) @@ -343,8 +351,8 @@ def add_file(filepath): add_file_to_db(abs_path) - print(bcolors.OKGREEN + "File added to cfgs!" + bcolors.ENDC) - print(bcolors.OKBLUE + "Use cfgs store to push the file to the remote repository!" + bcolors.ENDC) + print_color(bcolors.OKGREEN, "File added to cfgs!") + print_color(bcolors.OKBLUE, "Use cfgs store to push the file to the remote repository!") def remove_file(filepath): @@ -354,19 +362,19 @@ def remove_file(filepath): local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path if not os.path.exists(local_path): - print(bcolors.WARNING + "File not registered to cfgs, skipping!" + bcolors.ENDC) + print_color(bcolors.WARNING, "File not registered to cfgs, skipping!") sys.exit(1) else: - print(bcolors.OKBLUE + "Removing '" + abs_path + "' from cfgs..." + bcolors.ENDC) + print_color(bcolors.OKBLUE, "Removing '" + abs_path + "' from cfgs...") target_directory = os.path.abspath(os.path.join(abs_path, os.pardir)) if not os.path.exists(target_directory): os.makedirs(target_directory) if os.path.exists(abs_path): - confirmed = input(bcolors.OKBLUE + "Do you really want to override the local file '" + abs_path + "'? [y/N]: " + bcolors.ENDC) + confirmed = input(color_message(bcolors.OKBLUE, "Do you really want to override the local file '" + abs_path + "'? [y/N]: ")) if not confirmed or confirmed != "y": - print(bcolors.WARNING + "Skipping removal process!" + bcolors.ENDC) + print_color(bcolors.WARNING, "Skipping removal process!") sys.exit(0) else: os.remove(abs_path) @@ -385,8 +393,8 @@ def remove_file(filepath): delete_file_from_db(abs_path) - print(bcolors.OKGREEN + "File removed from cfgs!" + bcolors.ENDC) - print(bcolors.OKBLUE + "Use cfgs store to push the file to the remote repository!" + bcolors.ENDC) + print_color(bcolors.OKGREEN, "File removed from cfgs!") + print_color(bcolors.OKBLUE, "Use cfgs store to push the file to the remote repository!") def store(): @@ -394,8 +402,8 @@ def store(): git_setup_ssh_environment() git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) - print(bcolors.OKGREEN + "cfgs store successfull!" + bcolors.ENDC) - print(bcolors.OKBLUE + "You can now restore the configuration on your other systems." + bcolors.ENDC) + print_color(bcolors.OKGREEN, "cfgs store successfull!") + print_color(bcolors.OKBLUE, "You can now restore the configuration on your other systems.") def update_local_metadata(): @@ -406,7 +414,7 @@ def update_local_metadata(): local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path if not os.path.exists(local_path): - print(bcolors.WARNING + "Invalid file in database, skipping! (" + abs_path + ")" + bcolors.ENDC) + print_color(bcolors.WARNING, "Invalid file in database, skipping! (" + abs_path + ")") else: with open(local_path + ".cfgs", "r") as metadata_file: metadata_string = metadata_file.readline().rstrip() @@ -427,9 +435,9 @@ def restore(): update_local_metadata() - confirmed = input(bcolors.WARNING + "Do you really want to restore files from the repository? Local files will be overwritten! [y/N]: " + bcolors.ENDC) + confirmed = input(color_message(bcolors.WARNING, "Do you really want to restore files from the repository? Local files will be overwritten! [y/N]: ")) if not confirmed or confirmed != "y": - print(bcolors.WARNING + "Skipping restore process!" + bcolors.ENDC) + print_color(bcolors.WARNING, "Skipping restore process!") sys.exit(0) else: with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", "r") as search: @@ -438,7 +446,7 @@ def restore(): local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path if not os.path.exists(local_path): - print(bcolors.WARNING + "Invalid file, skipping!" + bcolors.ENDC) + print_color(bcolors.WARNING, "Invalid file, skipping!") else: target_directory = os.path.abspath(os.path.join(abs_path, os.pardir)) if not os.path.exists(target_directory): @@ -455,8 +463,8 @@ def restore(): os.chown(abs_path, file_owner, file_group, follow_symlinks=False) - print(bcolors.OKGREEN + "cfgs restore successfull!" + bcolors.ENDC) - print(bcolors.OKBLUE + "Configuration files have been updated. A reboot might be required." + bcolors.ENDC) + print_color(bcolors.OKGREEN, "cfgs restore successfull!") + print_color(bcolors.OKBLUE, "Configuration files have been updated. A reboot might be required.") # ----------------------------------------- From 5896df1e64e23d7e423f0029f7e9ff56f401148c Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Nov 2018 15:03:09 +0100 Subject: [PATCH 4/5] Cleanup whitespace --- cfgs.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cfgs.py b/cfgs.py index ff55c26..4d66ff5 100755 --- a/cfgs.py +++ b/cfgs.py @@ -104,7 +104,7 @@ def init_dialog(): if not git_email: git_email = config['GIT']['EMAIL'] config['GIT']['EMAIL'] = git_email - + config['DEFAULT']['INITIALIZED'] = "True" update_config(config) @@ -254,13 +254,13 @@ def git_push(path, message = "configuration update"): status = subprocess.call(["git", "add", "-A"], cwd=path) == 0 status |= subprocess.call(["git", "commit", "-a", "-m", message], cwd=path) == 0 status |= subprocess.call(["git", "push", "-u", "origin", "master"], cwd=path) == 0 - + return status def git_pull(path): status = subprocess.call(["git", "pull", "origin", "master"], cwd=path) == 0 - + return status @@ -291,7 +291,7 @@ def init_local_repo(): # init git repo if not git_is_repo(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']): git_init_repo(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) - + git_check_status(git_set_author(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], config['GIT']['USER'], config['GIT']['EMAIL'])) git_check_status(git_set_upstream(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], config['GIT']['REMOTE_REPOSITORY'])) @@ -451,7 +451,7 @@ def restore(): target_directory = os.path.abspath(os.path.join(abs_path, os.pardir)) if not os.path.exists(target_directory): os.makedirs(target_directory) - + if os.path.exists(abs_path): os.remove(abs_path) @@ -474,7 +474,7 @@ def restore(): def main(argv): if not check_dependencies(): sys.exit(1) - + if len(argv) == 2: arg = argv[1] if arg == "init": From 4062d6fdb42759e4bc8a833d3551b3c6ed8d23eb Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Nov 2018 19:11:46 +0100 Subject: [PATCH 5/5] Refactor confirmations into confirm-function --- cfgs.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cfgs.py b/cfgs.py index 4d66ff5..9ad3dbf 100755 --- a/cfgs.py +++ b/cfgs.py @@ -56,6 +56,10 @@ def check_dependencies(): return status +def confirm(message, color=bcolors.WARNING): + status = input(color_message(color, message + " [y/N]: ")) + return status and (status == "y" or status == "Y") + def print_splash(): print_color(bcolors.HEADER, "---=== cfgs ===---") print("Version: " + CONFIG_SYNC_VERSION) @@ -75,8 +79,7 @@ def init_dialog(): print() if config['DEFAULT']['INITIALIZED']: - reinitialize = input(color_message(bcolors.WARNING, "WARNING: cfgs has already been initialized! Do you really want to change the configuration? [y/N]: ")) - if not reinitialize or reinitialize != "y": + if not confirm("WARNING: cfgs has already been initialized! Do you really want to change the configuration?"): print("Skipping new initialization!") sys.exit(0) @@ -372,8 +375,7 @@ def remove_file(filepath): os.makedirs(target_directory) if os.path.exists(abs_path): - confirmed = input(color_message(bcolors.OKBLUE, "Do you really want to override the local file '" + abs_path + "'? [y/N]: ")) - if not confirmed or confirmed != "y": + if not confirm("Do you really want to override the local file '" + abs_path + "'?", bcolors.OKBLUE): print_color(bcolors.WARNING, "Skipping removal process!") sys.exit(0) else: @@ -435,8 +437,7 @@ def restore(): update_local_metadata() - confirmed = input(color_message(bcolors.WARNING, "Do you really want to restore files from the repository? Local files will be overwritten! [y/N]: ")) - if not confirmed or confirmed != "y": + if not confirm("Do you really want to restore files from the repository? Local files will be overwritten!"): print_color(bcolors.WARNING, "Skipping restore process!") sys.exit(0) else: