forked from mattbrictson/dotfiles
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Rakefile
153 lines (126 loc) · 2.89 KB
/
Rakefile
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Modified from https://github.com/ryanb/dotfiles/
require 'erb'
require 'fileutils'
require 'rake'
IGNORES = %w[
Rakefile README.md LICENSE node_modules package.json package-lock.json
]
task default: :install
desc 'Install packages and dotfiles'
task install: ['install:packages', 'install:dotfiles']
namespace :install do
desc 'Install homebrew packages, set sensible defaults'
task :packages do
%w(brew defaults).each do |type|
log(:blue, "executing bin/#{type}-install …")
system("bin/#{type}-install")
end
end
task :dotfiles do
desc 'Install dotfiles into your home directory'
replace_all = false
Dotfile.each do |dotfile|
case dotfile.status
when :identical
log(:green, "identical #{dotfile}")
when :missing
dotfile.link!
when :different
if replace_all
dotfile.replace!
elsif (answer = ask(:red, "overwrite #{dotfile}?"))
replace_all = true if answer == :all
dotfile.replace!
else
log(:gray, "skipping #{dotfile}")
end
end
end
end
end
def log(color, message, options={})
require "highline" rescue nil
first, rest = message.split(" ", 2)
first = first.ljust(10)
if defined?(HighLine::String)
first = HighLine::String.new(first).public_send(color)
end
line = [first, rest].join(" ")
if line.end_with?(" ")
print(line)
else
puts(line)
end
end
def ask(color, question)
log(color, "#{question} [yNaq]? ")
case $stdin.gets.chomp
when "a"
:all
when "y"
true
when "q"
exit
else
false
end
end
class Dotfile
def self.each(directory=nil, &block)
Dir[File.join([directory, "*"].compact)].each do |file|
next if IGNORES.include?(file)
if File.directory?(file)
each(file, &block)
else
yield(new(file))
end
end
end
attr_reader :file
def initialize(file)
@file = file
end
def erb?
file =~ /\.erb\z/i
end
def name
".#{file.sub(/\.erb\z/i, "")}"
end
alias :to_s :name
def target
File.expand_path("~/#{name}")
end
def status
if File.identical?(file, target)
:identical
elsif File.exist?(target) || File.symlink?(target)
:different
else
:missing
end
end
def link!
ensure_target_directory
if erb?
log(:yellow, "generating #{self}")
contents = ERB.new(File.read(file)).result(binding)
log(:blue, "writing #{self}")
File.open(target, "w") do |out|
out << contents
end
else
log(:blue, "linking #{self}")
FileUtils.ln_s(File.absolute_path(file), target)
end
end
def replace!
FileUtils.rm_rf(target)
link!
end
def ensure_target_directory
directory = File.dirname(target)
return if File.directory?(directory)
log(:magenta, "creating #{File.dirname(name)}")
FileUtils.mkdir_p(directory)
end
end