-
Notifications
You must be signed in to change notification settings - Fork 0
/
settings.py
executable file
·129 lines (109 loc) · 4.09 KB
/
settings.py
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python3
import argparse
import subprocess
import os
import tempfile
from pathlib import Path
def install():
parser = argparse.ArgumentParser(
description='setup dot files in home directory based on git repo')
parser.add_argument('--dryrun', action='store_true', default=False)
parser.add_argument('--no-dryrun', action='store_false', dest='dryrun')
parser.add_argument('--sync', action='store_true')
parser.add_argument('--verbose', action='store_true')
args = parser.parse_args()
args.files_processed = 0
args.files_changed = 0
print(f'dryrun: {args.dryrun} sync: {args.sync} verbose: {args.verbose} ')
if args.sync:
git_sync()
files = [f for f in Path('./dots').glob('*') # Only one level for ~/.blah
if str(f) not in [
'.gitignore',
'Makefile',
'README.md',
]
and os.path.isfile(f)]
config_files = [f for f in Path('.').glob(
'config/**/*') if os.path.isfile(f)]
local_files = [f for f in Path('.').glob('local/**/*') if os.path.isfile(f)]
sheldon_files = [f for f in Path('.').glob(
'sheldon/**/*') if os.path.isfile(f)]
zsh_files = [f for f in Path('.').glob('zsh/**/*') if os.path.isfile(f)]
link_files(files, args, "dots")
link_files(config_files, args, ".")
link_files(local_files, args, ".")
link_files(sheldon_files, args, ".")
link_files(zsh_files, args, ".")
print(
f'finished. Processed: {args.files_processed} Changed: {args.files_changed}')
def link_files(files, args, relative_path):
home_dir = Path.home()
this_dir = Path.cwd()
for file_name in files:
dot_file = os.path.join(
home_dir, '.'+str(file_name.relative_to(relative_path)))
status = get_symlink_status(file_name, dot_file)
args.files_processed += 1
if status == 'same':
continue
args.files_changed += 1
target = os.path.join(this_dir, file_name)
if args.verbose or status != 'same':
print(target + '->' + dot_file + ' :' + status)
if not args.dryrun:
symlink(target, dot_file, args)
def get_symlink_status(target, link_name):
if not os.path.exists(link_name):
return 'new'
if os.path.samefile(target, link_name):
return 'same'
if os.path.islink(link_name):
return 'replace link'
if os.path.isfile(link_name):
return 'replace file'
if os.path.isdir(link_name):
return 'ERROR: directory'
return 'unknown'
def symlink(target, link_name, args, overwrite=True):
'''
Create a symbolic link named link_name pointing to target.
If link_name exists then FileExistsError is raised, unless overwrite=True.
When trying to overwrite a directory, IsADirectoryError is raised.
'''
if not overwrite:
os.symlink(target, link_name)
return
# os.replace() may fail if files are on different filesystems
link_dir = os.path.dirname(link_name)
if not os.path.exists(link_dir):
try:
os.makedirs(link_dir)
except FileExistsError:
pass
# Create link to target with temporary filename
while True:
temp_link_name = link_name + tempfile.gettempprefix()
# os.* functions mimic as closely as possible system functions
# The POSIX symlink() returns EEXIST if link_name already exists
# https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html
try:
os.symlink(target, temp_link_name)
break
except FileExistsError:
pass
# Replace link_name with temp_link_name
try:
# Preempt os.replace on a directory with a nicer message
if os.path.isdir(link_name):
raise IsADirectoryError(
f"Cannot symlink over existing directory: '{link_name}'")
os.replace(temp_link_name, link_name)
except IsADirectoryError:
if os.path.islink(temp_link_name):
os.remove(temp_link_name)
raise
def git_sync():
subprocess.run(['git', 'pull'])
if __name__ == '__main__':
install()