Skip to content

Commit fc84b7b

Browse files
committed
Merge pull request #1 from acm-uiuc/master
pull in update script
2 parents ac63e8b + 32bee2d commit fc84b7b

File tree

4 files changed

+222
-151
lines changed

4 files changed

+222
-151
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.nfs.*
44
answerback.Linux
55
answerback.Darwin
6+
gitprivate

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Installation
2-
Install by executing `install.pl` from within the acmdots directory.
2+
Install by executing `install.py`.
3+
See `install.py --help` for more information.

install.pl

Lines changed: 0 additions & 150 deletions
This file was deleted.

install.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#! /usr/bin/env python
2+
3+
import os
4+
import os.path
5+
import optparse
6+
import shutil
7+
8+
links = {
9+
'screenrc': '.screenrc',
10+
'ackrc': '.ackrc',
11+
'toprc': '.toprc',
12+
'dir_colors': '.dir_colors',
13+
'lessfilter': '.lessfilter',
14+
15+
'vim': '.vim',
16+
'vimrc': '.vimrc',
17+
'_vimrc': '_vimrc',
18+
'gvimrc': '.gvimrc',
19+
20+
'emacsrc': '.emacs',
21+
'emacs': '.emacsdir',
22+
23+
'commonsh': '.commonsh',
24+
25+
'inputrc': '.inputrc',
26+
27+
'bash': '.bash',
28+
'bashrc': '.bashrc',
29+
'bash_profile': '.bash_profile',
30+
31+
'zsh': '.zsh',
32+
'zshrc': '.zshrc',
33+
34+
'ksh': '.ksh',
35+
'kshrc': '.kshrc',
36+
'mkshrc': '.mkshrc',
37+
38+
'shinit': '.shinit',
39+
40+
'Xdefaults': '.Xdefaults',
41+
'Xresources': '.Xresources',
42+
43+
'uncrustify.cfg': '.uncrustify.cfg',
44+
'indent.pro': '.indent.pro',
45+
46+
'xmobarrc': '.xmobarrc',
47+
'xmonad.hs': '.xmonad/xmonad.hs',
48+
49+
'Wombat.xccolortheme': 'Library/Application Support/Xcode/Color Themes/Wombat.xccolortheme',
50+
# 'Wombat.dvtcolortheme': 'Library/Developer/Xcode/UserData/FontAndColorThemes/Wombat.dvtcolortheme',
51+
52+
'gitconfig': '.gitconfig',
53+
'gitignore': '.gitignore',
54+
55+
'tigrc': '.tigrc',
56+
57+
'caffeinate': 'bin/caffeinate',
58+
'lock': 'bin/lock',
59+
60+
'git-info': 'bin/git-info',
61+
'git-untrack-ignored': 'bin/git-untracked-ignored',
62+
63+
'gdbinit': '.gdbinit',
64+
}
65+
66+
scriptdir = os.path.dirname(os.path.realpath(__file__))
67+
home = os.path.expanduser('~')
68+
contained = os.path.commonprefix([scriptdir, home]) == home
69+
70+
def read_link_abs(path):
71+
"""Read the absolute path to which the symbolic link points.
72+
73+
Args:
74+
path - path to the link
75+
Returns:
76+
the target absolute path or the empty string if path isn't a link
77+
"""
78+
if not os.path.islink(path):
79+
return ''
80+
81+
target = os.path.join(os.path.dirname(path), os.readlink(path))
82+
return os.path.abspath(target)
83+
84+
def uninstall(file):
85+
"""Uninstall a file.
86+
87+
Args:
88+
file - the file to uninstall
89+
Returns:
90+
True if the file was uninstalled, False otherwise
91+
"""
92+
src = os.path.join(scriptdir, file)
93+
dest = os.path.join(home, links[file])
94+
95+
# Only remove if it's a link to a dotfile in the repo
96+
if read_link_abs(dest) != src:
97+
return False
98+
99+
os.remove(dest)
100+
101+
# Remove empty directories that contained the link
102+
dir = os.path.dirname(dest)
103+
while dir and not os.listdir(dir):
104+
os.rmdir(dir)
105+
dir = os.path.dirname(dir)
106+
107+
return True
108+
109+
def uninstall_all():
110+
uname = os.uname()[0]
111+
links['answerback.' + uname] = 'bin/answerback.' + uname
112+
links['gitprivate'] = '.gitprivate'
113+
114+
i = 0; # Keep track of how many links we remove
115+
for file in links:
116+
if uninstall(file):
117+
i += 1
118+
119+
print '{0:d} link{1} removed'.format(i, 's' if i != 1 else '')
120+
121+
def install(file, force=False):
122+
"""Install a file.
123+
124+
Args:
125+
file - the file to install
126+
force - whether to overwrite existing files
127+
Returns:
128+
True if the file was installed, False otherwise
129+
"""
130+
src = os.path.join(scriptdir, file)
131+
dest = os.path.join(home, links[file])
132+
path = os.path.dirname(dest)
133+
134+
# If needed, create the directory this file resides in
135+
if not os.path.exists(path):
136+
os.makedirs(path)
137+
138+
if os.path.exists(dest):
139+
if force:
140+
# Remove the destination if it exists
141+
if os.path.isdir(dest) and not os.path.islink(dest):
142+
shutil.rmtree(dest)
143+
else:
144+
os.remove(dest)
145+
else:
146+
# If a link already exists, see if it points to this file
147+
# to prevent extra warnings caused by previous runs
148+
if read_link_abs(dest) != src:
149+
print 'Could not link "{0}" to "{1}": File exists'.format(src, dest)
150+
return False
151+
152+
# Use relative links if the dotfiles are contained in home
153+
if contained:
154+
os.chdir(home)
155+
src = os.path.relpath(src, path)
156+
dest = links[file]
157+
158+
os.symlink(src, dest)
159+
return True
160+
161+
def install_all(force=False):
162+
# Compile answerback and add it to links
163+
uname = os.uname()[0]
164+
answerback_src = os.path.join(scriptdir, 'answerback.c')
165+
answerback_bin = os.path.join(scriptdir, 'answerback.' + uname)
166+
if os.system('cc {0} -o {1}'.format(answerback_src, answerback_bin)) == 0:
167+
links['answerback.' + uname] = 'bin/answerback.' + uname
168+
else:
169+
print 'Could not compile answerback.'
170+
171+
# Create private git config and add it to links
172+
if not os.path.exists(os.path.join(scriptdir, 'gitprivate')):
173+
name = raw_input('Full name for Git config (enter to skip): ')
174+
email = raw_input('Email address for Git config (enter to skip): ')
175+
if name or email:
176+
with open(os.path.join(scriptdir, 'gitprivate'), 'w') as config:
177+
config.write('[user]\n')
178+
if name:
179+
config.write('\tname = ' + name + '\n')
180+
if email:
181+
config.write('\temail = ' + email + '\n')
182+
links['gitprivate'] = '.gitprivate'
183+
else:
184+
links['gitprivate'] = '.gitprivate'
185+
186+
i = 0; # Keep track of how many links we added
187+
for file in links:
188+
if install(file, force):
189+
i += 1
190+
191+
print '{0:d} link{1} created'.format(i, 's' if i != 1 else '')
192+
193+
def main():
194+
class RawHelpFormatter(optparse.IndentedHelpFormatter):
195+
def format_description(self, description):
196+
return description + '\n'
197+
198+
# Parse arguments
199+
parser = optparse.OptionParser(
200+
usage='usage: %prog [-h] [-u] [-f]',
201+
formatter=RawHelpFormatter(),
202+
description= \
203+
"""Installs symbolic links from dotfile repo into your home directory
204+
205+
Destination directory is "{0}".
206+
Source files are in "{1}".""".format(home, scriptdir))
207+
parser.add_option('-u', '--uninstall', action='store_true',
208+
help='unlink dotfiles from your home directory')
209+
parser.add_option('-f', '--force', action='store_true',
210+
help='force to overwrite existing files')
211+
args, _ = parser.parse_args()
212+
213+
if args.uninstall:
214+
uninstall_all()
215+
else:
216+
install_all(args.force)
217+
218+
if __name__ == '__main__':
219+
main()

0 commit comments

Comments
 (0)