Skip to content

Instantly share code, notes, and snippets.

@rz3n
Created June 13, 2023 16:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rz3n/5d9d373dea28b031302173cef5e261bc to your computer and use it in GitHub Desktop.
Save rz3n/5d9d373dea28b031302173cef5e261bc to your computer and use it in GitHub Desktop.
Dotfiles bootstrap script in Python
---
ignore:
- .git
- .gitignore
- README.md
- install
- install.ignore.yaml
#!/usr/bin/env python3
import argparse
import os
import yaml
def dotfiles(dstDir, srcDir, force=False):
# for all files and directories in srcDir, create a symlink in dstDir
# if it is a directory, recursively create directories and symlinks for all
# files
for item in os.listdir(srcDir):
# if it is a ignored file or directory, skip it
if item in IGNORE:
continue
if dstDir == HOME_DIR:
dstFile = os.path.join(dstDir, '.' + item)
else:
dstFile = os.path.join(dstDir, item)
srcFile = os.path.join(srcDir, item)
# if it is a file
if os.path.isfile(srcFile):
# check if it exists
if os.path.lexists(dstFile):
# if it is a symlink, skip it
if os.path.islink(dstFile):
continue
# if it is not a symlink, ask if we should overwrite it
else:
if not force:
response = input("Overwrite file `%s'? [y/N] " % dstFile)
if not response.lower().startswith('y'):
print ("Skipping `%s'..." % dstFile)
continue
else:
os.remove(dstFile)
elif force:
os.remove(dstFile)
# create the symlink
os.symlink(srcFile, dstFile)
# if it is a directory
if os.path.isdir(srcFile):
# check if it exists
if not os.path.exists(dstFile):
os.makedirs(dstFile)
# recursively create symlinks for all files
dotfiles(dstFile, srcFile, force)
if __name__ == '__main__':
# get arguments
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--src')
parser.add_argument('-d', '--dst')
parser.add_argument('-f', '--force', default=False, action='store_true',
help='overwrite existing files')
args = parser.parse_args()
# current directory
if not args.src:
DOTFILES_DIR = os.path.abspath('.')
else:
DOTFILES_DIR = os.path.abspath(args.src)
# home directory
if not args.dst:
HOME_DIR = os.path.expanduser('~')
else:
HOME_DIR = os.path.expanduser(args.dst)
# ignored files and directories (from install.ignore.yaml)
with open('install.ignore.yaml') as f:
IGNORE = yaml.load(f, Loader=yaml.FullLoader)['ignore']
# create symlinks
print('Creating symlinks...')
dotfiles(HOME_DIR, DOTFILES_DIR, args.force)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment