Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception handling #207

Merged
merged 31 commits into from
Jan 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5b47b3c
Exception handling for backups (#206)
Dec 26, 2018
1d279fd
Exception handling for --new_path (#206)
Dec 26, 2018
59ba373
Typo in config dict key
Dec 26, 2018
a9b1956
Fixed reinstalling packages w/ no package backups
Dec 27, 2018
ecbfbe5
coverage: trailing space
Dec 27, 2018
289cb65
Added EOF blank line
Jan 1, 2019
f436375
Updated to exit after no package backups are found
Jan 1, 2019
41c6f99
PEP8
Jan 1, 2019
5a96b6c
got rid of extra EOL blank line
Jan 1, 2019
cb2b47e
break to return
Jan 1, 2019
28f40b6
Refactored out existing file check into utils.py
Jan 1, 2019
fb5cef6
PEP8
Jan 1, 2019
5054d89
Updated backup prompt to not be literal satan
Jan 1, 2019
11434b6
Added check for existing but empty package directories
Jan 1, 2019
3783008
Fixed empty dir check and modified package error message
Jan 1, 2019
ef21b41
Updated existing file check function name
alichtman Jan 1, 2019
4fc4841
Pulled renaming suggested change
Jan 1, 2019
6947433
Modified empty directory check condition
Jan 2, 2019
89d425f
ternary up in here
Jan 2, 2019
65ae865
renamed print_pkg_mgr_error()
Jan 2, 2019
551f4a3
modified package error message
Jan 2, 2019
2b90678
removed unnecessary parameters and updated function calls
Jan 2, 2019
e16c9f0
missing comma
Jan 2, 2019
6584ba7
removed print_shell_cmd_error
Jan 2, 2019
eaf0b9d
Updated new_dir_is_valid to return bool
Jan 2, 2019
ff1233a
updated to reflect new new_dir_is_valid()
Jan 2, 2019
ee9343d
removed comment
Jan 2, 2019
6c7f9fa
Updated error message
Jan 2, 2019
92adb5b
moved empty backup dir check into function
Jan 2, 2019
e9ae1aa
updated empty_backup_dir_check() message
Jan 2, 2019
2031741
Fix error message.
alichtman Jan 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion shallow_backup/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from .prompts import *
from .reinstall import *
from .git_wrapper import *
from .utils import mkdir_warn_overwrite, destroy_backup_dir, expand_to_abs_path
from .utils import (
mkdir_warn_overwrite, destroy_backup_dir, expand_to_abs_path,
new_dir_is_valid)


# custom help options
Expand Down Expand Up @@ -64,6 +66,10 @@ def cli(show, all, dotfiles, configs, packages, fonts, old_path, new_path, remot
# User entered a new path, so update the config
if new_path:
abs_path = os.path.abspath(new_path)

if not new_dir_is_valid(abs_path):
sys.exit(1)
alichtman marked this conversation as resolved.
Show resolved Hide resolved

print_path_blue("\nUpdating shallow-backup path to:", abs_path)
backup_config["backup_path"] = abs_path
write_config(backup_config)
Expand Down
26 changes: 10 additions & 16 deletions shallow_backup/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,16 @@ def backup_packages(backup_path, skip=False):
print_pkg_mgr_backup("npm")
command = "npm ls --global --parseable=true --depth=0"
temp_file_path = "{}/npm_temp_list.txt".format(backup_path)
run_cmd_write_stdout(command, temp_file_path)
npm_dest_file = "{0}/npm_list.txt".format(backup_path)
# Parse npm output
with open(temp_file_path, mode="r+") as temp_file:
# Skip first line of file
temp_file.seek(1)
with open(npm_dest_file, mode="w+") as dest:
for line in temp_file:
dest.write(line.split("/")[-1])

os.remove(temp_file_path)
if not run_cmd_write_stdout(command, temp_file_path):
npm_dest_file = "{0}/npm_list.txt".format(backup_path)
# Parse npm output
with open(temp_file_path, mode="r+") as temp_file:
# Skip first line of file
temp_file.seek(1)
with open(npm_dest_file, mode="w+") as dest:
for line in temp_file:
dest.write(line.split("/")[-1])
os.remove(temp_file_path)

# atom package manager
print_pkg_mgr_backup("Atom")
Expand All @@ -151,11 +150,6 @@ def backup_packages(backup_path, skip=False):
dest = "{}/system_apps_list.txt".format(backup_path)
run_cmd_write_stdout(command, dest)

# Clean up empty package list files
for file in get_abs_path_subfiles(backup_path):
if os.path.getsize(file) == 0:
os.remove(file)


def backup_fonts(backup_path, skip=False):
"""
Expand Down
4 changes: 3 additions & 1 deletion shallow_backup/git_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,15 @@ def move_git_repo(source_path, dest_path):
dest_git_ignore = os.path.join(dest_path, '.gitignore')
git_exists = os.path.exists(dest_git_dir)
gitignore_exists = os.path.exists(dest_git_ignore)

if git_exists or gitignore_exists:
print_red_bold("Evidence of a git repo has been detected.")
if git_exists:
print_path_red("A git repo already exists here:", dest_git_dir)
if gitignore_exists:
print_path_red("A gitignore file already exists here:", dest_git_ignore)
print_red_bold("Exiting to prevent accidental deletion of user data.")
sys.exit()
sys.exit(1)

git_dir = os.path.join(source_path, '.git')
git_ignore_file = os.path.join(source_path, '.gitignore')
Expand All @@ -115,3 +116,4 @@ def move_git_repo(source_path, dest_path):
print_blue_bold("Moving git repo to new location.")
except FileNotFoundError:
pass

17 changes: 11 additions & 6 deletions shallow_backup/printing.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import inquirer
from colorama import Fore, Style
from .constants import ProjInfo
Expand Down Expand Up @@ -83,23 +84,27 @@ def print_section_header(title, color):


def print_pkg_mgr_backup(mgr):
print("{}Backing up {}{}{}{}{} packages list...{}".format(Fore.BLUE, Style.BRIGHT, Fore.YELLOW, mgr, Fore.BLUE,
Style.NORMAL, Style.RESET_ALL))
print("{}Backing up {}{}{}{}{} packages list...{}".format(Fore.BLUE, Style.BRIGHT, Fore.YELLOW, mgr,
Fore.BLUE, Style.NORMAL, Style.RESET_ALL))


def print_pkg_mgr_reinstall(mgr):
print("{}Reinstalling {}{}{}{}{}...{}".format(Fore.BLUE, Style.BRIGHT, Fore.YELLOW, mgr, Fore.BLUE, Style.NORMAL, Style.RESET_ALL))
print("{}Reinstalling {}{}{}{}{}...{}".format(Fore.BLUE, Style.BRIGHT, Fore.YELLOW,
mgr, Fore.BLUE, Style.NORMAL, Style.RESET_ALL))


def prompt_yes_no(message, color):
def prompt_yes_no(message, color, invert=False):
"""
Print question and return True or False depending on user selection from list.
"""
questions = [inquirer.List('choice',
message=color + Style.BRIGHT + message + Fore.BLUE,
choices=[' Yes', ' No'],
choices=(' No', ' Yes') if invert else (' Yes', ' No')
ibokuri marked this conversation as resolved.
Show resolved Hide resolved
)
]

answers = inquirer.prompt(questions)
return answers.get('choice').strip().lower() == 'yes'
if answers:
return answers.get('choice').strip().lower() == 'yes'
else:
sys.exit(1)
31 changes: 22 additions & 9 deletions shallow_backup/prompts.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os
import sys
import inquirer
from colorama import Fore, Style
from .utils import *
from .printing import *
from .config import *
from .git_wrapper import git_set_remote, move_git_repo
from .utils import new_dir_is_valid


def path_update_prompt(config):
Expand All @@ -14,14 +16,20 @@ def path_update_prompt(config):
"""
current_path = config["backup_path"]
print_path_blue("Current shallow-backup path:", current_path)
if prompt_yes_no("Would you like to update this?", Fore.GREEN):
print_green_bold("Enter relative or absolute path:")
abs_path = expand_to_abs_path(input())
print_path_blue("\nUpdating shallow-backup path to:", abs_path)
mkdir_warn_overwrite(abs_path)
move_git_repo(current_path, abs_path)
config["backup_path"] = abs_path
write_config(config)
if prompt_yes_no("Would you like to update this?", Fore.GREEN, invert=True):
while True:
print_green_bold("Enter relative or absolute path:")
abs_path = expand_to_abs_path(input())

if not new_dir_is_valid(abs_path):
continue

print_path_blue("\nUpdating shallow-backup path to:", abs_path)
mkdir_warn_overwrite(abs_path)
move_git_repo(current_path, abs_path)
config["backup_path"] = abs_path
write_config(config)
return


def git_url_prompt(repo):
Expand Down Expand Up @@ -159,4 +167,9 @@ def main_menu_prompt():
]

answers = inquirer.prompt(questions)
return answers.get('choice').strip().lower()

if answers:
return answers.get('choice').strip().lower()
else:
# KeyboardInterrupts
sys.exit(1)
15 changes: 9 additions & 6 deletions shallow_backup/reinstall.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from shlex import quote
from colorama import Fore
from .utils import run_cmd, get_abs_path_subfiles
from .utils import run_cmd, get_abs_path_subfiles, empty_backup_dir_check
from .printing import *
from .compatibility import *
from .config import get_config
Expand All @@ -15,7 +15,9 @@ def reinstall_dots_sb(dots_path):
"""
Reinstall all dotfiles and folders by copying them to the home dir.
"""
empty_backup_dir_check(dots_path, 'dotfile')
print_section_header("REINSTALLING DOTFILES", Fore.BLUE)

home_path = os.path.expanduser('~')
for file in get_abs_path_subfiles(dots_path):
if os.path.isdir(file):
Expand All @@ -29,7 +31,9 @@ def reinstall_fonts_sb(fonts_path):
"""
Reinstall all fonts.
"""
empty_backup_dir_check(fonts_path, 'font')
print_section_header("REINSTALLING FONTS", Fore.BLUE)

# Copy every file in fonts_path to ~/Library/Fonts
for font in get_abs_path_subfiles(fonts_path):
font_lib_path = get_fonts_dir()
Expand All @@ -42,15 +46,13 @@ def reinstall_configs_sb(configs_path):
"""
Reinstall all configs from the backup.
"""
empty_backup_dir_check(configs_path, 'config')
print_section_header("REINSTALLING CONFIG FILES", Fore.BLUE)

def backup_prefix(path):
return os.path.join(configs_path, path)

config = get_config()
for dest_path, backup_loc in config["configs_mapping"].items():
for dest_path, backup_loc in config["config_mapping"].items():
dest_path = quote(dest_path)
path_to_backup = quote(backup_prefix(backup_loc))
path_to_backup = quote(os.path.join(configs_path, backup_loc))
# TODO: REFACTOR WITH GENERIC COPY FUNCTION.
if os.path.isdir(path_to_backup):
copytree(path_to_backup, dest_path)
Expand All @@ -64,6 +66,7 @@ def reinstall_packages_sb(packages_path):
"""
Reinstall all packages from the files in backup/installs.
"""
empty_backup_dir_check(packages_path, 'package')
print_section_header("REINSTALLING PACKAGES", Fore.BLUE)

# Figure out which install lists they have saved
Expand Down
24 changes: 21 additions & 3 deletions shallow_backup/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ def run_cmd(command):
"""
try:
if not isinstance(command, list):
process = sp.run(command.split(), stdout=sp.PIPE)
process = sp.run(command.split(), stdout=sp.PIPE, stderr=sp.DEVNULL)
alichtman marked this conversation as resolved.
Show resolved Hide resolved
alichtman marked this conversation as resolved.
Show resolved Hide resolved
return process
else:
process = sp.run(command, stdout=sp.PIPE)
process = sp.run(command, stdout=sp.PIPE, stderr=sp.DEVNULL)
ibokuri marked this conversation as resolved.
Show resolved Hide resolved
return process
except FileNotFoundError: # If package manager is missing
return None
Expand All @@ -25,11 +25,23 @@ def run_cmd_write_stdout(command, filepath):
"""
Runs a command and then writes its stdout to a file
:param: command str representing command to run
:param: filepath str file to write command's stdout to
"""
process = run_cmd(command)
if process:
if process and process.returncode == 0:
with open(filepath, "w+") as f:
f.write(process.stdout.decode('utf-8'))
else:
print_path_red("An error occurred while running: $", command)
return 1


def new_dir_is_valid(abs_path):
alichtman marked this conversation as resolved.
Show resolved Hide resolved
if os.path.isfile(abs_path):
print_path_red('New path is a file:', abs_path)
print_red_bold('Please enter a directory.\n')
return False
return True


def safe_mkdir(directory):
Expand Down Expand Up @@ -66,6 +78,12 @@ def mkdir_warn_overwrite(path):
print_path_blue("Created directory:", path)


def empty_backup_dir_check(backup_path, backup_type):
if not os.path.isdir(backup_path) or not os.listdir(backup_path):
print_red_bold('No {} backup found.'.format(backup_type))
sys.exit(1)


def destroy_backup_dir(backup_path):
"""
Deletes the backup directory and its content
Expand Down