rap 0.12.3 → 0.13.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/History +7 -0
- data/README +36 -18
- data/bin/rap +44 -84
- data/doc/Syntax Reference +35 -27
- data/lib/rap.rb +6 -0
- data/lib/rap/declaration_task.rb +124 -22
- data/lib/rap/declarations.rb +83 -42
- data/lib/rap/description.rb +4 -4
- data/lib/rap/rake.rb +19 -10
- data/lib/rap/utils.rb +18 -0
- metadata +5 -6
- data/doc/Command Reference +0 -22
- data/lib/rap/rake_app.rb +0 -107
data/History
CHANGED
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= {Rap (Rakish App)}[http://tap.rubyforge.org/rap]
|
2
2
|
|
3
3
|
rap v. a quick, sharp knock or blow
|
4
|
-
|
4
|
+
rak.ish adj. having a dashing, jaunty, or slightly disreputable quality or appearance
|
5
5
|
|
6
6
|
A rakish extension to {Tap}[http://tap.rubyforge.org/rdoc].
|
7
7
|
|
@@ -20,16 +20,13 @@ Check out these links for documentation, development, and bug tracking.
|
|
20
20
|
|
21
21
|
== Usage
|
22
22
|
|
23
|
-
Usage is much like {
|
23
|
+
Usage is much like {Rake}[http://rake.rubyforge.org/]:
|
24
24
|
|
25
25
|
[Rapfile]
|
26
|
-
require 'rap/declarations'
|
27
|
-
include Rap::Declarations
|
28
|
-
|
29
|
-
desc "your basic goodnight moon task"
|
30
26
|
|
27
|
+
# ::desc your basic goodnight moon task
|
31
28
|
# Says goodnight with a configurable message.
|
32
|
-
task(:goodnight, :obj, :message => 'goodnight') do |task, args|
|
29
|
+
Rap.task(:goodnight, :obj, :message => 'goodnight') do |task, args|
|
33
30
|
puts "#{task.message} #{args.obj}\n"
|
34
31
|
end
|
35
32
|
|
@@ -52,13 +49,14 @@ Now from the command line:
|
|
52
49
|
--message MESSAGE
|
53
50
|
|
54
51
|
options:
|
55
|
-
|
56
|
-
--name NAME
|
57
|
-
--
|
52
|
+
--help Print this help
|
53
|
+
--name NAME Specifies the task name
|
54
|
+
--config FILE Specifies a config file
|
58
55
|
|
59
56
|
For testing, load the Rapfile and access the task as a constant.
|
60
57
|
|
61
58
|
[test.rb]
|
59
|
+
require 'rap'
|
62
60
|
load 'Rapfile'
|
63
61
|
require 'test/unit'
|
64
62
|
require 'stringio'
|
@@ -86,19 +84,39 @@ The test passes:
|
|
86
84
|
1 tests, 2 assertions, 0 failures, 0 errors
|
87
85
|
|
88
86
|
Generally speaking, the rap executable is a shorthand for 'tap run --' so you
|
89
|
-
can use rap to
|
90
|
-
|
91
|
-
|
87
|
+
can use rap to launch workflows as well.
|
88
|
+
|
89
|
+
== Limitations
|
90
|
+
|
91
|
+
Rap is not a pure replacement of Rake, nor do the Rap tasks behave exactly
|
92
|
+
like standard Tap tasks.
|
93
|
+
|
94
|
+
==== Regarding Rake:
|
95
|
+
|
96
|
+
* Rap does not support builds by default
|
97
|
+
* Classes like FileList are not available
|
98
|
+
* Namespace lookup is slightly different (see the {Syntax Reference}[link:files/doc/Syntax%20Reference.html])
|
99
|
+
|
100
|
+
That said, many rakefiles can be renamed as rapfiles and they'll work with
|
101
|
+
minor and sometimes no changes.
|
102
|
+
|
103
|
+
==== Regarding Tap
|
104
|
+
|
105
|
+
Rap tasks (ie subclasses of Rap::DeclarationTask) are designed to behave like
|
106
|
+
Rake tasks. As such Rap tasks:
|
92
107
|
|
93
|
-
|
108
|
+
* return nil and pass nil in workflows
|
109
|
+
* only execute once
|
110
|
+
* are effectively singletons
|
94
111
|
|
95
|
-
|
96
|
-
|
97
|
-
|
112
|
+
This makes rap tasks useful in dependency-based workflows but fairly useless
|
113
|
+
in imperative workflows. However, other tasks behave as normal and any
|
114
|
+
workflow you can run with 'tap run' can be run without alteration by rap.
|
98
115
|
|
99
116
|
== Installation
|
100
117
|
|
101
|
-
Rap is available as a gem on RubyForge[http://rubyforge.org/projects/tap].
|
118
|
+
Rap is available as a gem on RubyForge[http://rubyforge.org/projects/tap].
|
119
|
+
Use:
|
102
120
|
|
103
121
|
% gem install rap
|
104
122
|
|
data/bin/rap
CHANGED
@@ -2,20 +2,14 @@
|
|
2
2
|
# usage: rap taskname {options} [args] [-d-]
|
3
3
|
|
4
4
|
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
5
|
-
require 'rap
|
5
|
+
require 'rap'
|
6
6
|
|
7
7
|
# setup the environment
|
8
8
|
begin
|
9
9
|
|
10
|
-
env = Tap::Exe.setup
|
11
|
-
|
12
|
-
|
13
|
-
Dir.glob('[TtRr]apfile{,.rb}').each do |task_file|
|
14
|
-
task_file = File.expand_path(task_file)
|
15
|
-
next unless File.file?(task_file)
|
16
|
-
|
17
|
-
env.loads.unshift(task_file)
|
18
|
-
end
|
10
|
+
env = Tap::Exe.setup
|
11
|
+
Rap::Declarations.env = env
|
12
|
+
env.activate
|
19
13
|
|
20
14
|
rescue(Tap::Env::ConfigError)
|
21
15
|
# catch errors and exit gracefully
|
@@ -24,92 +18,58 @@ rescue(Tap::Env::ConfigError)
|
|
24
18
|
exit(1)
|
25
19
|
end
|
26
20
|
|
27
|
-
#
|
28
|
-
# setup after script
|
29
|
-
#
|
30
|
-
|
31
|
-
at_exit do
|
32
|
-
begin
|
33
|
-
eval(env.after) if env.after != nil
|
34
|
-
rescue(Exception)
|
35
|
-
puts "Error in after script."
|
36
|
-
env.handle_error($!)
|
37
|
-
exit(1)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
#
|
42
|
-
# run before script
|
43
|
-
#
|
44
|
-
|
45
|
-
begin
|
46
|
-
eval(env.before) if env.before != nil
|
47
|
-
rescue(Exception)
|
48
|
-
puts "Error in before script."
|
49
|
-
env.handle_error($!)
|
50
|
-
exit(1)
|
51
|
-
end
|
52
|
-
|
53
21
|
#
|
54
22
|
# run rap
|
55
23
|
#
|
56
24
|
|
57
|
-
|
58
|
-
|
25
|
+
Dir.glob('[TtRr]apfile{,.rb}').each do |rapfile|
|
26
|
+
next unless File.file?(rapfile)
|
27
|
+
load rapfile
|
59
28
|
end
|
60
29
|
|
61
|
-
|
62
|
-
|
30
|
+
case ARGV[0]
|
31
|
+
when '--help', nil, '-T'
|
63
32
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
<%=
|
33
|
+
# same as normal summarize, but pass over tasks that have no comment
|
34
|
+
summary_template = %Q{<% entries.delete_if {|key, const| const.comment.kind_of?(Rap::Description) && const.comment.resolve.desc == nil } %>
|
35
|
+
<% if !entries.empty? && count > 1 %>
|
36
|
+
<%= env_key %>:
|
68
37
|
<% end %>
|
69
|
-
<% entries.each do |
|
70
|
-
|
71
|
-
<%
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
puts Lazydoc.usage(__FILE__)
|
81
|
-
puts
|
82
|
-
puts "=== tap tasks ==="
|
83
|
-
puts env.summarize(:tasks, rap_template)
|
38
|
+
<% entries.each do |key, const| %>
|
39
|
+
<%= key.ljust(width) %> # <%= const.comment %>
|
40
|
+
<% end %>
|
41
|
+
}
|
42
|
+
|
43
|
+
puts Lazydoc.usage(__FILE__)
|
44
|
+
puts
|
45
|
+
puts "=== tap tasks ==="
|
46
|
+
puts env.manifest(:task).summarize(summary_template)
|
47
|
+
|
48
|
+
if Rap::Rake.has_rakefile?
|
84
49
|
puts
|
85
50
|
puts "=== rake tasks ==="
|
86
|
-
Rap::Rake.new.
|
87
|
-
Tap::App.instance.run
|
88
|
-
|
89
|
-
# this is not currently reached as rake exits on -T
|
90
|
-
puts
|
91
|
-
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
92
|
-
exit
|
93
|
-
else
|
94
|
-
app = Tap::App.instance
|
95
|
-
schema = Tap::Support::Schema.parse(ARGV)
|
96
|
-
ARGV.clear
|
97
|
-
env.build(schema, app) do |args|
|
98
|
-
warn "warning: implict rake for [#{args.join(' ')}]"
|
99
|
-
Rap::Rake
|
100
|
-
end
|
101
|
-
|
102
|
-
if app.queue.empty?
|
103
|
-
puts "no task specified"
|
104
|
-
exit
|
105
|
-
end
|
106
|
-
|
107
|
-
env.set_signals
|
108
|
-
app.run
|
51
|
+
Rap::Rake.new.execute('-T')
|
109
52
|
end
|
110
53
|
|
111
|
-
|
112
|
-
|
54
|
+
puts
|
55
|
+
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
56
|
+
else
|
57
|
+
begin
|
58
|
+
schema = Tap::Schema.parse(ARGV)
|
59
|
+
env.run(schema) do |type, key, metadata|
|
60
|
+
if type == :task && Rap::Rake.has_rakefile?
|
61
|
+
warn "warning: implict rake for '#{metadata.join(' ')}'"
|
62
|
+
metadata.unshift(key)
|
63
|
+
Rap::Rake
|
64
|
+
else
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
rescue
|
69
|
+
raise if $DEBUG
|
70
|
+
puts $!.message
|
71
|
+
exit(1)
|
72
|
+
end
|
113
73
|
end
|
114
74
|
|
115
75
|
exit(0)
|
data/doc/Syntax Reference
CHANGED
@@ -4,13 +4,7 @@
|
|
4
4
|
|
5
5
|
A task declaration:
|
6
6
|
|
7
|
-
|
8
|
-
# key of a {key => dependencies} hash
|
9
|
-
# dependencies:: an array of task names (optional)
|
10
|
-
# arg_names:: an array of argument names (optional)
|
11
|
-
# configurations:: a hash of {key => default} pairs (optional)
|
12
|
-
|
13
|
-
task({<name> => [<dependencies...>]}, <arg_names...>, {<configs>}) do |task, args|
|
7
|
+
task(<name>, <arg_names...>, {<configs>}) do |task, args|
|
14
8
|
# arguments are available through args:
|
15
9
|
args.arg_name
|
16
10
|
|
@@ -18,6 +12,10 @@ A task declaration:
|
|
18
12
|
task.key
|
19
13
|
end
|
20
14
|
|
15
|
+
A task declaration with dependencies:
|
16
|
+
|
17
|
+
task({<name> => [<dependencies...>]}, <arg_names...>, {<configs>}) { task ... }
|
18
|
+
|
21
19
|
A namespace declaration:
|
22
20
|
|
23
21
|
namespace(<name>) { task ... }
|
@@ -39,19 +37,19 @@ Extended documentation:
|
|
39
37
|
# Lines are justified and wrapped on the command line.
|
40
38
|
task ...
|
41
39
|
|
42
|
-
Pains were taken to make task declarations for
|
43
|
-
tasks.
|
44
|
-
|
40
|
+
Pains were taken to make task declarations for Rap work the similar to Rake
|
41
|
+
tasks. For both Rake and Rap (noting that in general task classes are not
|
42
|
+
limited in these ways):
|
45
43
|
|
46
44
|
* tasks are singleton instances that may be extended across multiple
|
47
45
|
declarations
|
48
46
|
* tasks do not pass inputs from one task to the next
|
49
47
|
* tasks only execute once
|
50
48
|
|
51
|
-
A few syntactical differences between
|
52
|
-
can cause errors
|
49
|
+
A few syntactical differences between Rake and Rap must to be noted, as they
|
50
|
+
can cause errors during migration.
|
53
51
|
|
54
|
-
====
|
52
|
+
==== No :needs
|
55
53
|
|
56
54
|
Rap does not support :needs as a way to specify dependencies. For instance,
|
57
55
|
this will declare a ':needs' configuration with the default value ':another',
|
@@ -59,24 +57,34 @@ not a task which depends on another:
|
|
59
57
|
|
60
58
|
Rap.task :name, :needs => :another
|
61
59
|
|
62
|
-
====
|
60
|
+
==== Namespace Lookup
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
Rap immediately resolves dependencies relative to the top level namespace,
|
63
|
+
which is very different from Rake. Rake waits to resolve dependencies and will
|
64
|
+
use a match within a namespace if it becomes available. For these tasks rap
|
65
|
+
and rake produce different results:
|
68
66
|
|
69
|
-
|
67
|
+
[Rapfile/Rakfile]
|
68
|
+
|
69
|
+
task(:outer) { print 'non-nested' }
|
70
70
|
namespace :nest do
|
71
|
-
task
|
72
|
-
task :outer {
|
71
|
+
task(:inner1 => :outer) { puts ' was executed' }
|
72
|
+
task(:inner2 => 'nest:outer') { puts ' was executed' }
|
73
|
+
task(:outer) { print 'nested' }
|
73
74
|
end
|
74
75
|
|
75
|
-
|
76
|
-
within a namespace in preference to a literal match. For these tasks rap and
|
77
|
-
rake produce different results:
|
76
|
+
Rap resolves the dependencies literally:
|
78
77
|
|
79
|
-
% rap nest/
|
78
|
+
% rap nest/inner1
|
80
79
|
non-nested was executed
|
81
|
-
|
82
|
-
|
80
|
+
|
81
|
+
% rap nest/inner2
|
82
|
+
nested was executed
|
83
|
+
|
84
|
+
Rake resolves the dependencies relative to the namespace:
|
85
|
+
|
86
|
+
% rake nest:inner1
|
87
|
+
nested was executed
|
88
|
+
|
89
|
+
% rake nest:inner2
|
90
|
+
nested was executed
|
data/lib/rap.rb
ADDED
data/lib/rap/declaration_task.rb
CHANGED
@@ -1,14 +1,41 @@
|
|
1
|
-
require 'tap'
|
1
|
+
require 'tap/task'
|
2
|
+
require 'tap/env'
|
2
3
|
require 'ostruct'
|
3
4
|
require 'rap/description'
|
4
5
|
|
5
6
|
module Rap
|
6
7
|
|
7
|
-
# DeclarationTasks are a
|
8
|
-
#
|
9
|
-
#
|
8
|
+
# DeclarationTasks are a special breed of Tap::Task designed to behave much
|
9
|
+
# like Rake tasks. As such, declaration tasks:
|
10
|
+
#
|
11
|
+
# * return nil and pass nil in workflows
|
12
|
+
# * only execute once
|
13
|
+
# * are effectively singletons (one instance per app)
|
14
|
+
# * allow for multiple actions
|
15
|
+
#
|
16
|
+
# The DeclarationTask class partially includes Declarations so subclasses
|
17
|
+
# may directly declare tasks. A few alias acrobatics makes it so that ONLY
|
18
|
+
# Declarations#task is made available (desc cannot be used because Task
|
19
|
+
# classes already use that method for documentation, and namespace
|
20
|
+
# would be silly).
|
21
|
+
#
|
22
|
+
# Weird? Yes, but it leads to this syntax:
|
23
|
+
#
|
24
|
+
# # [Rapfile]
|
25
|
+
# # class Subclass < Rap::DeclarationTask
|
26
|
+
# # def helper(); "help"; end
|
27
|
+
# # end
|
28
|
+
# #
|
29
|
+
# # # ::desc a help task
|
30
|
+
# # Subclass.task(:help) {|task, args| puts "got #{task.helper}"}
|
31
|
+
#
|
32
|
+
# % rap help
|
33
|
+
# got help
|
34
|
+
#
|
10
35
|
class DeclarationTask < Tap::Task
|
11
36
|
class << self
|
37
|
+
|
38
|
+
# Sets actions.
|
12
39
|
attr_writer :actions
|
13
40
|
|
14
41
|
# An array of actions (blocks) associated with this class. Each of the
|
@@ -18,6 +45,7 @@ module Rap
|
|
18
45
|
@actions ||= []
|
19
46
|
end
|
20
47
|
|
48
|
+
# Sets argument names
|
21
49
|
attr_writer :arg_names
|
22
50
|
|
23
51
|
# The argument names pulled from a task declaration.
|
@@ -32,24 +60,43 @@ module Rap
|
|
32
60
|
args
|
33
61
|
end
|
34
62
|
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
63
|
+
# Instantiates the instance of self for app and reconfigures it using
|
64
|
+
# argh. Configurations are set, the task name is set, and the
|
65
|
+
# arguments are stored on the instance. The arguments are returned
|
66
|
+
# as normal in the [instance, args] result.
|
67
|
+
#
|
68
|
+
# These atypical behaviors handle various situations on the command
|
69
|
+
# line. Setting the args this way, for example, allows arguments to
|
70
|
+
# be specified on dependency tasks:
|
71
|
+
#
|
72
|
+
# # [Rapfile]
|
73
|
+
# # Rap.task(:a, :obj) {|t, a| puts "A #{a.obj}"}
|
74
|
+
# # Rap.task({:b => :a}, :obj) {|t, a| puts "B #{a.obj}"}
|
75
|
+
#
|
76
|
+
# % rap b world -- a hello
|
77
|
+
# A hello
|
78
|
+
# B world
|
79
|
+
#
|
80
|
+
def instantiate(argh={}, app=Tap::App.instance)
|
81
|
+
config = argh[:config]
|
82
|
+
config_file = argh[:config_file]
|
83
|
+
|
84
|
+
instance = self.instance(app)
|
85
|
+
instance.reconfigure(load_config(config_file)) if config_file
|
86
|
+
instance.reconfigure(config) if config
|
87
|
+
instance.args = argh[:args]
|
88
|
+
|
89
|
+
[instance, instance.args]
|
40
90
|
end
|
41
91
|
|
42
|
-
# Looks up or creates the DeclarationTask subclass specified by
|
43
|
-
#
|
44
|
-
# Declare also registers the subclass in the declaration_env tasks
|
45
|
-
# manifest.
|
46
|
-
#
|
47
|
-
# Configurations are always validated using the yaml transformation block
|
48
|
-
# (see {Configurable::Validation.yaml}[http://tap.rubyforge.org/configurable/classes/Configurable/Validation.html]).
|
92
|
+
# Looks up or creates the DeclarationTask subclass specified by const_name
|
93
|
+
# and adds the configs and dependencies.
|
49
94
|
#
|
95
|
+
# Configurations are always validated using the yaml transformation block
|
96
|
+
# (see {Configurable::Validation}[http://tap.rubyforge.org/configurable/classes/Configurable/Validation.html]).
|
50
97
|
def subclass(const_name, configs={}, dependencies=[])
|
51
98
|
# lookup or generate the subclass
|
52
|
-
subclass = Tap::
|
99
|
+
subclass = Tap::Env::Constant.constantize(const_name.to_s) do |base, constants|
|
53
100
|
subclass_const = constants.pop
|
54
101
|
constants.inject(base) do |namespace, const|
|
55
102
|
# nesting Task classes into other Task classes is required
|
@@ -72,19 +119,74 @@ module Rap
|
|
72
119
|
|
73
120
|
# add dependencies
|
74
121
|
dependencies.each do |dependency|
|
75
|
-
dependency_name = File.basename(dependency.
|
122
|
+
dependency_name = File.basename(dependency.to_s.underscore)
|
123
|
+
|
124
|
+
# this suppresses 'method redefined' warnings
|
125
|
+
if subclass.method_defined?(dependency_name)
|
126
|
+
subclass.send(:undef_method, dependency_name)
|
127
|
+
end
|
128
|
+
|
76
129
|
subclass.send(:depends_on, dependency_name, dependency)
|
77
130
|
end
|
78
131
|
|
79
132
|
subclass
|
80
133
|
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# The result of self, set by call.
|
137
|
+
attr_reader :result
|
138
|
+
|
139
|
+
# The arguments assigned to self during call.
|
140
|
+
attr_accessor :args
|
141
|
+
|
142
|
+
def initialize(config={}, app=Tap::App.instance)
|
143
|
+
super
|
144
|
+
@resolved = false
|
145
|
+
@result = nil
|
146
|
+
@args = nil
|
147
|
+
end
|
148
|
+
|
149
|
+
# Conditional call to the super call; only calls once. Returns result.
|
150
|
+
def call(*args)
|
81
151
|
|
82
|
-
|
152
|
+
# Declaration tasks function as dependencies, but unlike normal
|
153
|
+
# dependencies, they CAN take arguments from the command line.
|
154
|
+
# Such arguments will be set as args, and be used to enque the
|
155
|
+
# task.
|
156
|
+
#
|
157
|
+
# If the task executes from the queue first, args will be
|
158
|
+
# provided to call and they should equal self.args. If the task
|
159
|
+
# executes as a dependency first, call will not receive args and
|
160
|
+
# in that case self.args will be used.
|
161
|
+
#
|
162
|
+
# This warns for cases that odd workflows can produce where the
|
163
|
+
# args have been set and DIFFERENT args are used to enque the task.
|
164
|
+
# In these cases always go with the pre-set args but warn the issue.
|
165
|
+
self.args ||= args
|
166
|
+
unless self.args == args
|
167
|
+
if @resolved
|
168
|
+
warn "warn: ignorning dependency task inputs #{args.inspect} (#{self})"
|
169
|
+
else
|
170
|
+
warn "warn: invoking dependency task with preset args #{self.args.inspect} and not inputs #{args.inspect} (#{self})"
|
171
|
+
end
|
172
|
+
end
|
83
173
|
|
84
|
-
|
85
|
-
|
86
|
-
self
|
174
|
+
unless @resolved
|
175
|
+
@resolved = true
|
176
|
+
@result = super(*self.args)
|
87
177
|
end
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns true if already resolved by call.
|
182
|
+
def resolved?
|
183
|
+
@resolved
|
184
|
+
end
|
185
|
+
|
186
|
+
# Resets self so call will call again. Also sets result to nil.
|
187
|
+
def reset
|
188
|
+
@resolved = false
|
189
|
+
@result = nil
|
88
190
|
end
|
89
191
|
|
90
192
|
# Collects the inputs into an OpenStruct according to the class arg_names,
|
data/lib/rap/declarations.rb
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
require 'rap/declaration_task'
|
2
|
-
require '
|
2
|
+
require 'rap/utils'
|
3
3
|
|
4
4
|
module Rap
|
5
5
|
|
6
|
-
# Defines the
|
7
|
-
# top level (like Rake) or
|
8
|
-
# through Rap.
|
6
|
+
# Defines the Rap task declaration methods. They may be included at the
|
7
|
+
# top level (like Rake) or used through Rap.
|
9
8
|
#
|
10
|
-
#
|
9
|
+
# === Usage
|
10
|
+
#
|
11
|
+
# Unlike in rake, task will define actual task classes according to the task
|
11
12
|
# names. Task classes may be nested within modules using namespace. It's
|
12
13
|
# VERY important to realize this is the case both to aid in thing like
|
13
14
|
# testing and to prevent namespace conflicts. For example:
|
14
15
|
#
|
15
|
-
# Rap.task(:sample)
|
16
|
+
# t = Rap.task(:sample)
|
17
|
+
# t.class # => Sample
|
18
|
+
#
|
16
19
|
# Rap.namespace(:nested) do
|
17
|
-
# Rap.task(:sample)
|
20
|
+
# t = Rap.task(:sample)
|
21
|
+
# t.class # => Nested::Sample
|
18
22
|
# end
|
19
23
|
#
|
20
|
-
# Normally all declared tasks are subclasses of DeclarationTask
|
21
|
-
#
|
22
|
-
# to call declare on the subclass. This feature is only available to
|
23
|
-
# subclasses of DeclarationTask, but can be used within namespaces, and in
|
24
|
-
# conjunction with desc.
|
24
|
+
# Normally all declared tasks are subclasses of DeclarationTask, but
|
25
|
+
# subclasses of DeclarationTask can declare tasks as well.
|
25
26
|
#
|
26
27
|
# class Alt < DeclarationTask
|
27
28
|
# end
|
@@ -30,31 +31,41 @@ module Rap
|
|
30
31
|
#
|
31
32
|
# desc "task one, a subclass of DeclarationTask"
|
32
33
|
# o = Rap.task(:one)
|
33
|
-
# o.class
|
34
|
-
# o.class.superclass
|
35
|
-
# o.class.
|
34
|
+
# o.class # => One
|
35
|
+
# o.class.superclass # => DeclarationTask
|
36
|
+
# o.class.desc.to_s # => "task one, a subclass of DeclarationTask"
|
36
37
|
#
|
37
38
|
# namespace(:nest) do
|
38
|
-
#
|
39
39
|
# desc "task two, a nested subclass of Alt"
|
40
|
-
# t = Alt.
|
40
|
+
# t = Alt.task(:two)
|
41
41
|
# t.class # => Nest::Two
|
42
42
|
# t.class.superclass # => Alt
|
43
|
-
# t.class.
|
44
|
-
#
|
43
|
+
# t.class.desc.to_s # => "task two, a nested subclass of Alt"
|
45
44
|
# end
|
46
45
|
#
|
47
|
-
#
|
46
|
+
# This feature is only available to subclasses of DeclarationTask and can
|
47
|
+
# be very useful for creating inheritance hierarchies. Note that other
|
48
|
+
# declaration methods like 'desc' and 'namespace' are not available on
|
49
|
+
# DeclarationTask or subclasses, just 'task'.
|
50
|
+
#
|
51
|
+
# See the {Syntax Reference}[link:files/doc/Syntax%20Reference.html] for more
|
52
|
+
# information.
|
48
53
|
module Declarations
|
49
|
-
include
|
54
|
+
include Utils
|
50
55
|
|
51
56
|
# The environment in which declared task classes are registered.
|
52
|
-
# By default
|
53
|
-
def Declarations.env() @@env ||= Tap::Env.
|
57
|
+
# By default a Tap::Env for Dir.pwd.
|
58
|
+
def Declarations.env() @@env ||= Tap::Env.new; end
|
54
59
|
|
55
60
|
# Sets the declaration environment.
|
56
61
|
def Declarations.env=(env) @@env=env; end
|
57
62
|
|
63
|
+
# The declaration App (default Tap::App.instance)
|
64
|
+
def Declarations.app() @@app ||= Tap::App.instance; end
|
65
|
+
|
66
|
+
# Sets the declaration App.
|
67
|
+
def Declarations.app=(app) @@app=app; end
|
68
|
+
|
58
69
|
# The base constant for all task declarations, prepended to the task name.
|
59
70
|
def Declarations.current_namespace() @@current_namespace; end
|
60
71
|
@@current_namespace = ''
|
@@ -64,6 +75,11 @@ module Rap
|
|
64
75
|
def Declarations.current_desc() @@current_desc; end
|
65
76
|
@@current_desc = nil
|
66
77
|
|
78
|
+
# Returns the instance of the task class in app.
|
79
|
+
def Declarations.instance(tasc)
|
80
|
+
tasc.instance(Declarations.app)
|
81
|
+
end
|
82
|
+
|
67
83
|
# Declares a task with a rake-like syntax. Task generates a subclass of
|
68
84
|
# DeclarationTask, nested within the current namespace.
|
69
85
|
def task(*args, &action)
|
@@ -74,22 +90,27 @@ module Rap
|
|
74
90
|
|
75
91
|
# generate the task class
|
76
92
|
const_name = File.join(@@current_namespace, name.to_s).camelize
|
77
|
-
|
93
|
+
tasc = declaration_class.subclass(const_name, configs, dependencies)
|
78
94
|
|
79
95
|
# register documentation
|
80
|
-
|
81
|
-
|
96
|
+
desc = Lazydoc.register_caller(Description)
|
97
|
+
desc.desc = @@current_desc
|
82
98
|
@@current_desc = nil
|
83
99
|
|
84
|
-
|
85
|
-
|
86
|
-
|
100
|
+
tasc.arg_names = arg_names
|
101
|
+
tasc.desc = desc
|
102
|
+
tasc.source_file = desc.document.source_file
|
87
103
|
|
88
104
|
# add the action
|
89
|
-
|
105
|
+
tasc.actions << action if action
|
106
|
+
|
107
|
+
# register
|
108
|
+
register tasc
|
90
109
|
|
91
110
|
# return the instance
|
92
|
-
|
111
|
+
instance = Declarations.instance(tasc)
|
112
|
+
instance.config.bind(instance, true)
|
113
|
+
instance
|
93
114
|
end
|
94
115
|
|
95
116
|
# Nests tasks within the named module for the duration of the block.
|
@@ -152,7 +173,7 @@ module Rap
|
|
152
173
|
unless need.kind_of?(Class)
|
153
174
|
# lookup or declare non-class dependencies
|
154
175
|
name = normalize_name(need).camelize
|
155
|
-
need = Tap::
|
176
|
+
need = Tap::Env::Constant.constantize(name) do |base, constants|
|
156
177
|
const = block_given? ? yield(name) : nil
|
157
178
|
const or raise ArgumentError, "unknown task class: #{name}"
|
158
179
|
end
|
@@ -186,26 +207,46 @@ module Rap
|
|
186
207
|
|
187
208
|
# Registers a task class with the Declarations.env, if necessary.
|
188
209
|
# Returns task_class.
|
189
|
-
def register(
|
190
|
-
tasks = Declarations.env.
|
191
|
-
|
192
|
-
|
193
|
-
|
210
|
+
def register(tasc)
|
211
|
+
tasks = Declarations.env.manifest(:task)
|
212
|
+
|
213
|
+
const_name = tasc.to_s
|
214
|
+
constant = tasks.find do |const|
|
215
|
+
const.const_name == const_name
|
216
|
+
end
|
217
|
+
|
218
|
+
unless constant
|
219
|
+
constant = Tap::Env::Constant.new(const_name)
|
220
|
+
tasks.entries << constant
|
194
221
|
end
|
195
222
|
|
196
|
-
|
223
|
+
constant.comment = tasc.desc(false)
|
224
|
+
tasc
|
197
225
|
end
|
198
226
|
end
|
199
227
|
|
200
228
|
class DeclarationTask
|
201
229
|
class << self
|
230
|
+
# :stopdoc:
|
231
|
+
alias original_desc desc
|
232
|
+
# :startdoc:
|
233
|
+
|
202
234
|
include Declarations
|
203
235
|
|
204
|
-
#
|
205
|
-
|
236
|
+
# :stopdoc:
|
237
|
+
undef_method :desc
|
238
|
+
alias desc original_desc
|
239
|
+
|
240
|
+
# hide remaining Declarations methods (including Utils methods)
|
241
|
+
private :namespace, :sh
|
242
|
+
# :startdoc:
|
206
243
|
|
207
|
-
|
208
|
-
|
244
|
+
private
|
245
|
+
|
246
|
+
# overridden to provide self as the declaration_class
|
247
|
+
def declaration_class # :nodoc:
|
248
|
+
self
|
249
|
+
end
|
209
250
|
end
|
210
251
|
end
|
211
252
|
|
data/lib/rap/description.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module Rap
|
2
2
|
|
3
|
-
# :::-
|
3
|
+
# :startdoc:::-
|
4
4
|
# A special type of Lazydoc::Comment designed to handle the comment syntax
|
5
5
|
# for task declarations.
|
6
6
|
#
|
7
7
|
# Description instances can be assigned a description, or they may parse
|
8
8
|
# one directly from the comment. Comment lines with the constant attribute
|
9
9
|
# '::desc' will have the value set as desc.
|
10
|
-
# :::+
|
10
|
+
# :startdoc:::+
|
11
11
|
class Description < Lazydoc::Comment
|
12
12
|
|
13
13
|
# The description for self.
|
@@ -15,8 +15,8 @@ module Rap
|
|
15
15
|
|
16
16
|
# Parses in-comment descriptions from prepended lines, if present.
|
17
17
|
def prepend(line)
|
18
|
-
if line =~ /::desc
|
19
|
-
self.desc = $1
|
18
|
+
if line =~ /::desc(?:\s+(.*?))?\s*$/
|
19
|
+
self.desc = $1.to_s
|
20
20
|
false
|
21
21
|
else
|
22
22
|
super
|
data/lib/rap/rake.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
2
3
|
|
3
4
|
module Rap
|
4
5
|
|
5
|
-
# :startdoc::
|
6
|
+
# :startdoc::task run rake tasks
|
6
7
|
#
|
7
8
|
# Simply enques the specified rake task(s) for execution. Useful when a
|
8
9
|
# rake task needs to be executed within a workflow. For example these
|
9
10
|
# are equivalent:
|
10
11
|
#
|
11
|
-
# %
|
12
|
+
# % rap rake test
|
12
13
|
# % rake test
|
13
14
|
#
|
14
15
|
# The only exeception is in the use of the --help option. Use --rake-help
|
@@ -16,7 +17,7 @@ module Rap
|
|
16
17
|
#
|
17
18
|
class Rake < Tap::Task
|
18
19
|
class << self
|
19
|
-
|
20
|
+
|
20
21
|
# Overrides Tap::Support::FrameworkClass#parse! to do
|
21
22
|
# nothing so that all args get passed forward to rake.
|
22
23
|
def parse!(argv, app=Tap::App.instance) # => instance, argv
|
@@ -24,13 +25,21 @@ module Rap
|
|
24
25
|
puts help
|
25
26
|
exit
|
26
27
|
end
|
27
|
-
|
28
|
+
argv = argv.collect {|arg| arg == '--rake-help' ? '--help' : arg}
|
29
|
+
[new({}, app), argv]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns true if Rake detects a rakefile.
|
33
|
+
def has_rakefile?
|
34
|
+
::Rake.application.have_rakefile != nil
|
28
35
|
end
|
29
36
|
end
|
30
|
-
|
37
|
+
|
38
|
+
# Executes Rake using the input arguments as if they came from the
|
39
|
+
# command line.
|
31
40
|
def process(*argv)
|
32
41
|
rake = ::Rake.application
|
33
|
-
|
42
|
+
|
34
43
|
# run as if from command line using argv
|
35
44
|
current_argv = ARGV.dup
|
36
45
|
begin
|
@@ -45,9 +54,9 @@ module Rap
|
|
45
54
|
ARGV.clear
|
46
55
|
ARGV.concat(current_argv)
|
47
56
|
end
|
48
|
-
|
49
|
-
rake.
|
50
|
-
|
57
|
+
|
58
|
+
rake.top_level
|
59
|
+
|
51
60
|
nil
|
52
61
|
end
|
53
62
|
end
|
data/lib/rap/utils.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rap
|
2
|
+
module Utils
|
3
|
+
# Run the system command +cmd+, passing the result to the block, if given.
|
4
|
+
# Raises an error if the command fails. Uses the same semantics as
|
5
|
+
# Kernel::exec and Kernel::system.
|
6
|
+
#
|
7
|
+
# Based on FileUtils#sh from Rake.
|
8
|
+
def sh(*cmd) # :yields: ok, status
|
9
|
+
ok = system(*cmd)
|
10
|
+
|
11
|
+
if block_given?
|
12
|
+
yield(ok, $?)
|
13
|
+
else
|
14
|
+
ok or raise "Command failed with status (#{$?.exitstatus}): [#{cmd.join(' ')}]"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Chiang
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-05-25 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.
|
23
|
+
version: 0.17.0
|
24
24
|
version:
|
25
25
|
description:
|
26
26
|
email: simon.a.chiang@gmail.com
|
@@ -32,19 +32,18 @@ extra_rdoc_files:
|
|
32
32
|
- README
|
33
33
|
- MIT-LICENSE
|
34
34
|
- History
|
35
|
-
- doc/Command Reference
|
36
35
|
- doc/Syntax Reference
|
37
36
|
files:
|
38
37
|
- lib/rap/declaration_task.rb
|
39
38
|
- lib/rap/declarations.rb
|
40
39
|
- lib/rap/description.rb
|
41
|
-
- lib/rap/rake_app.rb
|
42
40
|
- lib/rap/rake.rb
|
41
|
+
- lib/rap/utils.rb
|
42
|
+
- lib/rap.rb
|
43
43
|
- tap.yml
|
44
44
|
- README
|
45
45
|
- MIT-LICENSE
|
46
46
|
- History
|
47
|
-
- doc/Command Reference
|
48
47
|
- doc/Syntax Reference
|
49
48
|
has_rdoc: true
|
50
49
|
homepage: http://tap.rubyforge.org
|
data/doc/Command Reference
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
= Command Reference
|
2
|
-
|
3
|
-
Rap comes the rap executable. For help on the command line, type:
|
4
|
-
|
5
|
-
% rap --help
|
6
|
-
|
7
|
-
The rap executable is basically a shorthand for 'tap run --'. Specifying tasks
|
8
|
-
for rap is no different than 'tap run' (see the Tap {Command Reference}[http://tap.rubyforge.org/rdoc/files/doc/Command%20Reference.html]).
|
9
|
-
The only exception occurs when the task can't be found; unknown tasks are run
|
10
|
-
as if by rake. For instance all of these are the same:
|
11
|
-
|
12
|
-
Run a rake task with inputs and an ENV config:
|
13
|
-
|
14
|
-
% rake task_name[1,2,3] key=value
|
15
|
-
|
16
|
-
Explicitly run a Rap::Rake task using the same inputs:
|
17
|
-
|
18
|
-
% rap rake task_name[1,2,3] key=value
|
19
|
-
|
20
|
-
Implicitly run the Rap::Rake task:
|
21
|
-
|
22
|
-
% rap task_name[1,2,3] key=value
|
data/lib/rap/rake_app.rb
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
require 'tap'
|
4
|
-
|
5
|
-
module Rap
|
6
|
-
class RakeManifest < Tap::Support::Manifest
|
7
|
-
def initialize(env)
|
8
|
-
@env = env
|
9
|
-
rake = ::Rake.application
|
10
|
-
super(rake.have_rakefile(env.root.root) ? [rake.instance_variable_get(:@rakefile)] : [])
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module RakeApp
|
15
|
-
def self.extended(base)
|
16
|
-
Tap::Env.instantiate(Dir.pwd).activate unless Tap::Env.instance
|
17
|
-
base.env = Tap::Env.instance
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_accessor :env
|
21
|
-
|
22
|
-
def enq_top_level(app)
|
23
|
-
# takes the place of rake.top_level
|
24
|
-
if options.show_tasks
|
25
|
-
display_tasks_and_comments
|
26
|
-
exit
|
27
|
-
elsif options.show_prereqs
|
28
|
-
display_prerequisites
|
29
|
-
exit
|
30
|
-
else
|
31
|
-
top_level_tasks.each do |task_string|
|
32
|
-
name, args = parse_task_string(task_string)
|
33
|
-
task = self[name]
|
34
|
-
app.mq(task, :invoke, *args)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def collect_tasks(*args)
|
40
|
-
# a little song and dance for compliance with
|
41
|
-
# rake pre- and post-0.8.2
|
42
|
-
argv = args.empty? ? ARGV : args[0]
|
43
|
-
argv.collect! do |arg|
|
44
|
-
next(arg) unless arg =~ /^:([a-z_\d]+):(.*)$/
|
45
|
-
env_pattern = $1
|
46
|
-
rake_task = $2
|
47
|
-
|
48
|
-
next(arg) unless entry = env.find(:envs, env_pattern, false)
|
49
|
-
|
50
|
-
mini_path, env = entry
|
51
|
-
root_path = env.root.root
|
52
|
-
|
53
|
-
if have_rakefile(root_path)
|
54
|
-
# load sequence echos that in raw_load_rakefile
|
55
|
-
puts "(in #{root_path})" unless options.silent
|
56
|
-
current_global_rakefile = $rakefile
|
57
|
-
$rakefile = @rakefile
|
58
|
-
|
59
|
-
namespaces = Tap::Root.split(mini_path, false).delete_if do |segment|
|
60
|
-
segment.empty?
|
61
|
-
end
|
62
|
-
|
63
|
-
#if @rakefile != ''
|
64
|
-
eval nest_namespace(%Q{load "#{File.join(root_path, @rakefile)}"}, namespaces.dup)
|
65
|
-
#end
|
66
|
-
|
67
|
-
$rakefile = current_global_rakefile
|
68
|
-
@rakefile = nil
|
69
|
-
|
70
|
-
namespaces << rake_task
|
71
|
-
namespaces.join(":")
|
72
|
-
else
|
73
|
-
fail "No Rakefile found for '#{env_pattern}' (looking for: #{@rakefiles.join(', ')})"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
super
|
78
|
-
end
|
79
|
-
|
80
|
-
def have_rakefile(dir=nil)
|
81
|
-
return super() if dir == nil
|
82
|
-
Tap::Root.chdir(dir) { super() }
|
83
|
-
end
|
84
|
-
|
85
|
-
protected
|
86
|
-
|
87
|
-
NAMESPACE_STR = %Q{
|
88
|
-
namespace(:'%s') do
|
89
|
-
%s
|
90
|
-
end
|
91
|
-
}.strip
|
92
|
-
|
93
|
-
def nest_namespace(nest_str, namespaces)
|
94
|
-
return nest_str if namespaces.empty?
|
95
|
-
|
96
|
-
NAMESPACE_STR % [
|
97
|
-
namespaces.shift,
|
98
|
-
namespaces.empty? ? nest_str : nest_namespace(nest_str, namespaces)
|
99
|
-
]
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
Rake.application.extend Rap::RakeApp
|
105
|
-
Tap::Env.manifest(:rakefiles) do |env|
|
106
|
-
Rap::RakeManifest.new(env)
|
107
|
-
end
|