rc 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.index +66 -0
- data/.rubyrc +88 -0
- data/.yardopts +8 -0
- data/HISTORY.md +40 -0
- data/LICENSE.txt +27 -0
- data/README.md +194 -0
- data/demo/00_concept.md +23 -0
- data/demo/01_config.md +14 -0
- data/demo/02_configuration.md +51 -0
- data/demo/03_import.md +48 -0
- data/demo/06_interface.md +39 -0
- data/demo/applique/ae.rb +1 -0
- data/demo/applique/file.rb +8 -0
- data/demo/applique/fixture.rb +10 -0
- data/demo/applique/fixture/.ruby +11 -0
- data/demo/cov.rb +7 -0
- data/lib/c.rb +8 -0
- data/lib/rc.rb +10 -0
- data/lib/rc/api.rb +4 -0
- data/lib/rc/config.rb +305 -0
- data/lib/rc/config_filter.rb +110 -0
- data/lib/rc/configuration.rb +362 -0
- data/lib/rc/constants.rb +9 -0
- data/lib/rc/core_ext.rb +6 -0
- data/lib/rc/core_ext/argv.rb +22 -0
- data/lib/rc/core_ext/hash.rb +17 -0
- data/lib/rc/core_ext/kernel.rb +38 -0
- data/lib/rc/core_ext/string.rb +20 -0
- data/lib/rc/core_ext/symbol.rb +8 -0
- data/lib/rc/dsl.rb +72 -0
- data/lib/rc/interface.rb +338 -0
- data/lib/rc/properties.rb +108 -0
- data/lib/rc/required.rb +10 -0
- data/lib/rc/setup.rb +57 -0
- data/lib/rc/tweaks/rake.rb +31 -0
- metadata +118 -22
data/demo/01_config.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Config Class
|
2
|
+
|
3
|
+
The Config class encapsulates a single config entry. Every Config instance has a `command`, `feature`,
|
4
|
+
and `profile` atribute, as well as a procedure.
|
5
|
+
|
6
|
+
config = RC::Config.new('foo', :profile=>'bar') do
|
7
|
+
'example'
|
8
|
+
end
|
9
|
+
|
10
|
+
config.command #=> 'foo'
|
11
|
+
config.feature #=> 'foo'
|
12
|
+
config.profile #=> 'bar'
|
13
|
+
config.to_proc.call #=> 'example'
|
14
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Configuration
|
2
|
+
|
3
|
+
The Configuration class handle evaluation of a project configuration file.
|
4
|
+
|
5
|
+
rc = RC::Configuration.new
|
6
|
+
|
7
|
+
We can use the `#instance_eval` method to evaluate a configuration for our
|
8
|
+
demonstration.
|
9
|
+
|
10
|
+
rc.evaluate(<<-HERE)
|
11
|
+
config :sample1 do
|
12
|
+
"block code"
|
13
|
+
end
|
14
|
+
HERE
|
15
|
+
|
16
|
+
Evaluation of a configuration file, populate the Confection.config instance.
|
17
|
+
|
18
|
+
sample = rc.configurations.last
|
19
|
+
sample.command #=> 'sample1'
|
20
|
+
sample.profile #=> 'default'
|
21
|
+
sample.class #=> RC::Config
|
22
|
+
|
23
|
+
A profile can be used as a means fo defining multiple configurations
|
24
|
+
for a single tool. This can be done by setting the second argument to
|
25
|
+
a Symbol.
|
26
|
+
|
27
|
+
rc.evaluate(<<-HERE)
|
28
|
+
config :sample2, :profile=>'opt1' do
|
29
|
+
"block code"
|
30
|
+
end
|
31
|
+
HERE
|
32
|
+
|
33
|
+
sample = rc.configurations.last
|
34
|
+
sample.command #=> 'sample2'
|
35
|
+
sample.profile #=> 'opt1'
|
36
|
+
|
37
|
+
Or it can be done by using a `profile` block.
|
38
|
+
|
39
|
+
rc.evaluate(<<-HERE)
|
40
|
+
profile :opt1 do
|
41
|
+
config :sample2 do
|
42
|
+
"block code"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
HERE
|
46
|
+
|
47
|
+
sample = rc.configurations.last
|
48
|
+
sample.command #=> 'sample2'
|
49
|
+
sample.profile #=> 'opt1'
|
50
|
+
|
51
|
+
|
data/demo/03_import.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Importing
|
2
|
+
|
3
|
+
## Configuration Importing
|
4
|
+
|
5
|
+
Configurations can be imported from another project using the `:from` option.
|
6
|
+
|
7
|
+
rc = RC::Configuration.new
|
8
|
+
|
9
|
+
rc.config :qed, :profile=>'example', :from=>'test'
|
10
|
+
|
11
|
+
rc.to_a.size.assert == 1
|
12
|
+
|
13
|
+
The configuration can also be imported from a different profile.
|
14
|
+
|
15
|
+
rc.config :qed, :profile=>:coverage, :from=>['test', :profile=>'simplecov']
|
16
|
+
|
17
|
+
rc.to_a.size.assert == 2
|
18
|
+
|
19
|
+
Although it will very rarely be of use, it may also be imported from another
|
20
|
+
feature or command too.
|
21
|
+
|
22
|
+
rc.config :example, :from=>['test', :command=>'sample']
|
23
|
+
|
24
|
+
Imported configurations can also be augmented via a block.
|
25
|
+
|
26
|
+
rc = RC::Configuration.new
|
27
|
+
|
28
|
+
rc.config :qed, :from=>['test', :profile=>'simplecov'] do
|
29
|
+
# additional code here
|
30
|
+
end
|
31
|
+
|
32
|
+
rc.to_a.size.assert == 2
|
33
|
+
|
34
|
+
Technically this last form just creates two configurations for the same
|
35
|
+
tool and profile, but the ultimate effect is the same.
|
36
|
+
|
37
|
+
## Script Importing
|
38
|
+
|
39
|
+
Library files can be imported directly into configuration blocks via the
|
40
|
+
`#import` method.
|
41
|
+
|
42
|
+
rc.config :example do
|
43
|
+
import "fruitbasket/example.rb"
|
44
|
+
end
|
45
|
+
|
46
|
+
This looks up the file via the `finder` gem and then evals it in the context
|
47
|
+
of the config block.
|
48
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Interface
|
2
|
+
|
3
|
+
The main means of workin with RC's API are the RC class methods,
|
4
|
+
collectively called the Inteface.
|
5
|
+
|
6
|
+
Let's say we have a configuration file `.ruby` containing:
|
7
|
+
|
8
|
+
config :example do
|
9
|
+
"example config"
|
10
|
+
end
|
11
|
+
|
12
|
+
config :example, :profile=>:something do
|
13
|
+
"example config using profile"
|
14
|
+
end
|
15
|
+
|
16
|
+
To get the configuration of the current project --relative to the
|
17
|
+
current working directory, use the `configuration` method.
|
18
|
+
|
19
|
+
RC.configuration
|
20
|
+
|
21
|
+
The configuration properties of the current project can be
|
22
|
+
had via the `properties` method.
|
23
|
+
|
24
|
+
RC.properties
|
25
|
+
|
26
|
+
The profile names can be looked up for any given tool via the `profile_names`
|
27
|
+
method.
|
28
|
+
|
29
|
+
RC.profile_names(:example) #=> ['default', 'something']
|
30
|
+
|
31
|
+
The number of feature configurations in the current project can be
|
32
|
+
had via the `size` method.
|
33
|
+
|
34
|
+
RC.configuration.size #=> 1
|
35
|
+
|
36
|
+
A list of all configuration entries can be had by calling #to_a.
|
37
|
+
|
38
|
+
RC.configuration.to_a.size #=> 2
|
39
|
+
|
data/demo/applique/ae.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ae'
|
data/demo/cov.rb
ADDED
data/lib/c.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# This script is for use in the RUBYOPT, e.g. RUBYOPT="-rc".
|
2
|
+
#
|
3
|
+
# My apologies to the author of the `c` gem. If it helps,
|
4
|
+
# I think it would be better if the functionaility of the
|
5
|
+
# `c` gem were provided via other gems, e.g. the `github`
|
6
|
+
# gem.
|
7
|
+
|
8
|
+
require 'rc'
|
data/lib/rc.rb
ADDED
data/lib/rc/api.rb
ADDED
data/lib/rc/config.rb
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
module RC
|
2
|
+
|
3
|
+
# Config encapsulates a single configuration entry as defined in a project's
|
4
|
+
# ruby rc file. A config consists of a possible `command`, `feature`,
|
5
|
+
# `profile` and `onload` flag.
|
6
|
+
#
|
7
|
+
# If `command` or `feature` are nil, then the configuration applies to all
|
8
|
+
# commands and/or features.
|
9
|
+
#
|
10
|
+
# If profile is `nil` it automatically becomes `default`, which is the
|
11
|
+
# profile used when no profile is specified.
|
12
|
+
#
|
13
|
+
class Config
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initialize Config instance. Config instances are per-configuration,
|
17
|
+
# which means they are associated with one and only one config entry.
|
18
|
+
#
|
19
|
+
# @param [#to_s] target
|
20
|
+
# The command or feature name. (optional)
|
21
|
+
#
|
22
|
+
# @param [Hash] properties
|
23
|
+
# Any additional properties associated with the config entry.
|
24
|
+
#
|
25
|
+
def initialize(*args, &block)
|
26
|
+
properties = (Hash === args.last ? args.pop : {})
|
27
|
+
target = args.first
|
28
|
+
|
29
|
+
@property = {:command=>nil, :feature=>nil, :profile=>'default'}
|
30
|
+
|
31
|
+
if target
|
32
|
+
@property[:command] = target.to_s
|
33
|
+
@property[:feature] = target.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
@block = block
|
37
|
+
|
38
|
+
properties.each do |k, v|
|
39
|
+
property(k,v)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Get/set property.
|
45
|
+
#
|
46
|
+
def property(name, value=ArgumentError)
|
47
|
+
if value == ArgumentError
|
48
|
+
get(name)
|
49
|
+
else
|
50
|
+
set(name, value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# The feature being configured.
|
56
|
+
#
|
57
|
+
def feature
|
58
|
+
@property[:feature]
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# The name of command being configured.
|
63
|
+
#
|
64
|
+
def command
|
65
|
+
@property[:command]
|
66
|
+
end
|
67
|
+
|
68
|
+
# @todo Deprecate #tool alias?
|
69
|
+
alias :tool :command
|
70
|
+
|
71
|
+
#
|
72
|
+
# The name of the profile to which this configuration belongs.
|
73
|
+
#
|
74
|
+
def profile
|
75
|
+
@property[:profile]
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# The library from which this configuration derives.
|
80
|
+
#
|
81
|
+
def from
|
82
|
+
@property[:from]
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
#
|
87
|
+
#
|
88
|
+
def onload?
|
89
|
+
@property[:onload]
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Most configurations are scripted. In those cases the
|
94
|
+
# `@block` attributes holds the Proc instance, otherwise
|
95
|
+
# it is `nil`.
|
96
|
+
#
|
97
|
+
attr :block
|
98
|
+
|
99
|
+
#
|
100
|
+
# IDEA: Presets would be processed first and not require the underlying feature.
|
101
|
+
#
|
102
|
+
#def preset?
|
103
|
+
# @property[:preset]
|
104
|
+
#end
|
105
|
+
|
106
|
+
#
|
107
|
+
# The arity of the configuration procedure.
|
108
|
+
#
|
109
|
+
# @return [Fixnum] number of arguments
|
110
|
+
#
|
111
|
+
def arity
|
112
|
+
@block ? @block.arity : 0
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Require the feature.
|
117
|
+
#
|
118
|
+
def require_feature
|
119
|
+
begin
|
120
|
+
require feature
|
121
|
+
rescue LoadError
|
122
|
+
#warn "No such feature -- `#{feature}'"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Call the configuration procedure.
|
128
|
+
#
|
129
|
+
def call(*args)
|
130
|
+
block.call(*args) if block
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Returns underlying block.
|
135
|
+
#
|
136
|
+
def to_proc
|
137
|
+
block
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
## Convert block into a Hash.
|
142
|
+
##
|
143
|
+
## @return [Hash]
|
144
|
+
##
|
145
|
+
#def to_h
|
146
|
+
# HashBuilder.new(&self).to_h
|
147
|
+
#end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Copy the configuration with alterations.
|
151
|
+
#
|
152
|
+
# @param [Hash] alt
|
153
|
+
# Alternate values for configuration attributes.
|
154
|
+
#
|
155
|
+
# @return [Config] copied config
|
156
|
+
#
|
157
|
+
def copy(alt={})
|
158
|
+
tool = @property[:feature] || @property[:command]
|
159
|
+
copy = self.class.new(tool, @property.dup, &@block)
|
160
|
+
alt.each do |k,v|
|
161
|
+
copy.property(k, v)
|
162
|
+
end
|
163
|
+
copy
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Match config against tool and/or profile names.
|
168
|
+
#
|
169
|
+
# @return [Boolean]
|
170
|
+
#
|
171
|
+
def match?(*args)
|
172
|
+
props = Hash === args.last ? args.pop : {}
|
173
|
+
|
174
|
+
if target = args.shift
|
175
|
+
props[:command] = target.to_s
|
176
|
+
props[:feature] = target.to_s
|
177
|
+
end
|
178
|
+
|
179
|
+
if props[:profile]
|
180
|
+
props[:profile] = (props[:profile] || :default).to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
props.each do |k,v|
|
184
|
+
pv = property(k)
|
185
|
+
return false unless (pv.nil? || pv == v)
|
186
|
+
end
|
187
|
+
|
188
|
+
return true
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Does the given `feature` match the config's feature?
|
193
|
+
#
|
194
|
+
# @return [Boolean]
|
195
|
+
#
|
196
|
+
def feature?(feature=RC.current_feature)
|
197
|
+
return true if self.feature.nil?
|
198
|
+
self.feature == feature.to_s
|
199
|
+
end
|
200
|
+
|
201
|
+
#
|
202
|
+
# Does the given `command` match the config's command?
|
203
|
+
#
|
204
|
+
# @return [Boolean]
|
205
|
+
#
|
206
|
+
def command?(command=RC.current_command)
|
207
|
+
return true if self.command.nil?
|
208
|
+
self.command == command.to_s
|
209
|
+
end
|
210
|
+
alias_method :tool, :command?
|
211
|
+
|
212
|
+
#
|
213
|
+
# Does the given `profile` match the config's profile?
|
214
|
+
#
|
215
|
+
# @return [Boolean]
|
216
|
+
#
|
217
|
+
def profile?(profile=RC.current_profile)
|
218
|
+
self.profile == (profile || 'default').to_s
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
# @todo The feature argument might not be needed.
|
223
|
+
#
|
224
|
+
#def configure(feature)
|
225
|
+
# return false if self.feature != feature
|
226
|
+
#
|
227
|
+
# if setup = RC.setup(feature)
|
228
|
+
# setup.call(self)
|
229
|
+
# else
|
230
|
+
# block.call if command?
|
231
|
+
# end
|
232
|
+
#end
|
233
|
+
|
234
|
+
##
|
235
|
+
## Ruby 1.9 defines #inspect as #to_s, ugh.
|
236
|
+
##
|
237
|
+
#def inspect
|
238
|
+
# "#<#{self.class.name}:#{object_id} @tool=%s @profile=%s>" % [tool.inspect, profile.inspect]
|
239
|
+
#end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Does the configuration apply?
|
243
|
+
#
|
244
|
+
# @return [Boolean]
|
245
|
+
#
|
246
|
+
def apply_to_command?
|
247
|
+
return false if onload?
|
248
|
+
return false unless command? if command
|
249
|
+
return false unless profile? if profile
|
250
|
+
return true
|
251
|
+
end
|
252
|
+
alias_method :apply_to_tool?, :apply_to_command?
|
253
|
+
|
254
|
+
def apply_to_feature?
|
255
|
+
return false unless onload?
|
256
|
+
return false unless command? if command
|
257
|
+
return false unless profile? if profile
|
258
|
+
return true
|
259
|
+
end
|
260
|
+
|
261
|
+
private
|
262
|
+
|
263
|
+
#
|
264
|
+
# Get property.
|
265
|
+
#
|
266
|
+
def get(name)
|
267
|
+
@property[name.to_sym]
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# Set property.
|
272
|
+
#
|
273
|
+
def set(name, value)
|
274
|
+
case name.to_sym
|
275
|
+
when :command
|
276
|
+
self.command = value
|
277
|
+
when :tool # deprecate ?
|
278
|
+
self.command = value
|
279
|
+
when :feature
|
280
|
+
self.feature = value
|
281
|
+
when :profile
|
282
|
+
self.profile = value
|
283
|
+
else
|
284
|
+
@property[name.to_sym] = value
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
def command=(name)
|
290
|
+
@property[:command] = name ? name.to_s : nil
|
291
|
+
end
|
292
|
+
|
293
|
+
#
|
294
|
+
def feature=(path)
|
295
|
+
@property[:feature] = path ? path.to_s : nil
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
def profile=(name)
|
300
|
+
@property[:profile] = name ? name.to_s : 'default'
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|