-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.py
More file actions
103 lines (78 loc) · 2.85 KB
/
install.py
File metadata and controls
103 lines (78 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
import argparse
import logging
import os
import shutil
import tomllib
from pathlib import Path
from typing import Literal, TypedDict
logging.basicConfig()
log = logging.getLogger("Install Dotfiles")
log.setLevel(logging.DEBUG)
DeployType = Literal["copy", "symlink", "symlink-children", "hardlink"]
class Data(TypedDict):
source: str
target: str
type: DeployType
LinkError = None | str
def delete_destination(dst: Path):
if dst.exists() or dst.is_symlink():
if dst.is_dir() and not dst.is_symlink():
shutil.rmtree(dst)
else:
dst.unlink()
def link(src: Path, dst: Path) -> LinkError:
delete_destination(dst)
os.symlink(src, dst, src.is_dir())
return None
def run(dry_run: bool = False):
profile_path = Path(__file__).parent / "profiles"
profile = profile_path / "linux.toml"
profile_data: dict[str, Data] = tomllib.loads(profile.read_text())
for dotfile, data in profile_data.items():
source = Path(__file__).parent / "dotfiles" / data["source"]
destination = Path(data["target"]).expanduser()
deploy_type = data.get("type", "copy")
destination.parent.mkdir(parents=True, exist_ok=True)
try:
match deploy_type:
case "copy":
log.info(f"Soft Linking {source} -> {destination}")
if not dry_run:
raise NotImplementedError("Copying files is not implemented")
case "symlink":
log.info(f"Soft Linking {source} -> {destination}")
if not dry_run:
link(source, destination)
case "symlink-children":
log.info(f"Soft Linking Children {source} -> {destination}")
for child_src in source.iterdir():
child_dst = destination / child_src.name
log.info(f"\tSoft Linking {child_src} -> {child_dst}")
if not dry_run:
link(child_src, child_dst)
case "hardlink":
log.info(f"Hard Linking {source} -> {destination}")
if not dry_run:
os.link(source, destination)
except BaseException as err:
log.error(f"Failed because: {err}")
def main():
parser = argparse.ArgumentParser(description="Install dotfiles")
parser.add_argument(
"--dry-run",
action="store_true",
help="Simulate installation without modifying files",
)
args = parser.parse_args()
dry_run = args.dry_run
if dry_run:
global log
log = logging.getLogger("Install Dotfiles -- DRY")
log.setLevel(logging.DEBUG)
run(dry_run)
if __name__ == "__main__":
main()