shake 0.1.0
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/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
|
+
|