wizard 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|