Merge branch 'master' into 'master'

some cleanup

See merge request h44z/cfgs!1
This commit is contained in:
Christoph Haas 2018-11-30 23:19:15 +01:00
commit c989927e82
1 changed files with 67 additions and 58 deletions

125
cfgs.py Normal file → Executable file
View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
import os import os
import sys import sys
@ -36,23 +36,35 @@ class bcolors:
# UI helper functions # 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(): def check_dependencies():
status = True status = True
try: try:
subprocess.call(["git", "version"], stdout=subprocess.DEVNULL) subprocess.call(["git", "version"], stdout=subprocess.DEVNULL)
except OSError: except OSError:
status = False 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") print("Install git: pacman -S git")
return status 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(): def print_splash():
print(bcolors.HEADER + "---=== cfgs ===---" + bcolors.ENDC) print_color(bcolors.HEADER, "---=== cfgs ===---")
print("Version: " + CONFIG_SYNC_VERSION) print("Version: " + CONFIG_SYNC_VERSION)
print() print()
print(bcolors.HEADER + "---=== USAGE ===---" + bcolors.ENDC) print_color(bcolors.HEADER, "---=== USAGE ===---")
print("cfgs init") print("cfgs init")
print("cfgs add <file path>") print("cfgs add <file path>")
print("cfgs remove <file path>") print("cfgs remove <file path>")
@ -63,40 +75,39 @@ def print_splash():
def init_dialog(): def init_dialog():
config = get_config() config = get_config()
print(bcolors.HEADER + "---=== Welcome to cfgs! ===---" + bcolors.ENDC) print_color(bcolors.HEADER, "---=== Welcome to cfgs! ===---")
print() print()
if config['DEFAULT']['INITIALIZED']: 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) if not confirm("WARNING: cfgs has already been initialized! Do you really want to change the configuration?"):
if not reinitialize or reinitialize != "y":
print("Skipping new initialization!") print("Skipping new initialization!")
sys.exit(0) 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: if not local_path:
local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']
config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] = local_path 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: if not remote_repo:
remote_repo = config['GIT']['REMOTE_REPOSITORY'] remote_repo = config['GIT']['REMOTE_REPOSITORY']
config['GIT']['REMOTE_REPOSITORY'] = remote_repo 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: if not git_ssh_key:
git_ssh_key = config['GIT']['SSHKEY'] git_ssh_key = config['GIT']['SSHKEY']
config['GIT']['SSHKEY'] = git_ssh_key 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: if not git_user:
git_user = config['GIT']['USER'] git_user = config['GIT']['USER']
config['GIT']['USER'] = 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: if not git_email:
git_email = config['GIT']['EMAIL'] git_email = config['GIT']['EMAIL']
config['GIT']['EMAIL'] = git_email config['GIT']['EMAIL'] = git_email
config['DEFAULT']['INITIALIZED'] = "True" config['DEFAULT']['INITIALIZED'] = "True"
update_config(config) update_config(config)
@ -108,7 +119,7 @@ def init_dialog():
def validate_or_create_config(config): def validate_or_create_config(config):
if not os.path.exists(CONFIG_SYNC_FILE): 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'] = {}
config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] = "/opt/cfgs/storage" config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] = "/opt/cfgs/storage"
config['DEFAULT']['INITIALIZED'] = "" config['DEFAULT']['INITIALIZED'] = ""
@ -136,10 +147,10 @@ def update_config(config):
try: try:
config.write(open(CONFIG_SYNC_FILE, 'w')) config.write(open(CONFIG_SYNC_FILE, 'w'))
except PermissionError as e: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
@ -148,19 +159,19 @@ def create_initialization_file(path):
with open(path + "/cfgs.info", mode='w') as file: with open(path + "/cfgs.info", mode='w') as file:
file.write('cfgs repo initialized: %s. host: %s\n' % ( datetime.datetime.now(), socket.gethostname() )) file.write('cfgs repo initialized: %s. host: %s\n' % ( datetime.datetime.now(), socket.gethostname() ))
except PermissionError as e: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
try: try:
open(path + "/cfgs.db", mode='a').close() open(path + "/cfgs.db", mode='a').close()
except PermissionError as e: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
@ -181,10 +192,10 @@ def add_file_to_db(file_path):
with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", mode='a') as file: with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", mode='a') as file:
file.write('%s\n' % (file_path)) file.write('%s\n' % (file_path))
except PermissionError as e: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
@ -199,10 +210,10 @@ def delete_file_from_db(file_path):
search.write(line.rstrip() + "\n") search.write(line.rstrip() + "\n")
search.truncate() search.truncate()
except PermissionError as e: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
@ -246,21 +257,21 @@ def git_push(path, message = "configuration update"):
status = subprocess.call(["git", "add", "-A"], cwd=path) == 0 status = subprocess.call(["git", "add", "-A"], cwd=path) == 0
status |= subprocess.call(["git", "commit", "-a", "-m", message], 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 status |= subprocess.call(["git", "push", "-u", "origin", "master"], cwd=path) == 0
return status return status
def git_pull(path): def git_pull(path):
status = subprocess.call(["git", "pull", "origin", "master"], cwd=path) == 0 status = subprocess.call(["git", "pull", "origin", "master"], cwd=path) == 0
return status return status
def git_check_status(status): def git_check_status(status):
config = get_config() config = get_config()
if not status: if not status:
print(bcolors.FAIL + bcolors.BOLD + "FATAL: Git operation failed! Repository has to be recovered manually!" + bcolors.ENDC) print_color(bcolors.FAIL, "FATAL: Git operation failed! Repository has to be recovered manually!", bold=True)
print(bcolors.FAIL + "FATAL: Repository path: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + bcolors.ENDC) print_color(bcolors.FAIL, "FATAL: Repository path: " + config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'])
sys.exit(1) sys.exit(1)
@ -273,17 +284,17 @@ def init_local_repo():
print("Setting up local repository.") print("Setting up local repository.")
if not os.path.exists(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']): 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: try:
os.makedirs(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) os.makedirs(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'])
except OSError as e: 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) sys.exit(1)
# init git repo # init git repo
if not git_is_repo(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']): if not git_is_repo(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']):
git_init_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_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'])) git_check_status(git_set_upstream(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], config['GIT']['REMOTE_REPOSITORY']))
@ -294,8 +305,8 @@ def init_local_repo():
git_check_status(git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], "cfgs initialized")) git_check_status(git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'], "cfgs initialized"))
git_check_status(git_pull(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'])) git_check_status(git_pull(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']))
print(bcolors.OKGREEN + "cfgs initialization successfull!" + bcolors.ENDC) print_color(bcolors.OKGREEN, "cfgs initialization successfull!")
print(bcolors.OKBLUE + "You can now use cfgs to keep your config files up to date." + bcolors.ENDC) print_color(bcolors.OKBLUE, "You can now use cfgs to keep your config files up to date.")
def add_file(filepath): def add_file(filepath):
@ -303,15 +314,15 @@ def add_file(filepath):
abs_path = os.path.abspath(filepath) abs_path = os.path.abspath(filepath)
if not os.path.exists(abs_path): 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) sys.exit(1)
else: 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 local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path
if os.path.exists(local_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) sys.exit(1)
else: else:
target_directory = os.path.abspath(os.path.join(local_path, os.pardir)) target_directory = os.path.abspath(os.path.join(local_path, os.pardir))
@ -329,10 +340,10 @@ def add_file(filepath):
with open(local_path + ".cfgs", mode='w') as file: 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() )) 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: 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) sys.exit(1)
except Exception as e: 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) sys.exit(1)
shutil.copy2(abs_path, local_path) shutil.copy2(abs_path, local_path)
@ -343,8 +354,8 @@ def add_file(filepath):
add_file_to_db(abs_path) add_file_to_db(abs_path)
print(bcolors.OKGREEN + "File added to cfgs!" + bcolors.ENDC) print_color(bcolors.OKGREEN, "File added to cfgs!")
print(bcolors.OKBLUE + "Use cfgs store to push the file to the remote repository!" + bcolors.ENDC) print_color(bcolors.OKBLUE, "Use cfgs store to push the file to the remote repository!")
def remove_file(filepath): def remove_file(filepath):
@ -354,19 +365,18 @@ def remove_file(filepath):
local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path
if not os.path.exists(local_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) sys.exit(1)
else: 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)) target_directory = os.path.abspath(os.path.join(abs_path, os.pardir))
if not os.path.exists(target_directory): if not os.path.exists(target_directory):
os.makedirs(target_directory) os.makedirs(target_directory)
if os.path.exists(abs_path): 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) if not confirm("Do you really want to override the local file '" + abs_path + "'?", bcolors.OKBLUE):
if not confirmed or confirmed != "y": print_color(bcolors.WARNING, "Skipping removal process!")
print(bcolors.WARNING + "Skipping removal process!" + bcolors.ENDC)
sys.exit(0) sys.exit(0)
else: else:
os.remove(abs_path) os.remove(abs_path)
@ -385,8 +395,8 @@ def remove_file(filepath):
delete_file_from_db(abs_path) delete_file_from_db(abs_path)
print(bcolors.OKGREEN + "File removed from cfgs!" + bcolors.ENDC) print_color(bcolors.OKGREEN, "File removed from cfgs!")
print(bcolors.OKBLUE + "Use cfgs store to push the file to the remote repository!" + bcolors.ENDC) print_color(bcolors.OKBLUE, "Use cfgs store to push the file to the remote repository!")
def store(): def store():
@ -394,8 +404,8 @@ def store():
git_setup_ssh_environment() git_setup_ssh_environment()
git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY']) git_push(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'])
print(bcolors.OKGREEN + "cfgs store successfull!" + bcolors.ENDC) print_color(bcolors.OKGREEN, "cfgs store successfull!")
print(bcolors.OKBLUE + "You can now restore the configuration on your other systems." + bcolors.ENDC) print_color(bcolors.OKBLUE, "You can now restore the configuration on your other systems.")
def update_local_metadata(): def update_local_metadata():
@ -406,7 +416,7 @@ def update_local_metadata():
local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path
if not os.path.exists(local_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: else:
with open(local_path + ".cfgs", "r") as metadata_file: with open(local_path + ".cfgs", "r") as metadata_file:
metadata_string = metadata_file.readline().rstrip() metadata_string = metadata_file.readline().rstrip()
@ -427,9 +437,8 @@ def restore():
update_local_metadata() 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) if not confirm("Do you really want to restore files from the repository? Local files will be overwritten!"):
if not confirmed or confirmed != "y": print_color(bcolors.WARNING, "Skipping restore process!")
print(bcolors.WARNING + "Skipping restore process!" + bcolors.ENDC)
sys.exit(0) sys.exit(0)
else: else:
with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", "r") as search: with open(config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + "/cfgs.db", "r") as search:
@ -438,12 +447,12 @@ def restore():
local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path local_path = config['DEFAULT']['LOCAL_STORAGE_DIRECTORY'] + abs_path
if not os.path.exists(local_path): if not os.path.exists(local_path):
print(bcolors.WARNING + "Invalid file, skipping!" + bcolors.ENDC) print_color(bcolors.WARNING, "Invalid file, skipping!")
else: else:
target_directory = os.path.abspath(os.path.join(abs_path, os.pardir)) target_directory = os.path.abspath(os.path.join(abs_path, os.pardir))
if not os.path.exists(target_directory): if not os.path.exists(target_directory):
os.makedirs(target_directory) os.makedirs(target_directory)
if os.path.exists(abs_path): if os.path.exists(abs_path):
os.remove(abs_path) os.remove(abs_path)
@ -455,8 +464,8 @@ def restore():
os.chown(abs_path, file_owner, file_group, follow_symlinks=False) os.chown(abs_path, file_owner, file_group, follow_symlinks=False)
print(bcolors.OKGREEN + "cfgs restore successfull!" + bcolors.ENDC) print_color(bcolors.OKGREEN, "cfgs restore successfull!")
print(bcolors.OKBLUE + "Configuration files have been updated. A reboot might be required." + bcolors.ENDC) print_color(bcolors.OKBLUE, "Configuration files have been updated. A reboot might be required.")
# ----------------------------------------- # -----------------------------------------
@ -466,7 +475,7 @@ def restore():
def main(argv): def main(argv):
if not check_dependencies(): if not check_dependencies():
sys.exit(1) sys.exit(1)
if len(argv) == 2: if len(argv) == 2:
arg = argv[1] arg = argv[1]
if arg == "init": if arg == "init":