shake 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +229 -0
- data/Rakefile +5 -0
- data/examples/example +61 -0
- data/examples/example2 +30 -0
- data/lib/shake.rb +186 -0
- data/test/mock.rb +9 -0
- data/test/test_helper.rb +47 -0
- data/test/unit/params_test.rb +72 -0
- data/test/unit/shakefile_test.rb +44 -0
- data/test/unit/subclass_test.rb +29 -0
- data/test/unit/traverse_test.rb +15 -0
- metadata +67 -0
data/README.md
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
Shake
|
2
|
+
=====
|
3
|
+
|
4
|
+
**Simple command runner.**
|
5
|
+
|
6
|
+
Goals:
|
7
|
+
|
8
|
+
* Shake lets you create extendable CLI runners very easily.
|
9
|
+
|
10
|
+
* Shake intends to replicate Thor/Rake's basic functionality in one very small package.
|
11
|
+
|
12
|
+
Why not Rake or Thor?
|
13
|
+
|
14
|
+
* Shake starts up way faster than Thor and Rake.
|
15
|
+
* Rake doesn't support arguments.
|
16
|
+
* Rake can't be extended easily to support anything more than `rake` + `Rakefile`.
|
17
|
+
* Thor can be too huge for your purposes.
|
18
|
+
|
19
|
+
Shake was made with the idea of being easily-embeddable into your projects
|
20
|
+
for your command line runners. It's a single ~4kb Ruby file.
|
21
|
+
|
22
|
+
# Shakefile
|
23
|
+
# Place this file in your project somewhere
|
24
|
+
class Shake
|
25
|
+
task(:start) {
|
26
|
+
puts "Starting '#{params.join(' ')}'..."
|
27
|
+
}
|
28
|
+
|
29
|
+
task.description = "Starts something"
|
30
|
+
|
31
|
+
task(:stop) {
|
32
|
+
puts "Stopping..."
|
33
|
+
}
|
34
|
+
|
35
|
+
task.description = "Stops it"
|
36
|
+
end
|
37
|
+
|
38
|
+
In your shell:
|
39
|
+
|
40
|
+
$ shake start server
|
41
|
+
Starting 'server'...
|
42
|
+
|
43
|
+
$ shake stop
|
44
|
+
Stopping...
|
45
|
+
|
46
|
+
$ shake help
|
47
|
+
Commands:
|
48
|
+
start Starts something
|
49
|
+
stop Stops it
|
50
|
+
help Shows a list of commands
|
51
|
+
|
52
|
+
Usage
|
53
|
+
=====
|
54
|
+
|
55
|
+
### Using Shakefiles
|
56
|
+
|
57
|
+
Using the command `shake` will load your project's `Shakefile`.
|
58
|
+
|
59
|
+
# ~/project/Shakefile
|
60
|
+
class Shake
|
61
|
+
task(:deploy) do
|
62
|
+
puts "Deploying..."
|
63
|
+
system "ssh admin@server.com git pull && thin restart"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
And in your shell:
|
68
|
+
|
69
|
+
$ cd ~/project
|
70
|
+
$ shake deploy
|
71
|
+
Deploying...
|
72
|
+
|
73
|
+
### Parameters
|
74
|
+
|
75
|
+
Get the parameters with `params` (an array). Verify parameters with `wrong_usage`.
|
76
|
+
|
77
|
+
task(:init) do
|
78
|
+
wrong_usage if params.empty?
|
79
|
+
system "wget #{params.first}"
|
80
|
+
end
|
81
|
+
|
82
|
+
Example:
|
83
|
+
|
84
|
+
$ shake init
|
85
|
+
Invalid usage.
|
86
|
+
See `shake help` for more information.
|
87
|
+
|
88
|
+
### Parameter options and flags
|
89
|
+
|
90
|
+
You may get params from it with `params.extract` or `params.delete`. Doing `extract`
|
91
|
+
will remove it from params.
|
92
|
+
|
93
|
+
task(:create) do
|
94
|
+
type = params.extract('-t') || 'default'
|
95
|
+
quiet = params.delete('-q')
|
96
|
+
file = params.shift
|
97
|
+
wrong_usage if params.any?
|
98
|
+
|
99
|
+
puts "Creating '#{file}' (quiet: #{!!quiet}, type: #{type})"
|
100
|
+
end
|
101
|
+
|
102
|
+
Example:
|
103
|
+
|
104
|
+
$ shake create #=> Invalid
|
105
|
+
$ shake create foobar #=> Creating 'foobar' (quiet: false, type: default)
|
106
|
+
$ shake create foobar -q #=> Creating 'foobar' (quiet: true, type: default)
|
107
|
+
$ shake create foobar -t xyz #=> Creating 'foobar' (quiet: false, type: xyz)
|
108
|
+
|
109
|
+
# Common commands
|
110
|
+
|
111
|
+
Use `err` to print something to STDERR. Use `pass` to halt execution.
|
112
|
+
|
113
|
+
task(:delete) do
|
114
|
+
unless File.exists?(params.first)
|
115
|
+
err 'You can't delete something that doesn't exist!'
|
116
|
+
pass
|
117
|
+
end
|
118
|
+
|
119
|
+
FileUtils.rm_rf params.first
|
120
|
+
end
|
121
|
+
|
122
|
+
You may also pass parameters to `pass` to have it printed out before halting.
|
123
|
+
|
124
|
+
pass 'The target already exists.' if File.exists?(target)
|
125
|
+
|
126
|
+
### Default tasks
|
127
|
+
|
128
|
+
Use `default` to specify a default task. (The default task is usually `help`)
|
129
|
+
|
130
|
+
class Shake
|
131
|
+
task(:test) do
|
132
|
+
Dir['test/**/*_test.rb'].each { |f| load f }
|
133
|
+
end
|
134
|
+
|
135
|
+
default :test
|
136
|
+
end
|
137
|
+
|
138
|
+
# Typing `shake` will be the same as `shake test`
|
139
|
+
|
140
|
+
### Invalid commands
|
141
|
+
|
142
|
+
Use `invalid` to define what happens when
|
143
|
+
|
144
|
+
class Shake
|
145
|
+
invalid {
|
146
|
+
err "Invalid command. What's wrong with you?"
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
In your shell:
|
151
|
+
|
152
|
+
$ shake foobar
|
153
|
+
Invalid command. What's wrong with you?
|
154
|
+
|
155
|
+
### Defining helpers
|
156
|
+
|
157
|
+
Tasks are executed in the class's context, so just define your helpers like so:
|
158
|
+
|
159
|
+
module Helpers
|
160
|
+
def say_status(what, str)
|
161
|
+
puts "%15s %s" % [ what, str ]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class Shake
|
166
|
+
extend Helpers
|
167
|
+
end
|
168
|
+
|
169
|
+
Then use them in your tasks.
|
170
|
+
|
171
|
+
class Shake
|
172
|
+
task(:info) do
|
173
|
+
say_status :info, "It's a fine day"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
### Manual invocation
|
178
|
+
|
179
|
+
You can use shake in your projects without using the `shake` command. (recommended!)
|
180
|
+
|
181
|
+
require 'shake'
|
182
|
+
|
183
|
+
# If you want to load your own project file (optional)
|
184
|
+
file = Shake.find_in_project('Projectfile') and load file
|
185
|
+
|
186
|
+
# Now define some tasks, and then:
|
187
|
+
Shake.run!
|
188
|
+
|
189
|
+
### Subclassing Shake
|
190
|
+
|
191
|
+
You may subclass shake for your own project.
|
192
|
+
|
193
|
+
By default, it will not have any of the default tasks (that is, `shake help`, and
|
194
|
+
the "invalid command" message). Use `include Defaults` if you want this behavior.
|
195
|
+
|
196
|
+
require 'shake'
|
197
|
+
|
198
|
+
class CLI < Shake
|
199
|
+
include Defaults # optional, see above
|
200
|
+
|
201
|
+
task(:flip) do
|
202
|
+
what = rand < 0.5 ? "heads" : "tails"
|
203
|
+
puts "The coin says #{what}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
CLI.run!
|
208
|
+
|
209
|
+
### Defining tasks
|
210
|
+
|
211
|
+
# In your Shakefile or something
|
212
|
+
class Shake
|
213
|
+
task(:reset) do
|
214
|
+
# ...
|
215
|
+
end
|
216
|
+
|
217
|
+
task.description = "Resets passwords."
|
218
|
+
end
|
219
|
+
|
220
|
+
Alternatively:
|
221
|
+
|
222
|
+
class Shake
|
223
|
+
task(:reset) do
|
224
|
+
# ...
|
225
|
+
end
|
226
|
+
|
227
|
+
task(:reset).description = "Resets passwords."
|
228
|
+
end
|
229
|
+
|
data/Rakefile
ADDED
data/examples/example
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'shake'
|
3
|
+
|
4
|
+
## Example
|
5
|
+
# This is a very simple example of using Shake with a subclass.
|
6
|
+
|
7
|
+
class Monk < Shake
|
8
|
+
# Include the Shake default commands (like `help` and stuff)
|
9
|
+
# This is optional, but you probably want this for most cases.
|
10
|
+
include Defaults
|
11
|
+
|
12
|
+
# Define a task like this.
|
13
|
+
# The other command line options will be accesible as the
|
14
|
+
# `params` array. Pass it onto Clap or something.
|
15
|
+
task(:start) {
|
16
|
+
puts "Running..."
|
17
|
+
puts "Your options: #{params.inspect}"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Just `task` will return the last defined task.
|
21
|
+
# By the way, only `help` cares about the description (skip
|
22
|
+
# it if you wish), and you can add as much metadata to the
|
23
|
+
# tasks as you need.
|
24
|
+
task.description = "Starts the server"
|
25
|
+
|
26
|
+
# You may also define task metadata like this.
|
27
|
+
# Note that there are no namespaces, but feel free to use
|
28
|
+
# the colon anyway.
|
29
|
+
task(:'redis:start', :description => "Runs redis") {
|
30
|
+
puts "Starting redis..."
|
31
|
+
}
|
32
|
+
|
33
|
+
# Or this way:
|
34
|
+
task(:stop) {
|
35
|
+
puts "Stopping..."
|
36
|
+
}
|
37
|
+
|
38
|
+
task(:stop).description = "Stops the server"
|
39
|
+
end
|
40
|
+
|
41
|
+
# This gets ARGV and dispatches the appropriate task
|
42
|
+
Monk.run!
|
43
|
+
|
44
|
+
# Example output:
|
45
|
+
#
|
46
|
+
# $ ./monk
|
47
|
+
# Usage: monk <command>
|
48
|
+
#
|
49
|
+
# Commands:
|
50
|
+
# help Shows a list of commands
|
51
|
+
# start Starts the server
|
52
|
+
# redis:start Runs redis
|
53
|
+
# stop Stops the server
|
54
|
+
#
|
55
|
+
# $ ./monk start production
|
56
|
+
# Running...
|
57
|
+
# Your options: ['production']
|
58
|
+
#
|
59
|
+
# $ ./monk aaaa
|
60
|
+
# Unknown command: aaaa
|
61
|
+
# See `monk help` for a list of commands.
|
data/examples/example2
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'shake'
|
3
|
+
|
4
|
+
## Shake
|
5
|
+
# Shake is a very simple Thor/Rake replacement. It intends
|
6
|
+
# to replicate thor's basic functionality in <100loc.
|
7
|
+
#
|
8
|
+
# This is a very simple example.
|
9
|
+
#
|
10
|
+
Shake.task(:hello) {
|
11
|
+
puts "hi!"
|
12
|
+
}
|
13
|
+
|
14
|
+
Shake.run!
|
15
|
+
|
16
|
+
# Example output:
|
17
|
+
#
|
18
|
+
# $ ./example
|
19
|
+
# Usage: example <command>
|
20
|
+
#
|
21
|
+
# Commands:
|
22
|
+
# help
|
23
|
+
# hello
|
24
|
+
#
|
25
|
+
# $ ./example hello
|
26
|
+
# hi!
|
27
|
+
#
|
28
|
+
# $ ./example aaaa
|
29
|
+
# Unknown command: aaaa
|
30
|
+
# See `example help` for a list of commands.
|
data/lib/shake.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class Shake
|
4
|
+
VERSION = "0.1.0"
|
5
|
+
|
6
|
+
Abort = Class.new(StandardError)
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_reader :params
|
10
|
+
attr_reader :command
|
11
|
+
|
12
|
+
# By the way: every task gets evaluated in the context of the class.
|
13
|
+
# Just make more static methods (`def self.monkey`) if you need them
|
14
|
+
# in your tasks.
|
15
|
+
#
|
16
|
+
# This also means that all the methods here are available for use
|
17
|
+
# in your tasks.
|
18
|
+
|
19
|
+
# Returns a list of tasks.
|
20
|
+
# It gives out a hash with symbols as keys, and openstructs as values.
|
21
|
+
def tasks
|
22
|
+
@tasks ||= Hash.new
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets or retrieves a task.
|
26
|
+
# If no arguments are given, it returns the last task defined.
|
27
|
+
#
|
28
|
+
# Examples:
|
29
|
+
#
|
30
|
+
# task(:start) { ... }
|
31
|
+
# task(:start, description: 'Starts it') { ... }
|
32
|
+
# task(:start)
|
33
|
+
# task.description = "Starts it"
|
34
|
+
#
|
35
|
+
def task(what=nil, options={}, &blk)
|
36
|
+
return @last if what.nil?
|
37
|
+
|
38
|
+
key = what.downcase.to_sym
|
39
|
+
@last = tasks[key] = new_task(options, &blk) if block_given?
|
40
|
+
tasks[key]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets or retrieves the default task.
|
44
|
+
#
|
45
|
+
# Examples:
|
46
|
+
#
|
47
|
+
# default :default_task
|
48
|
+
# default { ... }
|
49
|
+
#
|
50
|
+
def default(what=nil, &blk)
|
51
|
+
@default = what || blk || @default
|
52
|
+
end
|
53
|
+
|
54
|
+
# Sets or retrieves the 'invalid command' task.
|
55
|
+
# See `default` for examples.
|
56
|
+
def invalid(what=nil, &blk)
|
57
|
+
@invalid = what || blk || @invalid
|
58
|
+
end
|
59
|
+
|
60
|
+
# Invokes a task with the given arguments.
|
61
|
+
# You may even nest multiple task invocations.
|
62
|
+
#
|
63
|
+
# Examples:
|
64
|
+
#
|
65
|
+
# invoke(:start)
|
66
|
+
# invoke(:start, 'nginx', 'memcache')
|
67
|
+
#
|
68
|
+
def invoke(what, *args)
|
69
|
+
old, @params = @params, args.extend(Params)
|
70
|
+
return if what.nil?
|
71
|
+
|
72
|
+
begin
|
73
|
+
return instance_eval(&what) if what.is_a?(Proc)
|
74
|
+
|
75
|
+
task = task(what) or return nil
|
76
|
+
instance_eval &task.proc
|
77
|
+
true
|
78
|
+
rescue Abort
|
79
|
+
true
|
80
|
+
ensure
|
81
|
+
@params = old
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Stops the execution of a task.
|
86
|
+
def pass(msg=nil)
|
87
|
+
err msg unless msg.nil?
|
88
|
+
raise Abort
|
89
|
+
end
|
90
|
+
|
91
|
+
# Halts a task because of wrong usage.
|
92
|
+
#
|
93
|
+
# Example:
|
94
|
+
#
|
95
|
+
# wrong_usage if params.any?
|
96
|
+
#
|
97
|
+
def wrong_usage
|
98
|
+
invoke(invalid) and pass
|
99
|
+
end
|
100
|
+
|
101
|
+
# Runs with the given arguments and dispatches the appropriate task.
|
102
|
+
# Use `run!` if you want to go with command line arguments.
|
103
|
+
#
|
104
|
+
# Example:
|
105
|
+
#
|
106
|
+
# # This is equivalent to `invoke(:start, 'nginx')`
|
107
|
+
# run 'start', 'nginx'
|
108
|
+
#
|
109
|
+
def run(*argv)
|
110
|
+
return invoke(default) if argv.empty?
|
111
|
+
|
112
|
+
@command = argv.shift
|
113
|
+
invoke(@command, *argv) or invoke(invalid, *argv)
|
114
|
+
end
|
115
|
+
|
116
|
+
def run!
|
117
|
+
run *ARGV
|
118
|
+
end
|
119
|
+
|
120
|
+
def executable
|
121
|
+
File.basename($0)
|
122
|
+
end
|
123
|
+
|
124
|
+
def err(str="")
|
125
|
+
$stderr.write "#{str}\n"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Traverse back it's parents and find the file called `file`.
|
129
|
+
def find_in_project(file)
|
130
|
+
dir = Dir.pwd
|
131
|
+
while true
|
132
|
+
path = File.join(dir, file)
|
133
|
+
return path if File.exists?(path)
|
134
|
+
|
135
|
+
parent = File.expand_path(File.join(dir, '..'))
|
136
|
+
return nil if parent == dir
|
137
|
+
|
138
|
+
dir = parent
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
protected
|
143
|
+
def new_task(options={}, &blk)
|
144
|
+
t = OpenStruct.new(options)
|
145
|
+
t.proc = blk
|
146
|
+
t
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module Params
|
151
|
+
def extract(what)
|
152
|
+
i = index(what) and slice!(i, 2)[1]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# This is a list of default commands.
|
157
|
+
# The class Shake itself uses this, but if you subclass it,
|
158
|
+
# you will have to do `include Defaults` yourself.
|
159
|
+
module Defaults
|
160
|
+
def self.included(to)
|
161
|
+
to.default :help
|
162
|
+
|
163
|
+
to.task(:help) {
|
164
|
+
err "Usage: #{executable} <command>"
|
165
|
+
err
|
166
|
+
err "Commands:"
|
167
|
+
tasks.each { |name, task| err " %-20s %s" % [ name, task.description ] }
|
168
|
+
}
|
169
|
+
|
170
|
+
to.task(:help).description = "Shows a list of commands"
|
171
|
+
|
172
|
+
to.invalid {
|
173
|
+
if task(command)
|
174
|
+
err "Invalid usage."
|
175
|
+
err "See `#{executable} help` for more info."
|
176
|
+
else
|
177
|
+
err "Unknown command: #{command}"
|
178
|
+
err "See `#{executable} help` for a list of commands."
|
179
|
+
end
|
180
|
+
}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
include Defaults
|
185
|
+
end
|
186
|
+
|
data/test/mock.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$: << File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'shake'
|
4
|
+
require 'contest'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
require File.expand_path('../mock', __FILE__)
|
8
|
+
|
9
|
+
class Test::Unit::TestCase
|
10
|
+
def temp_path(*a)
|
11
|
+
root %w(test tmp) + a
|
12
|
+
end
|
13
|
+
|
14
|
+
def root(*a)
|
15
|
+
File.join File.expand_path('../../', __FILE__), *a
|
16
|
+
end
|
17
|
+
|
18
|
+
setup do
|
19
|
+
$out, $err = '', ''
|
20
|
+
FileUtils.rm_rf temp_path if File.directory?(temp_path)
|
21
|
+
FileUtils.mkdir_p temp_path
|
22
|
+
Dir.chdir temp_path
|
23
|
+
end
|
24
|
+
|
25
|
+
teardown do
|
26
|
+
FileUtils.rm_rf temp_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def cout
|
30
|
+
$out
|
31
|
+
end
|
32
|
+
|
33
|
+
def cerr
|
34
|
+
$err
|
35
|
+
end
|
36
|
+
|
37
|
+
# Simulate bin/shake
|
38
|
+
def shake(*args)
|
39
|
+
ARGV.slice! 0, ARGV.length
|
40
|
+
args.each { |a| ARGV << a }
|
41
|
+
load File.expand_path('../../bin/shake', __FILE__)
|
42
|
+
end
|
43
|
+
|
44
|
+
def shakefile(str)
|
45
|
+
File.open('Shakefile', 'w') { |f| f.write str.strip }
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class ParamsTest < Test::Unit::TestCase
|
4
|
+
class Bake < ::Shake
|
5
|
+
task :heat do
|
6
|
+
wrong_usage if params.size != 1
|
7
|
+
puts "OK"
|
8
|
+
end
|
9
|
+
|
10
|
+
task :cool do
|
11
|
+
quiet = params.delete('-q')
|
12
|
+
type = params.extract('-t') || params.extract('--type') || 'default'
|
13
|
+
wrong_usage unless params.empty?
|
14
|
+
|
15
|
+
puts "Quiet #{!!quiet}, type #{type}"
|
16
|
+
end
|
17
|
+
|
18
|
+
invalid do
|
19
|
+
err "What?"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'wrong usage' do
|
24
|
+
Bake.run *%w{heat}
|
25
|
+
assert cerr == "What?\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'wrong usage 2' do
|
29
|
+
Bake.run *%w{heat x y}
|
30
|
+
assert cerr == "What?\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'proper usage' do
|
34
|
+
Bake.run *%w{heat x}
|
35
|
+
assert cout == "OK\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'cool' do
|
39
|
+
Bake.run 'cool'
|
40
|
+
assert cout == "Quiet false, type default\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'wrong usage' do
|
44
|
+
Bake.run *%w{cool down}
|
45
|
+
assert cerr == "What?\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'cool 2' do
|
49
|
+
Bake.run *%w{cool -q}
|
50
|
+
assert cout == "Quiet true, type default\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
test 'cool 3' do
|
54
|
+
Bake.run *%w{cool -t special}
|
55
|
+
assert cout == "Quiet false, type special\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
test 'cool 4' do
|
59
|
+
Bake.run *%w{cool -t special -q}
|
60
|
+
assert cout == "Quiet true, type special\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'cool 5' do
|
64
|
+
Bake.run *%w{cool -q -t}
|
65
|
+
assert cout == "Quiet true, type default\n"
|
66
|
+
end
|
67
|
+
|
68
|
+
test 'wrong usage again' do
|
69
|
+
Bake.run *%w{cool -q xyz}
|
70
|
+
assert cerr == "What?\n"
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class ShakefileTest < Test::Unit::TestCase
|
4
|
+
test 'no shakefile' do
|
5
|
+
shake
|
6
|
+
assert cout.empty?
|
7
|
+
assert cerr.include?('No Shakefile')
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'basics' do
|
11
|
+
setup do
|
12
|
+
shakefile %{
|
13
|
+
class Shake
|
14
|
+
task :start do
|
15
|
+
puts "Starting..."
|
16
|
+
puts params.inspect if params.any?
|
17
|
+
end
|
18
|
+
task.description = 'Starts the server'
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'help' do
|
24
|
+
shake 'help'
|
25
|
+
assert cout.empty?
|
26
|
+
assert cerr =~ /^ start *Starts the server/
|
27
|
+
end
|
28
|
+
|
29
|
+
test 'invalid command' do
|
30
|
+
shake 'stop'
|
31
|
+
assert cerr.include?('Unknown command: stop')
|
32
|
+
end
|
33
|
+
|
34
|
+
test 'run' do
|
35
|
+
shake 'start'
|
36
|
+
assert_equal "Starting...\n", cout
|
37
|
+
end
|
38
|
+
|
39
|
+
test 'run with args' do
|
40
|
+
shake *%w(start x)
|
41
|
+
assert_equal "Starting...\n[\"x\"]\n", cout
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class SubclassTest < Test::Unit::TestCase
|
4
|
+
class Bake < ::Shake
|
5
|
+
task :melt do
|
6
|
+
puts "Working..."
|
7
|
+
end
|
8
|
+
|
9
|
+
invalid do
|
10
|
+
err "What?"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'subclassing' do
|
15
|
+
Bake.run 'melt'
|
16
|
+
assert cout == "Working...\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'nothing to do' do
|
20
|
+
Bake.run
|
21
|
+
assert cerr.empty?
|
22
|
+
assert cout.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'invalid command' do
|
26
|
+
Bake.run 'foobar'
|
27
|
+
assert cerr == "What?\n"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class TraverseTest < Test::Unit::TestCase
|
4
|
+
test 'traverse backwards' do
|
5
|
+
shakefile %{
|
6
|
+
Shake.task(:create) { puts 'Creating...' }
|
7
|
+
}
|
8
|
+
|
9
|
+
Dir.mkdir 'xxx'
|
10
|
+
Dir.chdir 'xxx'
|
11
|
+
|
12
|
+
shake 'create'
|
13
|
+
assert_equal "Creating...\n", cout
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shake
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rico Sta. Cruz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-02-15 00:00:00 +08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Shake is a simple replacement for Thor/Rake.
|
18
|
+
email:
|
19
|
+
- rico@sinefunc.com
|
20
|
+
executables: []
|
21
|
+
|
22
|
+
extensions: []
|
23
|
+
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- lib/shake.rb
|
28
|
+
- test/mock.rb
|
29
|
+
- test/test_helper.rb
|
30
|
+
- test/unit/params_test.rb
|
31
|
+
- test/unit/shakefile_test.rb
|
32
|
+
- test/unit/subclass_test.rb
|
33
|
+
- test/unit/traverse_test.rb
|
34
|
+
- examples/example
|
35
|
+
- examples/example2
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: http://github.com/rstacruz/shake
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.5.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Simple command line runner.
|
66
|
+
test_files: []
|
67
|
+
|