polka 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +20 -0
- data/bin/polka +6 -0
- data/lib/polka/bootstrapper.rb +99 -0
- data/lib/polka/cli.rb +12 -0
- data/lib/polka/dotfile.rb +39 -0
- data/lib/polka/dotfile_group.rb +50 -0
- data/lib/polka/operations/parsed_copying.rb +49 -0
- data/lib/polka/version.rb +3 -0
- data/lib/polka.rb +17 -0
- data/polka.gemspec +22 -0
- data/spec/polka/bootstrapper_spec.rb +101 -0
- data/spec/polka/cli_spec.rb +26 -0
- data/spec/polka/dotfile_group_spec.rb +38 -0
- data/spec/polka/dotfile_spec.rb +56 -0
- data/spec/polka/operations/parsed_copying_spec.rb +13 -0
- data/spec/polka_spec.rb +52 -0
- data/spec/spec_helper.rb +23 -0
- metadata +106 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Guardfile
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
colorize (0.5.8)
|
5
|
+
diff-lcs (1.1.3)
|
6
|
+
rspec (2.11.0)
|
7
|
+
rspec-core (~> 2.11.0)
|
8
|
+
rspec-expectations (~> 2.11.0)
|
9
|
+
rspec-mocks (~> 2.11.0)
|
10
|
+
rspec-core (2.11.1)
|
11
|
+
rspec-expectations (2.11.2)
|
12
|
+
diff-lcs (~> 1.1.3)
|
13
|
+
rspec-mocks (2.11.2)
|
14
|
+
thor (0.16.0)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
colorize
|
21
|
+
rspec
|
22
|
+
thor
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Michi Huber
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/bin/polka
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
module Polka
|
2
|
+
class Bootstrapper
|
3
|
+
def initialize(home_dir, dotfile_dir)
|
4
|
+
@home_dir = home_dir
|
5
|
+
@dotfile_dir = dotfile_dir
|
6
|
+
DotfileGroup.all_files = dotfiles_in_dotfile_dir
|
7
|
+
|
8
|
+
symlinking = lambda { |dest, src| FileUtils.ln_s(dest, src) }
|
9
|
+
copying = lambda { |dest, src| FileUtils.cp(dest, src) }
|
10
|
+
|
11
|
+
@symlink = DotfileGroup.new(symlinking, " Symlinking files".light_blue)
|
12
|
+
@copy = DotfileGroup.new(copying, " Copying files".light_blue)
|
13
|
+
@parsed_copy = DotfileGroup.new(Operations::ParsedCopying, " Parsing and copying files".light_blue)
|
14
|
+
@inclusive_groups = [@symlink, @copy, @parsed_copy]
|
15
|
+
@exclude = DotfileGroup.new
|
16
|
+
exclude("Dotfile")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.from_dotfile(dotfile, home_dir)
|
20
|
+
bootstrapper = new(home_dir, File.expand_path(File.dirname(dotfile)))
|
21
|
+
bootstrapper.instance_eval(dotfile.read)
|
22
|
+
|
23
|
+
return bootstrapper
|
24
|
+
end
|
25
|
+
|
26
|
+
# TODO: the structure of copy and the rest is the same,
|
27
|
+
# refactor into one method?
|
28
|
+
[:symlink, :exclude].each do |var|
|
29
|
+
define_method(var) do |*files|
|
30
|
+
group = instance_variable_get("@#{var}")
|
31
|
+
if file_with_options?(files)
|
32
|
+
add_file_with_options_to_group(files, group)
|
33
|
+
else
|
34
|
+
group.add_all_other_files if files.delete(:all_other_files)
|
35
|
+
add_files_to_group(files, group)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def copy(*files)
|
41
|
+
if file_with_options?(files)
|
42
|
+
group = erb?(files[0]) ? @parsed_copy : @copy
|
43
|
+
add_file_with_options_to_group(files, group)
|
44
|
+
else
|
45
|
+
error_msg = "Cannot copy :all_other_files, please copy files explicitly."
|
46
|
+
raise ArgumentError, error_msg if files.include?(:all_other_files)
|
47
|
+
|
48
|
+
erb = files.select { |fn| erb?(fn) }
|
49
|
+
not_erb = files - erb
|
50
|
+
add_files_to_group(not_erb, @copy)
|
51
|
+
erb_dotfiles = erb.map { |erbfile| create_dotfile(erbfile, File.basename(erbfile, '.erb')) }
|
52
|
+
@parsed_copy.add(erb_dotfiles) unless erb_dotfiles.empty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def setup
|
57
|
+
Polka.log "\nStarting Dotfile Setup with Polka...\n".green
|
58
|
+
@inclusive_groups.each(&:setup)
|
59
|
+
Polka.log "\nSetup completed. Enjoy!\n".green
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def add_files_to_group(files, group)
|
64
|
+
dotfiles = files.map { |fn| create_dotfile(fn) }
|
65
|
+
group.add(dotfiles) unless dotfiles.empty?
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_file_with_options_to_group(file_with_options, group)
|
69
|
+
filename = file_with_options[0]
|
70
|
+
homename = file_with_options[1][:as]
|
71
|
+
|
72
|
+
group.add([create_dotfile(filename, homename)])
|
73
|
+
end
|
74
|
+
|
75
|
+
def erb?(filename)
|
76
|
+
filename =~ /\.erb$/
|
77
|
+
end
|
78
|
+
|
79
|
+
def file_with_options?(files)
|
80
|
+
return false unless files.size == 2 && files.last.class == Hash && files.last[:as]
|
81
|
+
unless files[0] == :all_other_files
|
82
|
+
return true
|
83
|
+
else
|
84
|
+
raise ArgumentError, "Cannot add :all_other_files with :as options"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def dotfiles_in_dotfile_dir
|
89
|
+
files = Dir.new(@dotfile_dir).entries - %w(.. .)
|
90
|
+
files.map { |fn| create_dotfile(fn) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_dotfile(filename, homename=nil)
|
94
|
+
dotfile_path = File.join(@dotfile_dir, filename)
|
95
|
+
home_path = File.join(@home_dir, homename || filename)
|
96
|
+
Dotfile.new(dotfile_path, home_path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/polka/cli.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Polka
|
2
|
+
class Cli < Thor
|
3
|
+
desc "setup", "sets up your dotfiles according to the instructions in Dotfile"
|
4
|
+
def setup(home_dir=nil, dotfile_dir=nil)
|
5
|
+
dotfile_path = dotfile_dir ? File.join(dotfile_dir, "Dotfile") : "Dotfile"
|
6
|
+
home_path = home_dir || ENV['HOME']
|
7
|
+
dotfile_path = File.expand_path(dotfile_path)
|
8
|
+
home_path = File.expand_path(home_path)
|
9
|
+
File.open(dotfile_path) { |the_dotfile| Bootstrapper.from_dotfile(the_dotfile, home_path).setup }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class FileNotPresentError < StandardError; end
|
2
|
+
|
3
|
+
class Dotfile
|
4
|
+
def initialize(path, home_path)
|
5
|
+
raise FileNotPresentError, "Could not find file at #{path}." unless File.exists?(path)
|
6
|
+
@path = path
|
7
|
+
@home_path = home_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup(operation)
|
11
|
+
backup if File.exists?(@home_path)
|
12
|
+
operation.call(@path, @home_path)
|
13
|
+
Polka.log " #{@path} set up as #{@home_path}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def backup
|
17
|
+
Polka.log " Backing up: ".light_yellow + "#{@home_path} => #{backup_dir}"
|
18
|
+
FileUtils.mkdir_p(backup_dir) unless File.exists?(backup_dir)
|
19
|
+
FileUtils.mv(@home_path, backup_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def hash
|
23
|
+
@path.hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def eql?(other)
|
27
|
+
hash == other.hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.backup_dir(home_path)
|
31
|
+
dir = File.join(".polka_backup", Time.now.strftime("%F_%T"))
|
32
|
+
@@backup_dir ||= File.join(home_path, dir)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def backup_dir
|
37
|
+
Dotfile.backup_dir(File.dirname(@home_path))
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class AllOtherFilesAlreadyAdded < StandardError; end
|
2
|
+
class FileAlreadyAddedError < StandardError; end
|
3
|
+
|
4
|
+
class DotfileGroup
|
5
|
+
@@all_files = []
|
6
|
+
@@grouped_files = []
|
7
|
+
@@all_other_files_added = false
|
8
|
+
|
9
|
+
def self.all_files=(files)
|
10
|
+
@@all_files = files
|
11
|
+
@@grouped_files = []
|
12
|
+
@@all_other_files_added = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.remaining_files
|
16
|
+
@@all_files - @@grouped_files
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(operation=nil, setup_msg=nil)
|
20
|
+
@operation = operation
|
21
|
+
@setup_message = setup_msg
|
22
|
+
@files = []
|
23
|
+
@all_other_files = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def add(new_files)
|
27
|
+
raise FileAlreadyAddedError if new_files.any? { |f| @@grouped_files.include?(f) }
|
28
|
+
@@grouped_files += new_files
|
29
|
+
@files += new_files
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_all_other_files
|
33
|
+
raise AllOtherFilesAlreadyAdded if @@all_other_files_added
|
34
|
+
@@all_other_files_added = true
|
35
|
+
@all_other_files = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def files
|
39
|
+
if @all_other_files
|
40
|
+
DotfileGroup.remaining_files + @files
|
41
|
+
else
|
42
|
+
@files
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup
|
47
|
+
Polka.log @setup_message unless files.empty?
|
48
|
+
files.each { |f| f.setup(@operation) }
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Polka
|
2
|
+
module Operations
|
3
|
+
class ParsedCopying
|
4
|
+
def self.call(file, dest)
|
5
|
+
copier = new(file, dest)
|
6
|
+
copier.run
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(file, dest)
|
10
|
+
@file = file
|
11
|
+
@dest = dest
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
write(result)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def result
|
20
|
+
personal = context
|
21
|
+
erb.result(binding)
|
22
|
+
end
|
23
|
+
|
24
|
+
def write(result)
|
25
|
+
File.open(dest_without_erb, "w") { |f| f.write(result) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def dest_without_erb
|
29
|
+
@dest.gsub(/\.erb$/, "")
|
30
|
+
end
|
31
|
+
|
32
|
+
def yaml_file
|
33
|
+
File.join(File.dirname(@file), 'personal.yml')
|
34
|
+
end
|
35
|
+
|
36
|
+
def context_name
|
37
|
+
File.basename(@file, ".erb")
|
38
|
+
end
|
39
|
+
|
40
|
+
def context
|
41
|
+
YAML.load_file(yaml_file)[context_name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def erb
|
45
|
+
ERB.new(File.open(@file) { |f| f.read })
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/polka.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "erb"
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
require "colorize"
|
6
|
+
|
7
|
+
require_relative "polka/cli"
|
8
|
+
require_relative "polka/bootstrapper"
|
9
|
+
require_relative "polka/dotfile"
|
10
|
+
require_relative "polka/dotfile_group"
|
11
|
+
require_relative "polka/operations/parsed_copying"
|
12
|
+
|
13
|
+
module Polka
|
14
|
+
def self.log(msg)
|
15
|
+
puts msg
|
16
|
+
end
|
17
|
+
end
|
data/polka.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'polka/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "polka"
|
6
|
+
s.version = Polka::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Michi Huber"]
|
9
|
+
s.email = ["michi.huber@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/michihuber/polka"
|
11
|
+
s.summary = ""
|
12
|
+
s.description = "Easy Dotfile Management"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency "thor", ">=0.16.0"
|
20
|
+
s.add_dependency "colorize", "0.5.8"
|
21
|
+
s.add_development_dependency 'rspec', '~> 2.11'
|
22
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require_relative "../../lib/polka/bootstrapper.rb"
|
3
|
+
class Dotfile; end
|
4
|
+
class DotfileGroup; end
|
5
|
+
module Operations
|
6
|
+
class ParsedCopying; end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Polka::Bootstrapper do
|
10
|
+
subject(:bs) { Polka::Bootstrapper.new('home', 'home/.polka') }
|
11
|
+
let(:copy_group) { double(:copies) }
|
12
|
+
let(:symlink_group) { double(:symlinks) }
|
13
|
+
let(:excluded_group) { double(:excluded) }
|
14
|
+
let(:parsed_copy_group) { double(:parsed_copy) }
|
15
|
+
|
16
|
+
before do
|
17
|
+
Dir.stub(:new) { double(entries: %w(. .. blah)) }
|
18
|
+
blah_dotfile = double
|
19
|
+
the_dotfile = double(:Dotfile)
|
20
|
+
Dotfile.should_receive(:new).with('home/.polka/blah', 'home/blah').and_return(blah_dotfile)
|
21
|
+
Dotfile.should_receive(:new).with('home/.polka/Dotfile', 'home/Dotfile').and_return(the_dotfile)
|
22
|
+
excluded_group.should_receive(:add).with([the_dotfile])
|
23
|
+
DotfileGroup.should_receive(:all_files=).with([blah_dotfile])
|
24
|
+
DotfileGroup.stub(:new).and_return(symlink_group, copy_group, parsed_copy_group, excluded_group)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#setup" do
|
28
|
+
it "sets up the symlink group" do
|
29
|
+
Polka.stub(:log)
|
30
|
+
copy_group.should_receive(:setup)
|
31
|
+
symlink_group.should_receive(:setup)
|
32
|
+
parsed_copy_group.should_receive(:setup)
|
33
|
+
bs.setup
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#symlink, #exclude, #copy" do
|
38
|
+
describe "addings files without options" do
|
39
|
+
let(:hello_dotfile) { double(:hello_dotfile) }
|
40
|
+
before { Dotfile.stub(:new) { hello_dotfile } }
|
41
|
+
|
42
|
+
it "adds to the symlink group" do
|
43
|
+
symlink_group.should_receive(:add).with([hello_dotfile])
|
44
|
+
bs.symlink "hello"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "adds to the exclude group" do
|
48
|
+
excluded_group.should_receive(:add).with([hello_dotfile])
|
49
|
+
bs.exclude "hello"
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#copy" do
|
53
|
+
it "cannot copy :all_other_files" do
|
54
|
+
expect { bs.copy :all_other_files }.to raise_error(ArgumentError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can copy files with aliases" do
|
58
|
+
alias_dotfile = double(:alias_dotfile)
|
59
|
+
Dotfile.should_receive(:new).with("home/.polka/hello", "home/ciao").and_return(alias_dotfile)
|
60
|
+
copy_group.should_receive(:add).with([alias_dotfile])
|
61
|
+
bs.copy("hello", as: "ciao")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "adds to the copy group" do
|
65
|
+
copy_group.should_receive(:add).with([hello_dotfile])
|
66
|
+
bs.copy "hello"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "adds to the parsed_copy group if file has erb extension (without extension on target)" do
|
70
|
+
Dotfile.should_receive(:new).with("home/.polka/hello.erb", "home/hello").and_return(hello_dotfile)
|
71
|
+
parsed_copy_group.should_receive(:add).with([hello_dotfile])
|
72
|
+
bs.copy "hello.erb"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ":all_other_files" do
|
78
|
+
it "adds :all_other_files" do
|
79
|
+
symlink_group.should_receive(:add_all_other_files)
|
80
|
+
bs.symlink :all_other_files
|
81
|
+
end
|
82
|
+
|
83
|
+
it "adds :all_other_files" do
|
84
|
+
excluded_group.should_receive(:add_all_other_files)
|
85
|
+
bs.exclude :all_other_files
|
86
|
+
end
|
87
|
+
|
88
|
+
it "cannot add :all_other_files with an alias" do
|
89
|
+
expect { bs.symlink(:all_other_files, as: 'something') }.to raise_error(ArgumentError)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "adds file with home_dir_path if specified" do
|
94
|
+
alias_dotfile = double(:alias_dotfile)
|
95
|
+
Dotfile.should_receive(:new).with("home/.polka/.testrc", "home/.onerc").and_return(alias_dotfile)
|
96
|
+
symlink_group.should_receive(:add).with([alias_dotfile])
|
97
|
+
bs.symlink(".testrc", as: ".onerc")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "thor"
|
2
|
+
require_relative "../../lib/polka/cli.rb"
|
3
|
+
class Polka::Bootstrapper; end
|
4
|
+
|
5
|
+
describe Polka::Cli do
|
6
|
+
describe "#setup" do
|
7
|
+
let(:the_dotfile) { double }
|
8
|
+
let(:bootstrapper) { double(:bootstrapper, setup: "works") }
|
9
|
+
|
10
|
+
it "initializes a bootstrapper with the Dotfile (and the target dir)" do
|
11
|
+
File.stub(:open).and_yield(the_dotfile)
|
12
|
+
Polka::Bootstrapper.should_receive(:from_dotfile).with(the_dotfile, File.expand_path(ENV['HOME'])).and_return(bootstrapper)
|
13
|
+
bootstrapper.setup.should == "works"
|
14
|
+
|
15
|
+
Polka::Cli.new.setup
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts home_dir and dotfile_dir as optional arguments" do
|
19
|
+
File.stub(:open).and_yield(the_dotfile)
|
20
|
+
Polka::Bootstrapper.should_receive(:from_dotfile).with(the_dotfile, File.expand_path("home")).and_return(bootstrapper)
|
21
|
+
bootstrapper.setup.should == "works"
|
22
|
+
|
23
|
+
Polka::Cli.new.setup("home", "home/.polka")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "../../lib/polka/dotfile_group.rb"
|
2
|
+
|
3
|
+
describe DotfileGroup do
|
4
|
+
subject(:group) { DotfileGroup.new }
|
5
|
+
1.upto(3) { |n| fn = "file#{n}".to_sym; let(fn) { double(fn) } }
|
6
|
+
|
7
|
+
before do
|
8
|
+
DotfileGroup.all_files = [file1, file2, file3]
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#add" do
|
12
|
+
it "adds dotfiles" do
|
13
|
+
group.add([file1, file2])
|
14
|
+
group.files.should == [file1, file2]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can only add each file once" do
|
18
|
+
group.add([file1])
|
19
|
+
expect { group.add([file1]) }.to raise_error(FileAlreadyAddedError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#add_all_other_files" do
|
24
|
+
let(:other_group) { DotfileGroup.new }
|
25
|
+
|
26
|
+
it "adds all other files to the group" do
|
27
|
+
group.add([file1])
|
28
|
+
group.add_all_other_files
|
29
|
+
other_group.add([file3])
|
30
|
+
group.files.should == [file2, file1]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can only be called once" do
|
34
|
+
group.add_all_other_files
|
35
|
+
expect {other_group.add_all_other_files }.to raise_error(AllOtherFilesAlreadyAdded)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dotfile do
|
4
|
+
describe "#setup", :integrated_with_files do
|
5
|
+
set_up_testdirs
|
6
|
+
|
7
|
+
def home_path(filename)
|
8
|
+
File.join(home_dir, filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def dotfile_path(filename)
|
12
|
+
File.join(dotfile_dir, filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "raises if dotfile does not exist" do
|
16
|
+
expect { Dotfile.new(dotfile_path('.testrc'), "irrelevant") }.to raise_error(FileNotPresentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "yields to a given operation" do
|
20
|
+
Polka.stub(:log)
|
21
|
+
FileUtils.touch(dotfile_path('.testrc'))
|
22
|
+
df = Dotfile.new(dotfile_path('.testrc'), home_path('.testrc'))
|
23
|
+
df.setup(lambda { |dest, src| FileUtils.ln_s(dest, src) })
|
24
|
+
Dir.new(home_dir).entries.should == %w(. .. .dotfile_dir .testrc)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "the homedir already contains the file" do
|
28
|
+
it "backs up into a backup dir" do
|
29
|
+
Time.stub(:now) { Time.new(2222, 2, 2, 2, 22, 22) }
|
30
|
+
FileUtils.touch(home_path('.testrc'))
|
31
|
+
FileUtils.touch(dotfile_path('.testrc'))
|
32
|
+
df = Dotfile.new(dotfile_path('.testrc'), home_path('.testrc'))
|
33
|
+
Polka.stub(:log)
|
34
|
+
df.setup(lambda { |a, b| FileUtils.cp(a, b) })
|
35
|
+
Dir.new(home_dir).entries.should == %w(. .. .dotfile_dir .polka_backup .testrc)
|
36
|
+
Dir.new(File.join(home_dir, '.polka_backup')).entries.should == %w(. .. 2222-02-02_02:22:22)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "equality" do
|
42
|
+
before { File.stub(:exists?) { true } }
|
43
|
+
|
44
|
+
it "regards dotfiles as equal if they share the same dotfile dir path" do
|
45
|
+
df1 = Dotfile.new("home/df1", "blah")
|
46
|
+
df2 = Dotfile.new("home/df1", "foo")
|
47
|
+
df1.eql?(df2).should == true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "substracts equal dotfiles in array substraction" do
|
51
|
+
df1 = Dotfile.new("home/df1", "blah")
|
52
|
+
df2 = Dotfile.new("home/df1", "foo")
|
53
|
+
([df1] - [df2]).should == []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Polka::Operations::ParsedCopying, :integrated_with_files do
|
4
|
+
set_up_testdirs
|
5
|
+
|
6
|
+
it "parses the erb file and copys the result without the extension" do
|
7
|
+
File.open(File.join(dotfile_dir, "blah.erb"), "w") { |f| f.write("hello <%= personal['name'] %>") }
|
8
|
+
File.open(File.join(dotfile_dir, "personal.yml"), "w") { |f| f.write("blah:\n name: ray stanz") }
|
9
|
+
|
10
|
+
Polka::Operations::ParsedCopying.call(File.join(dotfile_dir, "blah.erb"), File.join(home_dir, "foo.erb"))
|
11
|
+
File.open(File.join(home_dir, "foo")) { |f| f.read }.should == "hello ray stanz"
|
12
|
+
end
|
13
|
+
end
|
data/spec/polka_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "polka", :integrated_with_files do
|
4
|
+
set_up_testdirs
|
5
|
+
|
6
|
+
before { Polka.stub(:log) }
|
7
|
+
|
8
|
+
it "provides a DSL to manage your dotfile setup" do
|
9
|
+
setup_dotfiles %w(.onerc .tworc .threerc .nodotfile copyrc)
|
10
|
+
setup_the_dotfile <<-EOF
|
11
|
+
symlink :all_other_files
|
12
|
+
symlink ".onerc", ".tworc"
|
13
|
+
copy "copyrc"
|
14
|
+
exclude ".nodotfile"
|
15
|
+
EOF
|
16
|
+
Cli.new.setup(home_dir, dotfile_dir)
|
17
|
+
dir_entries = Dir.new(home_dir).entries
|
18
|
+
dir_entries.should == %w(. .. .dotfile_dir .onerc .threerc .tworc copyrc)
|
19
|
+
File.symlink?(File.join(home_dir, '.onerc')).should == true
|
20
|
+
File.symlink?(File.join(home_dir, 'copyrc')).should == false
|
21
|
+
end
|
22
|
+
|
23
|
+
it "backs up existing files in your homedir" do
|
24
|
+
Time.stub(:now) { Time.new(2222, 2, 2, 2, 22, 22) }
|
25
|
+
setup_dotfiles %w(.onerc)
|
26
|
+
setup_the_dotfile("symlink '.onerc'")
|
27
|
+
FileUtils.touch(File.join(home_dir, '.onerc'))
|
28
|
+
Cli.new.setup(home_dir, dotfile_dir)
|
29
|
+
Dir.new(home_dir).entries.should == %w(. .. .dotfile_dir .onerc .polka_backup)
|
30
|
+
Dir.new(File.join(home_dir, ".polka_backup", "2222-02-02_02:22:22")).entries.should == %w(. .. .onerc)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "copys a parsed version of erb files" do
|
34
|
+
setup_the_dotfile("copy '.inforc.erb'")
|
35
|
+
setup_file_with_content("personal.yml", ".inforc:\n name: peter venkman")
|
36
|
+
setup_file_with_content(".inforc.erb", "hello <%= personal['name'] %>")
|
37
|
+
Cli.new.setup(home_dir, dotfile_dir)
|
38
|
+
File.open(File.join(home_dir, '.inforc')) { |f| f.read }.should == "hello peter venkman"
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_file_with_content(name, content)
|
42
|
+
File.open(File.join(dotfile_dir, name), "w") { |f| f.write(content) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def setup_the_dotfile(content)
|
46
|
+
setup_file_with_content("Dotfile", content)
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup_dotfiles(files)
|
50
|
+
files.each { |fn| FileUtils.touch(File.join(dotfile_dir, fn)) }
|
51
|
+
end
|
52
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "../lib/polka"
|
2
|
+
include Polka
|
3
|
+
|
4
|
+
module FileSetupHelper
|
5
|
+
def set_up_testdirs
|
6
|
+
let(:home_dir) { "home_dir" }
|
7
|
+
let(:dotfile_dir) { "home_dir/.dotfile_dir" }
|
8
|
+
|
9
|
+
before do
|
10
|
+
FileUtils.mkdir(home_dir)
|
11
|
+
FileUtils.mkdir(dotfile_dir)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
FileUtils.rm_rf(home_dir)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
22
|
+
config.extend FileSetupHelper, :integrated_with_files
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: polka
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michi Huber
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: &70162070820700 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.16.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70162070820700
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: colorize
|
27
|
+
requirement: &70162070820180 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - =
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.5.8
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70162070820180
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70162070819580 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.11'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70162070819580
|
47
|
+
description: Easy Dotfile Management
|
48
|
+
email:
|
49
|
+
- michi.huber@gmail.com
|
50
|
+
executables:
|
51
|
+
- polka
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- Gemfile.lock
|
58
|
+
- LICENSE
|
59
|
+
- bin/polka
|
60
|
+
- lib/polka.rb
|
61
|
+
- lib/polka/bootstrapper.rb
|
62
|
+
- lib/polka/cli.rb
|
63
|
+
- lib/polka/dotfile.rb
|
64
|
+
- lib/polka/dotfile_group.rb
|
65
|
+
- lib/polka/operations/parsed_copying.rb
|
66
|
+
- lib/polka/version.rb
|
67
|
+
- polka.gemspec
|
68
|
+
- spec/polka/bootstrapper_spec.rb
|
69
|
+
- spec/polka/cli_spec.rb
|
70
|
+
- spec/polka/dotfile_group_spec.rb
|
71
|
+
- spec/polka/dotfile_spec.rb
|
72
|
+
- spec/polka/operations/parsed_copying_spec.rb
|
73
|
+
- spec/polka_spec.rb
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
homepage: http://github.com/michihuber/polka
|
76
|
+
licenses: []
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.11
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: ''
|
99
|
+
test_files:
|
100
|
+
- spec/polka/bootstrapper_spec.rb
|
101
|
+
- spec/polka/cli_spec.rb
|
102
|
+
- spec/polka/dotfile_group_spec.rb
|
103
|
+
- spec/polka/dotfile_spec.rb
|
104
|
+
- spec/polka/operations/parsed_copying_spec.rb
|
105
|
+
- spec/polka_spec.rb
|
106
|
+
- spec/spec_helper.rb
|