""" defines target classes: the places where things should be written """ import pathlib import subprocess import shutil import os from functools import cached_property from . import host class Target: """ base class of all target platforms """ def target_path(self, relpath): """ computes the path of a file in the home directory """ return self.target_root / relpath @cached_property def target_root(self): """ locates the home directory """ return pathlib.Path.home() def map_file(self, source_path, target_path): """ maps a file from a source path to some target path. The source path is expected to be an absolute path, while the target_path is a relative path, relative to the target's root. """ if not target_path.is_absolute(): target_path = self.target_root / target_path print(f"target path: {target_path}") print(f"target drive: {target_path.drive}") if not target_path.parent.exists(): print("creating missing parent directories for target") parent_dir = target_path.parent parent_dir.mkdir(parents=True) print(f"checking if target path {target_path.parts} exists") exists = os.path.exists(str(target_path)) print(f"exists: {exists}") is_link = os.path.islink(str(target_path)) print(f"is link: {is_link}") if target_path.exists(): print("target path exists") if target_path.is_symlink(): print("target path is symlink") if target_path.resolve() == source_path: print("symlink is up to date\n") return print("removing out of date symlink") target_path.unlink() elif target_path.is_file(): print("removing existing regular file") target_path.unlink() elif target_path.is_dir(): print("skip: target path is existing directory\n") return else: print("skip: target path already exists") return else: print("target path does not exist") if target_path.is_symlink(): # ok this deserves some explaining: if a symlink points to # itself, then pathlib considers it to not exist. It can't be # resolved because it's an infinite loop, but a non-existent # file that is a symlink is a circular reference in a symlink. print("removing broken symlink") target_path.unlink() print("creating symlink") target_path.symlink_to(source_path) print("") class Linux(Target): """ defines a local Linux target: the local machine when the script is run on Linux """ class Windows(Target): """ defines a local Windows target: the local machine when the script is run on Windows """ class WSLHost(Target): """ defines the Windows machine on which the WSL instance is hosted """ @cached_property def target_root(self): if not host.is_wsl: raise Exception("cannot get windows home dir from anything other than wsl") res = subprocess.run(['wslvar', 'USERPROFILE'], check=False, capture_output=True) winpath = res.stdout.decode('utf-8').strip() res = subprocess.run(['wslpath', winpath], check=False, capture_output=True) return pathlib.Path(res.stdout.decode('utf-8').strip()) def map_file(self, source_path, target_path): """ maps a file from a source path to some target path. The source path is expected to be an absolute path, while the target_path is a relative path, relative to the target's root. """ if source_path.is_file(): clone = shutil.copy elif source_path.is_dir(): clone = shutil.copytree else: print(f"source path {source_path} is not a file or directory") return if not target_path.is_absolute(): target_path = self.target_root / target_path print(f"target path: {target_path}") print(f"target drive: {target_path.drive}") if not target_path.parent.exists(): print("creating missing parent directories for target") parent_dir = target_path.parent parent_dir.mkdir(parents=True) print(f"checking if target path {target_path.parts} exists") exists = os.path.exists(str(target_path)) print(f"exists: {exists}") is_link = os.path.islink(str(target_path)) print(f"is link: {is_link}") if target_path.exists(): print("target path exists") if source_path.is_file(): if target_path.is_file(): print("removing existing regular file") target_path.unlink() else: print("skip: target path exists and is not a regular file") return elif source_path.is_dir(): print("removing existing file tree") shutil.rmtree(target_path) else: print("target path does not exist") print("copying file to target") clone(source_path, target_path) print("")