Update setup script using new lint rules

No functional changes, I just wanted to tidy things up.
This commit is contained in:
Trysdyn Black 2023-12-28 18:01:11 -08:00
parent ff2faf4e4c
commit 91b6e2377f

View file

@ -1,25 +1,24 @@
#!/usr/bin/env python3
"""
Dotfile setup utility.
Syncronizes dotfiles from a source dir that mimics a homedir tree to a homedir,
removing old symlinks as necessary as well as optionally files.
"""
import os
import pathlib
import inspect
import os # Needed for os.walk til Py3.12
from pathlib import Path
FORCE = False
HOMEDIR = os.path.expanduser("~")
SOURCEDIR = os.path.dirname(os.path.join(os.path.realpath(__file__)))
HOMEDIR = Path("~").expanduser()
SOURCEDIR = Path(str(inspect.getsourcefile(lambda: False))).parent
EXCLUSIONS = [".git", "setup_dotfiles.py", "README.md"]
EXCLUSIONS = [
".git",
"setup_dotfiles.py",
"README.md"
]
def check_and_remove(source, destination, force=False):
def check_and_remove(source: Path, destination: Path, *, force: bool = False) -> bool:
"""
Checks if a file exists and removes it if appropriate.
Check if a file exists and remove it if appropriate.
If it's a symlink we check it points the right place and remove it if not.
@ -27,38 +26,37 @@ def check_and_remove(source, destination, force=False):
If we need to re-deploy the symlink, return True, else return False.
"""
pathlib.Path(os.path.dirname(destination)).mkdir(parents=True, exist_ok=True)
Path(destination).parent.mkdir(parents=True, exist_ok=True)
# Destination exists as a symlink
if os.path.islink(destination):
if Path(destination).is_symlink():
# Symlink is correct, return
if os.readlink(destination) == source:
if Path(destination).readlink() == source:
return False
# Symlink is incorrect, remove it
os.unlink(destination)
Path(destination).unlink()
# Destination exists as a file
elif os.path.exists(destination):
elif Path(destination).exists():
# Force mode enabled, remove it (Data loss risk!!)
if force:
os.remove(destination)
Path(destination).unlink()
# Force mode disabled, error out
else:
raise OSError(destination + " exists as a file and --force not provided")
msg = f"{destination!s} exists as a file and --force not provided"
raise OSError(msg)
# File doesn't exist or undefined "thing" happened, return True to try to
# write, and if something goes wrong, we'll see the OSError
return True
def install_dotfiles(source_dir, dest_dir, exclusions, force=False):
def install_dotfiles(source_dir: Path, dest_dir: Path, exclusions: list, *, force: bool = False) -> None:
"""
Iterates the files present in source_dir, excluding EXCLUSIONS, and symlinks
them in dest_dir, overwriting files that exist if force is true.
"""
# source_dir needs to end in an / to make replacements work
if not source_dir.endswith("/"):
source_dir = source_dir + "/"
Iterate files in SOURCEDIR and create symlinks to them in HOMEDIR.
We also exclude files noted in exclusions, and will remove files in the way
if "force" is true.
"""
for root, dir_names, file_names in os.walk(source_dir):
# Remove exclusions from the walk list so we don't touch them
for exclusion in exclusions:
@ -69,18 +67,18 @@ def install_dotfiles(source_dir, dest_dir, exclusions, force=False):
for file_name in file_names:
# Get the full path for the source file
source = os.path.join(root, file_name)
source = Path(root) / file_name
# Get the full path for where the symlink should go
# We remove the source_dir to get a dotfile dir relative path
destination = os.path.join(dest_dir, source.replace(source_dir, ''))
destination = dest_dir / source.relative_to(source_dir)
# Check for and remove the destination file if it exists
# If a removal occurs, catch True and deploy the symlink
if check_and_remove(source, destination, force):
print("Symlinking " + source + " => " + destination)
if check_and_remove(source, destination, force=force):
print(f"Symlinking {source} => {destination}")
os.symlink(source, destination)
if __name__ == "__main__":
install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, False)
install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, force=False)