185 lines
4.9 KiB
Python
185 lines
4.9 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
import os, os.path
|
||
|
import shutil
|
||
|
|
||
|
# FUNCTIONS
|
||
|
########################################
|
||
|
def yes_no_question(question="Yes or no?", default=False):
|
||
|
prompt=""
|
||
|
if(default is True):
|
||
|
prompt = " [Y/n]"
|
||
|
else:
|
||
|
prompt = " [y/N]"
|
||
|
|
||
|
answer = input(question + prompt).lower()
|
||
|
|
||
|
if(len(answer) == 0):
|
||
|
return default
|
||
|
else:
|
||
|
answer = answer[0]
|
||
|
|
||
|
if(default is True):
|
||
|
if answer in ['n','0']:
|
||
|
return False
|
||
|
else:
|
||
|
if answer in ['y','o','1']:
|
||
|
return True
|
||
|
|
||
|
return default
|
||
|
|
||
|
def contractuser(path):
|
||
|
home = os.path.expanduser("~")
|
||
|
|
||
|
if path.startswith(home):
|
||
|
return path.replace(home, "~", 1) # Replace only one instance:
|
||
|
# the first one
|
||
|
else:
|
||
|
return path
|
||
|
|
||
|
def copy_file_or_directory(logger, path_dst, path_src, overwrite=True):
|
||
|
|
||
|
# Expand '~' as user's home dir
|
||
|
dst = os.path.expanduser(path_dst)
|
||
|
src = os.path.expanduser(path_src)
|
||
|
|
||
|
if overwrite:
|
||
|
|
||
|
# --------------------------------------
|
||
|
def replace_backup():
|
||
|
try:
|
||
|
logger.info("Putting backup back in place")
|
||
|
shutil.move(dst + ".bak", dst)
|
||
|
|
||
|
except FileNotFoundError:
|
||
|
logger.error("No backup of %s found. Oops" % dst)
|
||
|
return False
|
||
|
|
||
|
except PermissionError:
|
||
|
logger.error("Cannot replace backup %s because of permissions"
|
||
|
% (dst + ".bak"))
|
||
|
return False
|
||
|
|
||
|
except FileExistsError:
|
||
|
logger.error("%s has been created, you need to chose " \
|
||
|
"manually to keep it or to use the backup %s"
|
||
|
% (dst, dst + ".bak"))
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
# --------------------------------------
|
||
|
|
||
|
|
||
|
try:
|
||
|
logger.info("Moving old directory %s" % dst)
|
||
|
shutil.move(dst, dst + ".bak")
|
||
|
|
||
|
except FileNotFoundError:
|
||
|
logger.info("No file %s exists yet" % dst)
|
||
|
|
||
|
except PermissionError:
|
||
|
logger.error("Unable to write %s, please check permissions"
|
||
|
% (dst + ".bak"))
|
||
|
return False
|
||
|
|
||
|
except FileExistsError:
|
||
|
logger.error("%s already exists" % (dst + ".bak"))
|
||
|
return False
|
||
|
|
||
|
|
||
|
# No overwrite ? No problem.
|
||
|
else:
|
||
|
|
||
|
def replace_backup():
|
||
|
return True
|
||
|
|
||
|
|
||
|
# Copy the conf dir
|
||
|
# --------------------------------------
|
||
|
try:
|
||
|
logger.info("Copying directory %s" % src)
|
||
|
shutil.copytree(src, dst)
|
||
|
|
||
|
except FileNotFoundError:
|
||
|
logger.error("%s does not seem to exist" % src)
|
||
|
replace_backup()
|
||
|
return False
|
||
|
|
||
|
except PermissionError:
|
||
|
logger.error("Unable to write %s, please check permissions" % dst)
|
||
|
replace_backup()
|
||
|
return False
|
||
|
|
||
|
except FileExistsError:
|
||
|
logger.error("The directory '%s' already exists" % dst)
|
||
|
replace_backup()
|
||
|
return False
|
||
|
|
||
|
# It's not a dir, it's a file !
|
||
|
# --------------------------------------
|
||
|
except NotADirectoryError:
|
||
|
|
||
|
# Try not to overwrite an existing file.
|
||
|
# Note that if 'overwrite' was set to True, any existing file would
|
||
|
# have been moved at this point.
|
||
|
if os.path.exists(dst):
|
||
|
logger.error("The file %s already exists" % dst)
|
||
|
replace_backup()
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
logger.info("Copying file %s" % src)
|
||
|
shutil.copyfile(src, dst)
|
||
|
|
||
|
except PermissionError:
|
||
|
logger.error("Unable to write %s, please check permissions" % dst)
|
||
|
replace_backup()
|
||
|
return False
|
||
|
|
||
|
# Everything went well, time to remove the backup
|
||
|
# --------------------------------------
|
||
|
if overwrite:
|
||
|
delete_file_or_dir((dst + ".bak"), logger)
|
||
|
|
||
|
# The End.
|
||
|
return True
|
||
|
|
||
|
|
||
|
# ======================================
|
||
|
def delete_file_or_dir(path, logger=None):
|
||
|
|
||
|
# Set logger to '/dev/null' if it's not set
|
||
|
if logger is None:
|
||
|
logger = logging.getLogger("/dev/null")
|
||
|
logger.addHandler(logging.NullHandler())
|
||
|
|
||
|
# Try it as a dir first
|
||
|
try:
|
||
|
logger.info("Removing directory %s" % path)
|
||
|
shutil.rmtree(path)
|
||
|
|
||
|
except FileNotFoundError:
|
||
|
logger.warning("File %s seems to be already deleted" % path)
|
||
|
return False
|
||
|
except PermissionError:
|
||
|
logger.warning("Cannot remove dir %s, you will have to do it manually"
|
||
|
% path)
|
||
|
return False
|
||
|
|
||
|
# If not, try it as a file
|
||
|
except NotADirectoryError:
|
||
|
try:
|
||
|
logger.info("Removing file %s" % path)
|
||
|
os.remove(path)
|
||
|
|
||
|
except PermissionError:
|
||
|
logger.warning( "Cannot remove file %s, you'll have to do it " \
|
||
|
"manually"
|
||
|
% path )
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
|