dotfiles-installer 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +26 -0
- data/README.rdoc +112 -0
- data/Rakefile +7 -0
- data/dotfiles-installer.gemspec +24 -0
- data/lib/dotfiles-installer.rb +1 -0
- data/lib/dotfiles_installer.rb +73 -0
- data/lib/dotfiles_installer/actions.rb +49 -0
- data/lib/dotfiles_installer/runner.rb +94 -0
- data/lib/dotfiles_installer/utilities.rb +31 -0
- data/lib/dotfiles_installer/version.rb +3 -0
- data/test/actions_test.rb +91 -0
- data/test/fixtures/sourcedir/bash/aliases +0 -0
- data/test/fixtures/sourcedir/bash/colors +0 -0
- data/test/fixtures/sourcedir/bin/a_script +0 -0
- data/test/fixtures/sourcedir/bin/~also_ignored +0 -0
- data/test/fixtures/sourcedir/gemrc +0 -0
- data/test/fixtures/sourcedir/gitconfig.erb +1 -0
- data/test/fixtures/sourcedir/gitignore +0 -0
- data/test/fixtures/sourcedir/ignored_file +0 -0
- data/test/fixtures/sourcedir/irbrc +0 -0
- data/test/helper.rb +53 -0
- data/test/installer_test.rb +73 -0
- data/test/irb.rb +9 -0
- data/test/runner_test.rb +16 -0
- metadata +146 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dotfiles-installer (1.0.0)
|
5
|
+
ansi (~> 1.3)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ansi (1.3.0)
|
11
|
+
assert (0.6.0)
|
12
|
+
assert-view (~> 0.3)
|
13
|
+
assert-view (0.3.0)
|
14
|
+
ansi (~> 1.3)
|
15
|
+
undies (~> 1.1)
|
16
|
+
rake (0.9.2)
|
17
|
+
undies (1.1.0)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
assert
|
24
|
+
bundler
|
25
|
+
dotfiles-installer!
|
26
|
+
rake (~> 0.9.2)
|
data/README.rdoc
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
= DotfilesInstaller
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
This gem installs safely installs dotfiles into your $HOME
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
gem install dotfiles-installer
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
I prefer to use this in a Rakefile. I build an :install rake task and put the installer in there. Check out my dotfiles repo for an example: .
|
14
|
+
|
15
|
+
You can run the installer from any Ruby script:
|
16
|
+
|
17
|
+
require 'dotfiles_installer'
|
18
|
+
|
19
|
+
First, create an installer, passing it the source directory where your dotfiles are stored:
|
20
|
+
|
21
|
+
installer = DotfilesInstaller::Interactive.new("~/.dotfiles")
|
22
|
+
|
23
|
+
You can optionally pass an argument for the home dir to install to (defaults to $HOME).
|
24
|
+
|
25
|
+
Finally, just tell the installer to install its dotfiles:
|
26
|
+
|
27
|
+
installer.install
|
28
|
+
|
29
|
+
== How it Installs
|
30
|
+
The installer attempts to safely install dotfiles. What I mean is that, in addition to symlinking any root files, it will create dot-directories for any nested dotfiles instead of just symlinking the root directory. This means you can install multiple sets of dotfiles from different source. As long as they don't have the same relative paths, you're good. It's really easier to just show how this works:
|
31
|
+
|
32
|
+
So, given a source of dotfiles, say at ~/.dotfiles:
|
33
|
+
|
34
|
+
bash
|
35
|
+
| aliases
|
36
|
+
| colors
|
37
|
+
bin
|
38
|
+
| a_script
|
39
|
+
gemrc
|
40
|
+
gitconfig.erb
|
41
|
+
gitignore
|
42
|
+
irbrc
|
43
|
+
|
44
|
+
Installs into the $HOME as:
|
45
|
+
|
46
|
+
.bash
|
47
|
+
| aliases -> /Users/xxx/.dotfiles/bash/aliases
|
48
|
+
| colors -> /Users/xxx/.dotfiles/bash/colors
|
49
|
+
.bin
|
50
|
+
| a_script -> /Users/xxx/.dotfiles/bin/a_script
|
51
|
+
.gemrc -> /Users/xxx/.dotfiles/gemrc
|
52
|
+
.gitconfig -> /Users/xxx/.dotfiles/~gitconfig
|
53
|
+
.gitignore -> /Users/xxx/.dotfiles/gitignore
|
54
|
+
.irbrc -> /Users/xxx/.dotfiles/irbrc
|
55
|
+
|
56
|
+
== Other Stuff
|
57
|
+
|
58
|
+
=== It uninstalls
|
59
|
+
The installer can clean itself up. If you want to remove a source's dotfiles, spin up an installer and tell it to uninstall:
|
60
|
+
|
61
|
+
DotfilesInstaller::Interactive.new("~/.dotfiles").uninstall
|
62
|
+
|
63
|
+
Not only will it remove all dotfile symlinks, it will remove any directories it made for the symlinks (assuming they are empty).
|
64
|
+
|
65
|
+
=== It's Interactive
|
66
|
+
I've named the installer class DotfilesInstaller::Interactive for a reason. The installer keeps you in the loop on what its doing. If it detects conflicts on install, it will ask what you want to do. It will prompt before removing anything on uninstall.
|
67
|
+
|
68
|
+
=== ERB evaluation
|
69
|
+
You'll notice in the above example, the gitconfig source dotfile is an erb file. Any source files with a '.erb' extension are rendered using ERB. The rendered source file is cached alongside the original source with the '~' prefix. This cached file is linked to the home.
|
70
|
+
|
71
|
+
If you store your dotfiles in git, you can add a gitignore for these cached files to keep them out of your repo.
|
72
|
+
|
73
|
+
=== Auto Ignored source files
|
74
|
+
Any source file whos name begins with a '~' is ignored by the installer.
|
75
|
+
|
76
|
+
=== Manually ignoring source files
|
77
|
+
If you want some files in the source to be ignored but don't want to rename it with a '~' (say a README or something), pass in an :ignored_filenames option:
|
78
|
+
|
79
|
+
installer = DotfilesInstaller::Interactive.new("~/.dotfiles"), {
|
80
|
+
:ignored_filenames => %w[README Gemfile Rakefile]
|
81
|
+
})
|
82
|
+
|
83
|
+
You can specify :ignored_filenames using strings or regular expressions. Any file whos name matches one of these will be ignored by the installer.
|
84
|
+
|
85
|
+
== I wrote this for me
|
86
|
+
|
87
|
+
I also use this to install private dotfiles as part of my machine build script. I also use this in some rake tasks on my dotfiles repo (). Check it out the rake tasks and the repo setup for a usage example.
|
88
|
+
|
89
|
+
== License
|
90
|
+
|
91
|
+
Copyright (c) 2011 Kelly Redding
|
92
|
+
|
93
|
+
Permission is hereby granted, free of charge, to any person
|
94
|
+
obtaining a copy of this software and associated documentation
|
95
|
+
files (the "Software"), to deal in the Software without
|
96
|
+
restriction, including without limitation the rights to use,
|
97
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
98
|
+
copies of the Software, and to permit persons to whom the
|
99
|
+
Software is furnished to do so, subject to the following
|
100
|
+
conditions:
|
101
|
+
|
102
|
+
The above copyright notice and this permission notice shall be
|
103
|
+
included in all copies or substantial portions of the Software.
|
104
|
+
|
105
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
106
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
107
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
108
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
109
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
110
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
111
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
112
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dotfiles_installer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dotfiles-installer"
|
7
|
+
s.version = DotfilesInstaller::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Kelly Redding"]
|
10
|
+
s.email = ["kelly@kelredd.com"]
|
11
|
+
s.homepage = "http://github.com/kelredd/dotfiles-installer"
|
12
|
+
s.summary = %q{Safely install dotfiles into your home dir.}
|
13
|
+
s.description = %q{Safely install dotfiles into your home dir.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency("bundler")
|
21
|
+
s.add_development_dependency("assert")
|
22
|
+
|
23
|
+
s.add_dependency("ansi", ["~> 1.3"])
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'dotfiles_installer'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'ansi'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module DotfilesInstaller; end
|
5
|
+
|
6
|
+
require 'dotfiles_installer/actions'
|
7
|
+
require 'dotfiles_installer/utilities'
|
8
|
+
require 'dotfiles_installer/runner'
|
9
|
+
|
10
|
+
# The dotfiles installer parses a sourcedir and links files to a homedir:
|
11
|
+
# - The installer provides install and uninstall commands that guide and update
|
12
|
+
# as it performs its linkings.
|
13
|
+
# - Any source files with the '.erb' extension are rendered then linked
|
14
|
+
# - Nested files are linked to a corresponding dir made in the homedir
|
15
|
+
# - Uninstalls remove each symlink and its dir (if empty)
|
16
|
+
|
17
|
+
# the sourcedir, ~/.dotfiles:
|
18
|
+
# - bash
|
19
|
+
# - aliases
|
20
|
+
# - colors
|
21
|
+
# - bin
|
22
|
+
# - a_script
|
23
|
+
# - gemrc
|
24
|
+
# - gitconfig.erb
|
25
|
+
# - gitignore
|
26
|
+
# _ irbrc
|
27
|
+
|
28
|
+
# installs in the homedir, ~:
|
29
|
+
# - .bash
|
30
|
+
# - aliases --> /Users/xxx/.dotfiles/bash/aliases
|
31
|
+
# - colors --> /Users/xxx/.dotfiles/bash/colors
|
32
|
+
# - .bin
|
33
|
+
# - a_script --> /Users/xxx/.dotfiles/bin/a_script
|
34
|
+
# - .gemrc --> /Users/xxx/.dotfiles/gemrc
|
35
|
+
# - .gitconfig --> /Users/xxx/.dotfiles/~gitconfig
|
36
|
+
# - .gitignore --> /Users/xxx/.dotfiles/gitignore
|
37
|
+
# _ .irbrc --> /Users/xxx/.dotfiles/irbrc
|
38
|
+
|
39
|
+
module DotfilesInstaller
|
40
|
+
|
41
|
+
class Base
|
42
|
+
include Utilities
|
43
|
+
|
44
|
+
attr_reader :sourcedir, :homedir, :options
|
45
|
+
|
46
|
+
def initialize(sourcedir, *args)
|
47
|
+
@sourcedir = sourcedir
|
48
|
+
@options = args.last.kind_of?(::Hash) ? args.pop : {}
|
49
|
+
@homedir = args.pop || ENV["HOME"]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# run the install or uninstall printing to $stdout and reading from $stdin
|
55
|
+
class Interactive < Base
|
56
|
+
|
57
|
+
def install
|
58
|
+
Runner.new($stdout).install(self.source_map) do |prompt, inputs|
|
59
|
+
$stdout.print "#{prompt} #{inputs} "
|
60
|
+
$stdin.gets.chomp
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def uninstall
|
65
|
+
Runner.new($stdout).uninstall(self.source_map) do |prompt, inputs|
|
66
|
+
$stdout.print "#{prompt} #{inputs} "
|
67
|
+
$stdin.gets.chomp
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module DotfilesInstaller::Actions
|
2
|
+
|
3
|
+
def replace(home_path, source_path)
|
4
|
+
[ self.remove_path(home_path),
|
5
|
+
self.create(source_path, home_path)
|
6
|
+
].flatten
|
7
|
+
end
|
8
|
+
|
9
|
+
def remove(home_path)
|
10
|
+
self.out("uninstalled #{home_path}")
|
11
|
+
[ self.remove_path(home_path),
|
12
|
+
self.remove_dir_if_empty(home_path)
|
13
|
+
].flatten
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove_path(path)
|
17
|
+
[ %Q{rm -f "#{self.ep(path)}"} ]
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove_dir_if_empty(home_path)
|
21
|
+
[ %Q{rmdir -p "#{File.dirname(self.ep(home_path))}" 2> /dev/null} ]
|
22
|
+
end
|
23
|
+
|
24
|
+
def create(source_path, home_path)
|
25
|
+
self.out("installed #{home_path}")
|
26
|
+
[ self.makedir(home_path),
|
27
|
+
self.link(source_path =~ /.erb$/ ? generate(source_path) : source_path, home_path)
|
28
|
+
].flatten
|
29
|
+
end
|
30
|
+
|
31
|
+
def makedir(home_path)
|
32
|
+
[ %Q{mkdir -p "#{self.ep(File.dirname(home_path))}"} ]
|
33
|
+
end
|
34
|
+
|
35
|
+
def link(source_path, home_path)
|
36
|
+
[ %Q{ln -s "#{self.ep(source_path)}" "#{self.ep(home_path)}"} ]
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate(source_path)
|
40
|
+
source_path_dirname = File.dirname(File.expand_path(source_path))
|
41
|
+
gen_source_filename = "~#{File.basename(source_path, ".erb")}"
|
42
|
+
gen_source_path = File.join(source_path_dirname, gen_source_filename)
|
43
|
+
File.open(gen_source_path, 'w') do |gen_source_file|
|
44
|
+
gen_source_file.write ERB.new(File.read(File.expand_path(source_path))).result(binding)
|
45
|
+
end
|
46
|
+
gen_source_path
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'ansi'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
require 'dotfiles_installer/actions'
|
5
|
+
|
6
|
+
module DotfilesInstaller
|
7
|
+
|
8
|
+
class Runner
|
9
|
+
include Actions
|
10
|
+
|
11
|
+
attr_reader :output_io
|
12
|
+
|
13
|
+
def initialize(output_io, options={})
|
14
|
+
@output_io = output_io
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def install(source_map, &block)
|
19
|
+
replace_all = false
|
20
|
+
|
21
|
+
source_map.each do |source_path, home_path|
|
22
|
+
if !File.exist? self.ep(home_path)
|
23
|
+
self.execute(self.create(source_path, home_path))
|
24
|
+
next
|
25
|
+
end
|
26
|
+
|
27
|
+
if File.identical? self.ep(source_path), self.ep(home_path)
|
28
|
+
self.out "identical #{home_path}"
|
29
|
+
elsif replace_all
|
30
|
+
self.execute(self.replace(home_path, source_path))
|
31
|
+
else
|
32
|
+
case (block_given? ? yield("overwrite #{home_path}?", "[ynaq]") : "")
|
33
|
+
when 'a'
|
34
|
+
replace_all = true
|
35
|
+
self.execute(self.replace(home_path, source_path))
|
36
|
+
when 'y'
|
37
|
+
self.execute(self.replace(home_path, source_path))
|
38
|
+
when 'q'
|
39
|
+
exit
|
40
|
+
else
|
41
|
+
self.out "skipping #{home_path}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def uninstall(source_map)
|
49
|
+
remove_all = false
|
50
|
+
|
51
|
+
source_map.each do |source_path, home_path|
|
52
|
+
if !File.exist? self.ep(home_path)
|
53
|
+
next
|
54
|
+
end
|
55
|
+
|
56
|
+
if remove_all
|
57
|
+
self.execute(self.remove(home_path))
|
58
|
+
else
|
59
|
+
case (block_given? ? yield("remove #{home_path}?", "[ynaq]") : "")
|
60
|
+
when 'a'
|
61
|
+
remove_all = true
|
62
|
+
self.execute(self.remove(home_path))
|
63
|
+
when 'y'
|
64
|
+
self.execute(self.remove(home_path))
|
65
|
+
when 'q'
|
66
|
+
exit
|
67
|
+
else
|
68
|
+
self.out "skipping #{home_path}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def execute(commands)
|
78
|
+
commands.flatten.each do |cmd|
|
79
|
+
out(" => #{cmd}") if @options[:debug]
|
80
|
+
system(cmd)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def out(msg)
|
85
|
+
@output_io.puts(msg) if @output_io
|
86
|
+
end
|
87
|
+
|
88
|
+
def ep(path)
|
89
|
+
File.expand_path(path)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DotfilesInstaller::Utilities
|
2
|
+
|
3
|
+
# nested source paths for not-ignored files
|
4
|
+
def source_paths
|
5
|
+
Dir["#{File.expand_path(self.sourcedir)}/**/*"].
|
6
|
+
select { |path| File.file?(path) }.
|
7
|
+
reject { |path| ignored_file?(path) }
|
8
|
+
end
|
9
|
+
|
10
|
+
# create a hash of soure_path keys with home_path values
|
11
|
+
def source_map
|
12
|
+
self.source_paths.inject({}) do |map, path|
|
13
|
+
map[path] = self.home_path(path)
|
14
|
+
map
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def home_path(source_path)
|
21
|
+
source_path.
|
22
|
+
gsub(/^#{File.expand_path(self.sourcedir)}\//, "#{self.homedir}/.").
|
23
|
+
gsub(/.erb$/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
def ignored_file?(path)
|
27
|
+
path_bn = File.basename(path)
|
28
|
+
(self.options[:ignored_filenames] || []).include?(path_bn) || path_bn =~ /^~/
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'assert'
|
2
|
+
|
3
|
+
module DotfilesInstaller
|
4
|
+
|
5
|
+
class CommandActionsTests < Assert::Context
|
6
|
+
desc "the command_list actions"
|
7
|
+
before { @runner = ::TestRunner.new }
|
8
|
+
subject { @runner }
|
9
|
+
|
10
|
+
should have_instance_methods :replace, :remove, :create
|
11
|
+
should have_instance_methods :makedir, :generate, :link
|
12
|
+
|
13
|
+
should "link source paths" do
|
14
|
+
exp_cmds = [
|
15
|
+
%Q{ln -s "#{File.expand_path("source_path")}" "#{File.expand_path("home_dir/path")}"}
|
16
|
+
]
|
17
|
+
|
18
|
+
assert_equal exp_cmds, subject.link("source_path", "home_dir/path")
|
19
|
+
end
|
20
|
+
|
21
|
+
should "make home dirs" do
|
22
|
+
exp_cmds = [ %Q{mkdir -p "#{File.expand_path("home_dir")}"} ]
|
23
|
+
assert_equal exp_cmds, subject.makedir("home_dir/path")
|
24
|
+
end
|
25
|
+
|
26
|
+
should "remove home paths" do
|
27
|
+
exp_cmds = [
|
28
|
+
%Q{rm -f "#{File.expand_path("home_path")}"},
|
29
|
+
%Q{rmdir -p "#{File.dirname(File.expand_path("home_path"))}" 2> /dev/null}
|
30
|
+
]
|
31
|
+
|
32
|
+
assert_equal exp_cmds, subject.remove("home_path")
|
33
|
+
end
|
34
|
+
|
35
|
+
should "replace home paths" do
|
36
|
+
exp_cmds = [
|
37
|
+
%Q{rm -f "#{File.expand_path("home_dir/path")}"},
|
38
|
+
%Q{mkdir -p "#{File.expand_path("home_dir")}"},
|
39
|
+
%Q{ln -s "#{File.expand_path("source_path")}" "#{File.expand_path("home_dir/path")}"}
|
40
|
+
]
|
41
|
+
|
42
|
+
assert_equal exp_cmds, subject.replace("home_dir/path", "source_path")
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
class CreateActionsTests < CommandActionsTests
|
48
|
+
|
49
|
+
setup do
|
50
|
+
@reg_source_path = File.join(TESTDIRS_SOURCE, "gitignore")
|
51
|
+
@reg_home_path = File.join(TESTDIRS_HOME, ".gitignore")
|
52
|
+
@erb_source_path = File.join(TESTDIRS_SOURCE, "gitconfig.erb")
|
53
|
+
@erb_home_path = File.join(TESTDIRS_HOME, ".gitconfig")
|
54
|
+
@gen_erb_source_path = subject.generate(@erb_source_path)
|
55
|
+
end
|
56
|
+
teardown do
|
57
|
+
FileUtils.rm(@gen_erb_source_path) if File.exists?(@gen_erb_source_path)
|
58
|
+
end
|
59
|
+
|
60
|
+
should "generate a ~ prefixed file in the sourcedir when generating" do
|
61
|
+
assert File.exists?(@gen_erb_source_path)
|
62
|
+
assert_equal '~gitconfig', File.basename(@gen_erb_source_path)
|
63
|
+
assert_equal "this was rendered", File.read(@gen_erb_source_path).strip
|
64
|
+
end
|
65
|
+
|
66
|
+
should "create an erb dotfile by generating then linking to the generated source file" do
|
67
|
+
# clear this part of the setup for this test
|
68
|
+
FileUtils.rm(@gen_erb_source_path)
|
69
|
+
@gen_erb_source_path = File.join(TESTDIRS_SOURCE, "~gitconfig")
|
70
|
+
|
71
|
+
exp_cmds = [
|
72
|
+
%Q{mkdir -p "#{File.expand_path(File.dirname(@erb_home_path))}"},
|
73
|
+
%Q{ln -s "#{File.expand_path(@gen_erb_source_path)}" "#{File.expand_path(@erb_home_path)}"}
|
74
|
+
]
|
75
|
+
|
76
|
+
assert_equal exp_cmds, subject.create(@erb_source_path, @erb_home_path)
|
77
|
+
assert File.exists?(@gen_erb_source_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
should "create a reg dotfile by just linking to the source file directly" do
|
81
|
+
exp_cmds = [
|
82
|
+
%Q{mkdir -p "#{File.expand_path(File.dirname(@reg_home_path))}"},
|
83
|
+
%Q{ln -s "#{File.expand_path(@reg_source_path)}" "#{File.expand_path(@reg_home_path)}"}
|
84
|
+
]
|
85
|
+
|
86
|
+
assert_equal exp_cmds, subject.create(@reg_source_path, @reg_home_path)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= "this was rendered" %>
|
File without changes
|
File without changes
|
File without changes
|
data/test/helper.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# this file is automatically required in when you require 'assert' in your tests
|
2
|
+
# put test helpers here
|
3
|
+
|
4
|
+
# add root dir to the load path
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'dotfiles_installer'
|
9
|
+
|
10
|
+
FIXTURE_SOURCEDIR = "test/fixtures/sourcedir"
|
11
|
+
FIXTURE_HOMEDIR = "test/fixtures/homedir"
|
12
|
+
TESTDIRS_ROOT = "testdirs"
|
13
|
+
TESTDIRS_SOURCE = "#{TESTDIRS_ROOT}/sourcedir"
|
14
|
+
TESTDIRS_HOME = "#{TESTDIRS_ROOT}/homedir"
|
15
|
+
|
16
|
+
class TestRunner < ::DotfilesInstaller::Runner
|
17
|
+
def initialize
|
18
|
+
super(nil, {:debug => true})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class TestInstaller < ::DotfilesInstaller::Base
|
23
|
+
def initialize
|
24
|
+
super(TESTDIRS_SOURCE, TESTDIRS_HOME, {
|
25
|
+
:ignored_filenames => %w[ignored_file]
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
# force the install or uninstall on all files
|
30
|
+
def install
|
31
|
+
TestRunner.new.install(self.source_map) { |p, i| 'a' }
|
32
|
+
end
|
33
|
+
|
34
|
+
def uninstall
|
35
|
+
TestRunner.new.uninstall(self.source_map) { |p, i| 'a' }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Assert::Context
|
40
|
+
startup do
|
41
|
+
FileUtils.mkdir_p(TESTDIRS_SOURCE)
|
42
|
+
FileUtils.mkdir_p(TESTDIRS_HOME)
|
43
|
+
FileUtils.cp_r(FIXTURE_SOURCEDIR, TESTDIRS_ROOT)
|
44
|
+
end
|
45
|
+
shutdown do
|
46
|
+
FileUtils.rm_rf(TESTDIRS_ROOT)
|
47
|
+
end
|
48
|
+
|
49
|
+
before do
|
50
|
+
@installer = TestInstaller.new
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'assert'
|
2
|
+
|
3
|
+
module DotfilesInstaller
|
4
|
+
|
5
|
+
class InstallerTests < Assert::Context
|
6
|
+
desc "a basic installer"
|
7
|
+
before do
|
8
|
+
@source_files = [
|
9
|
+
"bash/aliases",
|
10
|
+
"bash/colors",
|
11
|
+
"bin/a_script",
|
12
|
+
"gemrc",
|
13
|
+
"gitconfig.erb",
|
14
|
+
"gitignore",
|
15
|
+
"irbrc"
|
16
|
+
]
|
17
|
+
end
|
18
|
+
subject { @installer }
|
19
|
+
|
20
|
+
should have_readers :sourcedir, :homedir, :options
|
21
|
+
should have_instance_methods :source_paths, :install, :uninstall
|
22
|
+
|
23
|
+
should "know its source files and ignore any :ignored_filenames" do
|
24
|
+
source_paths = subject.source_paths
|
25
|
+
|
26
|
+
assert_equal 7, source_paths.size
|
27
|
+
@source_files.collect{|f| File.expand_path("./#{TESTDIRS_SOURCE}/#{f}")}.each do |path|
|
28
|
+
assert_included path, source_paths
|
29
|
+
end
|
30
|
+
assert_not_included File.expand_path("./#{TESTDIRS_SOURCE}/ignored_file"), source_paths
|
31
|
+
assert_not_included File.expand_path("./#{TESTDIRS_SOURCE}/bin/~also_ignored"), source_paths
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class InstallTests < InstallerTests
|
37
|
+
desc "running an install"
|
38
|
+
before do
|
39
|
+
FileUtils.rm_rf(TESTDIRS_HOME)
|
40
|
+
|
41
|
+
@exp_linked_files = @source_files.collect do |f|
|
42
|
+
File.join(TESTDIRS_HOME, ".#{f}").gsub(/.erb/, '')
|
43
|
+
end
|
44
|
+
@installer.install
|
45
|
+
end
|
46
|
+
|
47
|
+
should "link up the sourcedir files to the homedir" do
|
48
|
+
@exp_linked_files.each do |home_path|
|
49
|
+
assert File.symlink?(home_path), "#{home_path} is not a symlink"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class UninstallTests < InstallTests
|
56
|
+
desc "then running an uninstall"
|
57
|
+
before { @installer.uninstall }
|
58
|
+
|
59
|
+
should "rm all homedir links and any empty homedir dirs" do
|
60
|
+
@exp_linked_files.each do |home_path|
|
61
|
+
assert !File.exists?(home_path), "#{home_path} exists"
|
62
|
+
end
|
63
|
+
|
64
|
+
home_bash = File.join(TESTDIRS_HOME, ".bash")
|
65
|
+
home_bin = File.join(TESTDIRS_HOME, ".bin")
|
66
|
+
|
67
|
+
assert !File.exists?(home_bash), "#{home_bash} exists"
|
68
|
+
assert !File.exists?(home_bin), "#{home_bin} exists"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
data/test/irb.rb
ADDED
data/test/runner_test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dotfiles-installer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Kelly Redding
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
version_requirements: *id001
|
33
|
+
name: bundler
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
version_requirements: *id002
|
47
|
+
name: assert
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 9
|
57
|
+
segments:
|
58
|
+
- 1
|
59
|
+
- 3
|
60
|
+
version: "1.3"
|
61
|
+
version_requirements: *id003
|
62
|
+
name: ansi
|
63
|
+
description: Safely install dotfiles into your home dir.
|
64
|
+
email:
|
65
|
+
- kelly@kelredd.com
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- Gemfile
|
75
|
+
- Gemfile.lock
|
76
|
+
- README.rdoc
|
77
|
+
- Rakefile
|
78
|
+
- dotfiles-installer.gemspec
|
79
|
+
- lib/dotfiles-installer.rb
|
80
|
+
- lib/dotfiles_installer.rb
|
81
|
+
- lib/dotfiles_installer/actions.rb
|
82
|
+
- lib/dotfiles_installer/runner.rb
|
83
|
+
- lib/dotfiles_installer/utilities.rb
|
84
|
+
- lib/dotfiles_installer/version.rb
|
85
|
+
- test/actions_test.rb
|
86
|
+
- test/fixtures/sourcedir/bash/aliases
|
87
|
+
- test/fixtures/sourcedir/bash/colors
|
88
|
+
- test/fixtures/sourcedir/bin/a_script
|
89
|
+
- test/fixtures/sourcedir/bin/~also_ignored
|
90
|
+
- test/fixtures/sourcedir/gemrc
|
91
|
+
- test/fixtures/sourcedir/gitconfig.erb
|
92
|
+
- test/fixtures/sourcedir/gitignore
|
93
|
+
- test/fixtures/sourcedir/ignored_file
|
94
|
+
- test/fixtures/sourcedir/irbrc
|
95
|
+
- test/helper.rb
|
96
|
+
- test/installer_test.rb
|
97
|
+
- test/irb.rb
|
98
|
+
- test/runner_test.rb
|
99
|
+
homepage: http://github.com/kelredd/dotfiles-installer
|
100
|
+
licenses: []
|
101
|
+
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
requirements: []
|
126
|
+
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.8.10
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: Safely install dotfiles into your home dir.
|
132
|
+
test_files:
|
133
|
+
- test/actions_test.rb
|
134
|
+
- test/fixtures/sourcedir/bash/aliases
|
135
|
+
- test/fixtures/sourcedir/bash/colors
|
136
|
+
- test/fixtures/sourcedir/bin/a_script
|
137
|
+
- test/fixtures/sourcedir/bin/~also_ignored
|
138
|
+
- test/fixtures/sourcedir/gemrc
|
139
|
+
- test/fixtures/sourcedir/gitconfig.erb
|
140
|
+
- test/fixtures/sourcedir/gitignore
|
141
|
+
- test/fixtures/sourcedir/ignored_file
|
142
|
+
- test/fixtures/sourcedir/irbrc
|
143
|
+
- test/helper.rb
|
144
|
+
- test/installer_test.rb
|
145
|
+
- test/irb.rb
|
146
|
+
- test/runner_test.rb
|