wizard 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/CHANGELOG.md +5 -0
- data/README.md +0 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/lib/wizard.rb +12 -0
- data/lib/wizard/formula.rb +23 -0
- data/lib/wizard/helpers.rb +63 -0
- data/lib/wizard/spells.rb +12 -0
- data/lib/wizard/spells/base.rb +84 -0
- data/lib/wizard/spells/compile_template.rb +27 -0
- data/lib/wizard/spells/execute_shell.rb +22 -0
- data/lib/wizard/spells/make_dir.rb +47 -0
- data/lib/wizard/spells/make_file.rb +69 -0
- data/lib/wizard/spells/update_file.rb +95 -0
- data/spec/helpers_spec.rb +55 -0
- data/spec/spec_helper.rb +71 -0
- data/spec/spells/compile_template_spec.rb +60 -0
- data/spec/spells/execute_shell_spec.rb +58 -0
- data/spec/spells/make_dir_spec.rb +77 -0
- data/spec/spells/make_file_spec.rb +125 -0
- data/spec/spells/update_file_spec.rb +209 -0
- data/spec/spells_spec.rb +142 -0
- metadata +125 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/README.md
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "wizard"
|
8
|
+
gem.summary = %Q{Projects generator and recipes compiler.}
|
9
|
+
gem.description = <<-DESCR
|
10
|
+
Projects generator...
|
11
|
+
DESCR
|
12
|
+
gem.email = "chris@nu7hat.ch"
|
13
|
+
gem.homepage = "http://github.com/nu7hatch/wizard"
|
14
|
+
gem.authors = ["Kriss 'nu7hatch' Kowalik"]
|
15
|
+
gem.add_development_dependency "rspec", "~> 2.0"
|
16
|
+
gem.add_development_dependency "mocha", "~> 0.9"
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rspec/core/rake_task'
|
24
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
25
|
+
t.pattern = 'spec/**/*_spec.rb'
|
26
|
+
t.rspec_opts = %q[--colour --backtrace]
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
30
|
+
t.rcov = true
|
31
|
+
t.rspec_opts = %q[--colour --backtrace]
|
32
|
+
t.rcov_opts = %q[--exclude "spec" --text-report]
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
rdoc.rdoc_dir = 'rdoc'
|
41
|
+
rdoc.title = "Wizard #{version}"
|
42
|
+
rdoc.rdoc_files.include('README*')
|
43
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
44
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/wizard.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Wizard
|
2
|
+
class Formula
|
3
|
+
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
COLORIZERS = {
|
7
|
+
:success => :green,
|
8
|
+
:error => :red,
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.colorizers
|
12
|
+
COLORIZERS
|
13
|
+
end
|
14
|
+
|
15
|
+
def render(spell)
|
16
|
+
line = " "
|
17
|
+
line += a(spell.to_s, console_width-spell.status.to_s.size-3) + " "
|
18
|
+
line += c(spell.status.to_s, self.class.colorizers[spell.status], true)
|
19
|
+
say! line
|
20
|
+
end
|
21
|
+
|
22
|
+
end # Formula
|
23
|
+
end # Ryori
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Wizard
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
COLORS = {
|
5
|
+
:black => 30,
|
6
|
+
:red => 31,
|
7
|
+
:green => 32,
|
8
|
+
:yellow => 33,
|
9
|
+
:blue => 34,
|
10
|
+
:purple => 35,
|
11
|
+
:cyan => 36,
|
12
|
+
:white => 37,
|
13
|
+
}
|
14
|
+
|
15
|
+
# Display colorized output (no new line at the end).
|
16
|
+
def say(text, color=nil, bold=false)
|
17
|
+
print(color ? colorize(text, color, bold) : text)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Writes given text to <tt>$stdout</tt>.
|
21
|
+
def print(*args)
|
22
|
+
res = $stdout.write(*args)
|
23
|
+
$stdout.flush
|
24
|
+
return res
|
25
|
+
end
|
26
|
+
|
27
|
+
# Display colorized output.
|
28
|
+
def say!(text, color=nil, bold=false)
|
29
|
+
say(text+"\n", color, bold)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Colorize specified text with given color.
|
33
|
+
def colorize(text, color=:white, bold=false)
|
34
|
+
color = COLORS[color] || COLORS[:white]
|
35
|
+
return "\e[#{bold ? 1 : 0};#{color}m#{text}\e[0m"
|
36
|
+
end
|
37
|
+
alias :c :colorize
|
38
|
+
|
39
|
+
# Display given text adjusted to the desired length.
|
40
|
+
#
|
41
|
+
# adjust("This", 30, "-")
|
42
|
+
# adjust("is", 30, "-")
|
43
|
+
# adjust("SPARTA!", 30, "-")
|
44
|
+
#
|
45
|
+
# will produce:
|
46
|
+
#
|
47
|
+
# This -------------------------
|
48
|
+
# is ---------------------------
|
49
|
+
# SPARTA! ----------------------
|
50
|
+
def adjust(text, size=nil, delim=".")
|
51
|
+
size ||= console_width
|
52
|
+
delims = size-text.size
|
53
|
+
delims > 0 ? text+" "+(c(delim*(delims-1), :black)) : text
|
54
|
+
end
|
55
|
+
alias :a :adjust
|
56
|
+
|
57
|
+
# Returns actual width of console line.
|
58
|
+
def console_width
|
59
|
+
`stty size`.split.last.to_i
|
60
|
+
end
|
61
|
+
|
62
|
+
end # Helpers
|
63
|
+
end # Wizard
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Wizard
|
2
|
+
module Spells
|
3
|
+
|
4
|
+
require "wizard/spells/base"
|
5
|
+
require "wizard/spells/make_dir"
|
6
|
+
require "wizard/spells/make_file"
|
7
|
+
require "wizard/spells/update_file"
|
8
|
+
require "wizard/spells/compile_template"
|
9
|
+
require "wizard/spells/execute_shell"
|
10
|
+
|
11
|
+
end # Spells
|
12
|
+
end # Wizard
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Wizard
|
2
|
+
module Spells
|
3
|
+
class Base
|
4
|
+
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Should all actions be performed in force mode?
|
9
|
+
def all_forced?
|
10
|
+
defined?(@@force_all) and !!@@force_all
|
11
|
+
end
|
12
|
+
|
13
|
+
# Set force mode for all apps.
|
14
|
+
# XXX. deadlocks can raise here.
|
15
|
+
def force_all!
|
16
|
+
@@force_all = true
|
17
|
+
end
|
18
|
+
|
19
|
+
# Creates shortcuts for given statuses:
|
20
|
+
#
|
21
|
+
# attr_status :my_status
|
22
|
+
#
|
23
|
+
# will produce methods:
|
24
|
+
#
|
25
|
+
# my_status! # => status!(:my_status)
|
26
|
+
# my_status? # => status?(:my_status)
|
27
|
+
#
|
28
|
+
def attr_status(*statuses)
|
29
|
+
statuses.each do |status|
|
30
|
+
define_method("#{status}!".to_sym) { status!(status.to_sym) }
|
31
|
+
define_method("#{status}?".to_sym) { status?(status.to_sym) }
|
32
|
+
protected "#{status}!".to_sym
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shortcuts for the most commonly used statuses. We are creating
|
38
|
+
# <tt>success</tt> and <tt>error</tt> shortcuts by default.
|
39
|
+
attr_status :success, :error
|
40
|
+
|
41
|
+
# Returns status of currently performed operation.
|
42
|
+
def status
|
43
|
+
@status
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns +true+ when actual status equals the given one.
|
47
|
+
#
|
48
|
+
# status!(:success)
|
49
|
+
# status?(:success) # => true
|
50
|
+
# status?(:error) # => false
|
51
|
+
#
|
52
|
+
def status?(status)
|
53
|
+
self.status == status.to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
# Should be forced performing of current action?
|
57
|
+
def forced?
|
58
|
+
@force || self.class.all_forced?
|
59
|
+
end
|
60
|
+
|
61
|
+
# See Ryori::Makers::Base.force_all! for details.
|
62
|
+
def force_all!
|
63
|
+
self.class.force_all!
|
64
|
+
end
|
65
|
+
|
66
|
+
# Set force mode for current action.
|
67
|
+
def force!
|
68
|
+
@force = true
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
# Set given status for actual operation.
|
74
|
+
#
|
75
|
+
# status!(:success)
|
76
|
+
# status!(:error)
|
77
|
+
#
|
78
|
+
def status!(status)
|
79
|
+
@status = status.to_sym
|
80
|
+
end
|
81
|
+
|
82
|
+
end # Base
|
83
|
+
end # Spells
|
84
|
+
end # Wizard
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'wizard/spells/make_file'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Wizard
|
5
|
+
module Spells
|
6
|
+
class CompileTemplate < MakeFile
|
7
|
+
|
8
|
+
attr_reader :template
|
9
|
+
|
10
|
+
def initialize(filename, template, options={})
|
11
|
+
super(filename, nil, options)
|
12
|
+
@template = template
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform_with_template_compilation
|
16
|
+
@content = ERB.new(File.read(template)).result(binding)
|
17
|
+
perform_without_template_compilation
|
18
|
+
rescue Object
|
19
|
+
error!
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :perform_without_template_compilation, :perform
|
23
|
+
alias_method :perform, :perform_with_template_compilation
|
24
|
+
|
25
|
+
end # CompileTemplate
|
26
|
+
end # Spells
|
27
|
+
end # Wizard
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Wizard
|
2
|
+
module Spells
|
3
|
+
class ExecuteShell < Base
|
4
|
+
|
5
|
+
attr_reader :command, :output
|
6
|
+
attr_status :executed, :failed
|
7
|
+
|
8
|
+
def initialize(command, options={})
|
9
|
+
@command = command
|
10
|
+
@output = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform
|
14
|
+
return executed! if @output = `#{command} 2>&1` and $?.exitstatus == 0
|
15
|
+
failed!
|
16
|
+
rescue Object
|
17
|
+
error!
|
18
|
+
end
|
19
|
+
|
20
|
+
end # CompileTemplate
|
21
|
+
end # Spells
|
22
|
+
end # Wizard
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Wizard
|
2
|
+
class Formula
|
3
|
+
|
4
|
+
colorizers.merge!(
|
5
|
+
:created => :green,
|
6
|
+
:exist => :cyan,
|
7
|
+
:noaccess => :red,
|
8
|
+
)
|
9
|
+
|
10
|
+
def make_dir(dirname, options={})
|
11
|
+
spell = Spells::MakeDir.new(dirname, options)
|
12
|
+
spell.perform
|
13
|
+
render(spell)
|
14
|
+
end
|
15
|
+
alias_method :dir, :make_dir
|
16
|
+
alias_method :directory, :make_dir
|
17
|
+
alias_method :mkdir, :make_dir
|
18
|
+
alias_method :create_dir, :make_dir
|
19
|
+
|
20
|
+
end # Formula
|
21
|
+
|
22
|
+
module Spells
|
23
|
+
class MakeDir < Base
|
24
|
+
|
25
|
+
attr_reader :dirname, :chmod
|
26
|
+
attr_status :created, :exist, :noaccess
|
27
|
+
|
28
|
+
def initialize(dirname, options={})
|
29
|
+
@dirname = dirname
|
30
|
+
@chmod = options[:mode]
|
31
|
+
end
|
32
|
+
|
33
|
+
def perform
|
34
|
+
return exist! if File.exist?(dirname)
|
35
|
+
return created! if FileUtils.mkdir_p(dirname, :mode => chmod) == dirname
|
36
|
+
error!
|
37
|
+
rescue Errno::EACCES
|
38
|
+
noaccess!
|
39
|
+
rescue Object
|
40
|
+
error!
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :to_s, :dirname
|
44
|
+
|
45
|
+
end # MakeDir
|
46
|
+
end # Spells
|
47
|
+
end # Wizard
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Wizard
|
2
|
+
class Formula
|
3
|
+
|
4
|
+
colorizers.merge!(
|
5
|
+
:created => :green,
|
6
|
+
:noaccess => :red,
|
7
|
+
:identical => :cyan,
|
8
|
+
:conflict => :yellow,
|
9
|
+
:updated => :green,
|
10
|
+
:skipped => :yellow
|
11
|
+
)
|
12
|
+
|
13
|
+
def make_file(filename, content=nil, options={})
|
14
|
+
spell = Spells::MakeFile.new(filename, content, options)
|
15
|
+
spell.perform
|
16
|
+
render(spell)
|
17
|
+
end
|
18
|
+
alias_method :file, :make_file
|
19
|
+
alias_method :mkfile, :make_file
|
20
|
+
alias_method :create_file, :make_file
|
21
|
+
|
22
|
+
end # Formula
|
23
|
+
|
24
|
+
module Spells
|
25
|
+
class MakeFile < Base
|
26
|
+
|
27
|
+
attr_reader :filename, :chmod, :content
|
28
|
+
attr_status :created, :noaccess, :identical, :conflict, :updated, :skipped
|
29
|
+
|
30
|
+
def initialize(filename, content=nil, options={})
|
31
|
+
@filename = filename
|
32
|
+
@content = content
|
33
|
+
@chmod = options[:mode]
|
34
|
+
|
35
|
+
force! if options[:force]
|
36
|
+
end
|
37
|
+
|
38
|
+
def perform
|
39
|
+
if File.exist?(filename)
|
40
|
+
return identical! if identical_content?
|
41
|
+
return status if conflict! and !forced?
|
42
|
+
end
|
43
|
+
return conflict? ? updated! : created! if create_file!
|
44
|
+
error!
|
45
|
+
rescue Errno::EACCES
|
46
|
+
noaccess!
|
47
|
+
rescue Object
|
48
|
+
error!
|
49
|
+
end
|
50
|
+
|
51
|
+
# Create current performed file, write its content and set proper chmod.
|
52
|
+
def create_file!
|
53
|
+
if File.open(filename, "w+") {|f| f.write(content) if content }
|
54
|
+
FileUtils.chmod(chmod, filename) if chmod
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns +true+ when current file already exists and have the same
|
60
|
+
# content as given in initializer.
|
61
|
+
def identical_content?
|
62
|
+
File.read(filename) == content
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :to_s, :filename
|
66
|
+
|
67
|
+
end # MakeFile
|
68
|
+
end # Spells
|
69
|
+
end # Wizard
|