117 lines
3.5 KiB
Python
117 lines
3.5 KiB
Python
|
#!/usr/bin/python
|
||
|
|
||
|
import argparse
|
||
|
from sys import argv
|
||
|
from pathlib import Path
|
||
|
from os import path, link, remove, walk, mkdir
|
||
|
|
||
|
DEBUG_MODE = False
|
||
|
REPLACE_MODE = False
|
||
|
|
||
|
# def askYesNo(msg):
|
||
|
# while True:
|
||
|
# ans = input(msg + ' [Y/N]')
|
||
|
# if ans in 'Yy':
|
||
|
# return True
|
||
|
# elif ans in 'Nn':
|
||
|
# return False
|
||
|
# else:
|
||
|
# print('Please answer with Y or N')
|
||
|
|
||
|
def info(msg):
|
||
|
print(f'\033[1;32m[INFO] {msg}\033[0m')
|
||
|
|
||
|
def warn(msg):
|
||
|
print(f'\033[1;33m[WARNING] {msg}\033[0m')
|
||
|
|
||
|
def error(msg):
|
||
|
print(f'\033[1;5;31m[ERROR] {msg}\033[0m')
|
||
|
|
||
|
def hardlink(src_path, dest_path):
|
||
|
if not path.exists(src_path):
|
||
|
error('File does not exist: ' + src_path)
|
||
|
return
|
||
|
|
||
|
if path.exists(dest_path):
|
||
|
if REPLACE_MODE:
|
||
|
info('Removing ' + dest_path)
|
||
|
if not DEBUG_MODE:
|
||
|
remove(dest_path)
|
||
|
else:
|
||
|
warn(f'File {dest_path} already exists. Skipping')
|
||
|
return
|
||
|
|
||
|
info('Linked ' + src_path + " -> " + dest_path)
|
||
|
if not DEBUG_MODE:
|
||
|
link(src_path, dest_path)
|
||
|
|
||
|
def copy_folder_structure(src_dir, dest_dir):
|
||
|
for root, dirs, _ in walk(src_dir):
|
||
|
for d in dirs:
|
||
|
new_dir = path.join(dest_dir, d)
|
||
|
if not path.isdir(new_dir):
|
||
|
info('New dir: ' + new_dir)
|
||
|
if not DEBUG_MODE:
|
||
|
mkdir(new_dir)
|
||
|
else:
|
||
|
warn(f'Dir {new_dir} already exists. Skipping')
|
||
|
break
|
||
|
|
||
|
def hardlink_contents_of(src_dir, dest_dir):
|
||
|
for _, _, files in walk(src_dir):
|
||
|
for file in files:
|
||
|
hardlink(path.join(src_dir, file), path.join(dest_dir, file))
|
||
|
break
|
||
|
|
||
|
def hardlink_dir_recursively(src_dir, dest_dir):
|
||
|
for root, dirs, _ in walk(src_dir):
|
||
|
src = path.join(path.abspath(src_dir), root[len(src_dir) + 1:])
|
||
|
dest = dest_dir + root[len(src_dir):]
|
||
|
copy_folder_structure(root, dest)
|
||
|
hardlink_contents_of(src, path.abspath(dest))
|
||
|
|
||
|
def parse_file(filepath):
|
||
|
with open(filepath) as file:
|
||
|
return (line.split() for line in file.readlines() if len(line.split()) != 0)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
|
||
|
parser = argparse.ArgumentParser(description='Recursively hardlink dotfiles')
|
||
|
|
||
|
parser.add_argument('-r', '--replace', dest='REPLACE_MODE', action='store_const',
|
||
|
const=True, default=False,
|
||
|
help='Replace files if they already exist at location')
|
||
|
|
||
|
parser.add_argument('-d', '--debug', dest='DEBUG_MODE', action='store_const',
|
||
|
const=True, default=False,
|
||
|
help='Run a fake run where all ouput is generated but nothing is executed')
|
||
|
|
||
|
parser.add_argument('SRC', nargs='?', metavar='src', type=str,
|
||
|
help='Source folder to recursively scan for files')
|
||
|
|
||
|
parser.add_argument('DEST', nargs='?', metavar='dest', type=str,
|
||
|
help='Destination folder to hardlink all files to')
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
DEBUG_MODE = args.DEBUG_MODE
|
||
|
REPLACE_MODE = args.REPLACE_MODE
|
||
|
|
||
|
if hasattr(args, 'src') and hasattr(args, 'dest'):
|
||
|
src_dir = path.abspath(args.src)
|
||
|
dest_dir = path.abspath(args.dest)
|
||
|
hardlink_dir_recursively(src_dir, dest_dir)
|
||
|
else:
|
||
|
for src,dest in parse_file(path.join(Path(__file__).parent.absolute(), 'hardlinklist.txt')):
|
||
|
project_dir = Path(__file__).parent.parent.absolute()
|
||
|
src_dir = path.abspath(path.join(project_dir, path.expanduser(src)))
|
||
|
dest_dir = path.abspath(path.join(project_dir, path.expanduser(dest)))
|
||
|
|
||
|
if path.exists(src_dir):
|
||
|
if path.isfile(src_dir):
|
||
|
hardlink(src_dir, dest_dir)
|
||
|
else:
|
||
|
hardlink_dir_recursively(src_dir, dest_dir)
|
||
|
else:
|
||
|
error(src_dir + ' does not exist')
|