You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.4 KiB
Python

"""
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("")