rc 0.2.0 → 0.3.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/.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
|