stack 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +13 -1
- data/VERSION.yml +4 -0
- data/bin/stack +3 -2
- data/lib/core_ext/hash.rb +63 -0
- data/lib/stack/configuration.rb +16 -0
- data/lib/stack/generator.rb +16 -0
- data/lib/stack/runner.rb +42 -0
- data/lib/stack.rb +61 -7
- metadata +7 -4
- data/.document +0 -5
- data/.gitignore +0 -21
- data/VERSION +0 -1
data/Rakefile
CHANGED
@@ -10,7 +10,9 @@ begin
|
|
10
10
|
gem.email = "dev@sixones.com"
|
11
11
|
gem.homepage = "http://github.com/sixones/stack"
|
12
12
|
gem.authors = ["sixones"]
|
13
|
+
gem.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
|
13
14
|
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
15
|
+
|
14
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
17
|
end
|
16
18
|
rescue LoadError
|
@@ -43,10 +45,20 @@ task :default => :test
|
|
43
45
|
|
44
46
|
require 'rake/rdoctask'
|
45
47
|
Rake::RDocTask.new do |rdoc|
|
46
|
-
|
48
|
+
if File.exist?('VERSION.yml')
|
49
|
+
config = YAML.load(File.read('VERSION.yml'))
|
50
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
51
|
+
else
|
52
|
+
version = ""
|
53
|
+
end
|
47
54
|
|
48
55
|
rdoc.rdoc_dir = 'rdoc'
|
49
56
|
rdoc.title = "stack #{version}"
|
50
57
|
rdoc.rdoc_files.include('README*')
|
51
58
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
59
|
end
|
60
|
+
|
61
|
+
desc "provide a console like merb -i or script/console"
|
62
|
+
task :console do
|
63
|
+
exec "irb -r irb/completion -r lib/stack.rb"
|
64
|
+
end
|
data/VERSION.yml
ADDED
data/bin/stack
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Returns a new hash just like this one, but with all the string keys expressed as symbols.
|
4
|
+
# Also applies to hashes within self.
|
5
|
+
# Based on an implementation within Rails 2.x, thanks Rails!
|
6
|
+
def deep_symbolize
|
7
|
+
target = dup
|
8
|
+
target.inject({}) do |memo, (key, value)|
|
9
|
+
value = value.deep_symbolize if value.is_a?(Hash)
|
10
|
+
memo[(key.to_sym rescue key) || key] = value
|
11
|
+
memo
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Subtracts one hash from another by removing keys from the actor and recursing on any hash values.
|
16
|
+
# Returns a new Hash without affecting the actors.
|
17
|
+
# Example 1:
|
18
|
+
# {:foo=>"bar"} - {:foo=>"bar"} == {}
|
19
|
+
# Example 2 of deep nesting:
|
20
|
+
# {:foo=>{:bar=>"baz", :car=>"naz"}, :bar=>"baz"} - {:foo=>{:car=>"naz"}} == {:foo=>{:bar=>"baz"}, :bar=>"baz"}
|
21
|
+
def -(arg)
|
22
|
+
target = dup; actor = arg.dup
|
23
|
+
actor.each do |key, value|
|
24
|
+
if value.is_a?(Hash)
|
25
|
+
target[key] = target[key] - value
|
26
|
+
else
|
27
|
+
target.delete(key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
return target
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a new hash just like this one, but with all STRING keys and values evaluated
|
34
|
+
# and rendered as liquid templates using the provided payload hash.
|
35
|
+
def deep_liquify(payload={})
|
36
|
+
target = dup
|
37
|
+
target.inject({}) do |memo, (key, value)|
|
38
|
+
value = value.deep_liquify(payload) if value.is_a?(Hash)
|
39
|
+
value = value.liquify(payload) if value.is_a?(String)
|
40
|
+
key = key.liquify(payload) if key.is_a?(String)
|
41
|
+
memo[(key.to_sym rescue key) || key] = value
|
42
|
+
memo
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Merges self with another hash, recursively.
|
47
|
+
#
|
48
|
+
# This code was lovingly stolen from some random gem:
|
49
|
+
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
|
50
|
+
#
|
51
|
+
# Thanks to whoever made it.
|
52
|
+
def deep_merge(hash)
|
53
|
+
target = dup
|
54
|
+
hash.keys.each do |key|
|
55
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
56
|
+
target[key] = target[key].deep_merge(hash[key])
|
57
|
+
next
|
58
|
+
end
|
59
|
+
target[key] = hash[key]
|
60
|
+
end
|
61
|
+
target
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Stack
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :source, :target
|
4
|
+
|
5
|
+
def initialize(hash = nil)
|
6
|
+
self.from_hash(hash)
|
7
|
+
end
|
8
|
+
|
9
|
+
def from_hash(hash)
|
10
|
+
if (hash != nil)
|
11
|
+
@source = hash[:source]
|
12
|
+
@target = hash[:target]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/stack/runner.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Stack
|
2
|
+
class Runner
|
3
|
+
attr_accessor :configuration
|
4
|
+
attr_accessor :command
|
5
|
+
attr_accessor :arguments
|
6
|
+
|
7
|
+
def initialize(argv)
|
8
|
+
@argv = argv
|
9
|
+
@options = { }
|
10
|
+
|
11
|
+
parse!
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parse options, command and arguments
|
15
|
+
def parse!
|
16
|
+
options = Stack::parse! @argv
|
17
|
+
|
18
|
+
@configuration = Stack::Configuration.new(options)
|
19
|
+
|
20
|
+
@command = @argv.shift
|
21
|
+
@arguments = @argv
|
22
|
+
end
|
23
|
+
|
24
|
+
# Run stack!
|
25
|
+
def run!
|
26
|
+
if @command.nil?
|
27
|
+
@command = "generate"
|
28
|
+
end
|
29
|
+
|
30
|
+
if Stack::COMMANDS.include?(@command)
|
31
|
+
run_command
|
32
|
+
else
|
33
|
+
abort "Unknown command: #{@command}. Use one of #{Stack::COMMANDS.join(", ")}."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Runs the specified command
|
38
|
+
def run_command
|
39
|
+
Stack::Generator.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/stack.rb
CHANGED
@@ -1,28 +1,82 @@
|
|
1
1
|
# rubygems
|
2
2
|
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require 'core_ext/hash'
|
6
|
+
|
7
|
+
require 'stack/configuration'
|
8
|
+
require 'stack/generator'
|
9
|
+
require 'stack/runner'
|
3
10
|
|
4
11
|
module Stack
|
5
|
-
# Default options used by stack, overridden from the command line or
|
12
|
+
# Default options used by stack, overridden from the command line or YML configration file.
|
6
13
|
DEFAULTS = {
|
7
|
-
|
14
|
+
:source => '.',
|
15
|
+
:target => File.join('.', '_stack')
|
8
16
|
}.freeze
|
9
17
|
|
18
|
+
# Array of valid commands stack can use
|
19
|
+
COMMANDS = %w(create generate server)
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :runner
|
23
|
+
end
|
24
|
+
|
25
|
+
# Parses the options configuration from the command line
|
26
|
+
def self.parse!(argv)
|
27
|
+
config = { }
|
28
|
+
|
29
|
+
parser = OptionParser.new do |opts|
|
30
|
+
opts.banner = "Usage: stack [options] #{Stack::COMMANDS.join('|')}"
|
31
|
+
|
32
|
+
opts.on("-s", "--source [DIR]", "Directory to use as the source for generating a stack") do |l| config[:source] = l unless l.nil? end
|
33
|
+
opts.on("-t", "--target [DIR]", "Directory to use as the target directory") do |l| config[:target] = l unless l.nil? end
|
34
|
+
|
35
|
+
opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
|
36
|
+
opts.on_tail("-v", "--version" "Show version") do puts "stack #{Stack::version}"; exit; end
|
37
|
+
end
|
38
|
+
|
39
|
+
parser.parse! argv
|
40
|
+
|
41
|
+
options = Stack::configuration(config)
|
42
|
+
|
43
|
+
options
|
44
|
+
end
|
45
|
+
|
46
|
+
# Merges the configuration from YAML file, command line and defaults
|
10
47
|
def self.configuration(override)
|
11
48
|
config = { }
|
49
|
+
source = File.join(override['source'] || Stack::DEFAULTS[:source])
|
50
|
+
|
51
|
+
config_file = File.join(source, "_stack.yml")
|
12
52
|
|
13
53
|
begin
|
14
|
-
|
15
|
-
rescue => error
|
54
|
+
yml = YAML.load_file(config_file)
|
16
55
|
|
56
|
+
raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash)
|
57
|
+
|
58
|
+
yml.each { |key, value| config[key.to_sym] = value }
|
59
|
+
|
60
|
+
STDOUT.puts "Configuration loaded from #{config_file}"
|
61
|
+
rescue => error
|
62
|
+
STDERR.puts "WARNING: Could not read configuration. Using defaults (and options)."
|
63
|
+
STDERR.puts "\t" + error.to_s
|
17
64
|
end
|
18
65
|
|
19
66
|
# Merge configuration with defaults
|
20
|
-
Stack::DEFAULTS.deep_merge(
|
67
|
+
Stack::DEFAULTS.deep_merge(override).deep_merge(config)
|
21
68
|
end
|
22
69
|
|
23
70
|
# Stacks current version
|
24
71
|
def self.version
|
25
|
-
|
26
|
-
|
72
|
+
version_file = File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])
|
73
|
+
|
74
|
+
if File.exist?(version_file)
|
75
|
+
yml = YAML.load(File.read(version_file))
|
76
|
+
|
77
|
+
"#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
|
78
|
+
else
|
79
|
+
"0.0.0"
|
80
|
+
end
|
27
81
|
end
|
28
82
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sixones
|
@@ -32,13 +32,16 @@ extra_rdoc_files:
|
|
32
32
|
- LICENSE
|
33
33
|
- README.rdoc
|
34
34
|
files:
|
35
|
-
- .document
|
36
|
-
- .gitignore
|
37
35
|
- LICENSE
|
38
36
|
- README.rdoc
|
39
37
|
- Rakefile
|
40
|
-
- VERSION
|
38
|
+
- VERSION.yml
|
39
|
+
- bin/stack
|
40
|
+
- lib/core_ext/hash.rb
|
41
41
|
- lib/stack.rb
|
42
|
+
- lib/stack/configuration.rb
|
43
|
+
- lib/stack/generator.rb
|
44
|
+
- lib/stack/runner.rb
|
42
45
|
- test/helper.rb
|
43
46
|
- test/test_stack.rb
|
44
47
|
has_rdoc: true
|
data/.document
DELETED
data/.gitignore
DELETED
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.1
|