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.
@@ -0,0 +1,110 @@
1
+ module RC
2
+
3
+ # To be quite honest I have forgotten the purpose of this class
4
+ # and it is no longer being used, so it should be deleted. But
5
+ # I am holding off a bit, in case I recall why it was here, in
6
+ # order to be sure.
7
+ #
8
+ class ConfigFilter
9
+
10
+ include Enumerable
11
+
12
+ #
13
+ # Initialize new ConfigFilter.
14
+ #
15
+ # @param [Array<Config>] configuration
16
+ # List if Config instances.
17
+ #
18
+ def initialize(configuration, criteria={})
19
+ @configuration = configuration
20
+ @criteria = criteria
21
+
22
+ @list = []
23
+
24
+ configuration.each do |c|
25
+ @list << c if c.match?(criteria)
26
+ end
27
+ end
28
+
29
+ #
30
+ #
31
+ #
32
+ def tool
33
+ @criteria[:tool]
34
+ end
35
+
36
+ #
37
+ #
38
+ #
39
+ def profile
40
+ @criteria[:profile]
41
+ end
42
+
43
+ #
44
+ # Returns list of profiles.
45
+ #
46
+ def profiles
47
+ @list.map{ |c| c.profile }
48
+ end
49
+
50
+ #
51
+ #
52
+ #
53
+ def [](subset)
54
+ return method_missing(:[]) if profile
55
+ if tool
56
+ criteria = @criteria.dup
57
+ criteria[:profile] = subset
58
+ else
59
+ criteria = @criteria.dup
60
+ criteria[:tool] = subset
61
+ end
62
+ self.class.new(@configuration, criteria)
63
+ end
64
+
65
+ #
66
+ #
67
+ #
68
+ def each(&block)
69
+ @list.each do
70
+ block
71
+ end
72
+ end
73
+
74
+ #
75
+ #
76
+ #
77
+ def size
78
+ @list.size
79
+ end
80
+
81
+ #
82
+ # Call each config.
83
+ #
84
+ def call(*args)
85
+ @list.each do |c|
86
+ if c.profile?(RC.current_profile)
87
+ c.call(*args)
88
+ end
89
+ end
90
+ end
91
+
92
+ #
93
+ # Convert to Proc.
94
+ #
95
+ def to_proc(exec=false)
96
+ list = @list
97
+ if exec
98
+ Proc.new do |*args|
99
+ list.each{ |c| instance_exec(*args, &c) }
100
+ end
101
+ else
102
+ Proc.new do |*args|
103
+ list.each{ |c| c.call(*args) }
104
+ end
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ end
@@ -0,0 +1,362 @@
1
+ module RC
2
+
3
+ # The Configuration class encapsulates a project/library's tool
4
+ # configuration.
5
+ #
6
+ class Configuration < Module
7
+
8
+ #
9
+ # Configuration is Enumerable.
10
+ #
11
+ include Enumerable
12
+
13
+ #
14
+ # Runtime configuration file glob pattern.
15
+ #
16
+ CONFIG_FILE = '.ruby{rc,}'
17
+
18
+ class << self
19
+ #
20
+ # Load configuration file from local project or other gem.
21
+ #
22
+ # @param options [Hash] Load options.
23
+ #
24
+ # @option options [String] :from
25
+ # Name of gem or library.
26
+ #
27
+ def load(options={})
28
+ if options[:from]
29
+ load_from(options[:from])
30
+ else
31
+ load_local()
32
+ end
33
+ end
34
+
35
+ #
36
+ # Load configuration from another gem.
37
+ #
38
+ def load_from(gem)
39
+ files = Find.path(CONFIG_FILE, :from=>gem)
40
+ file = files.find{ |f| File.file?(f) }
41
+ new(*file)
42
+
43
+ #if file
44
+ # paths = [file]
45
+ #else
46
+ # #paths = Find.path(CONFIG_DIR + '/**/*', :from=>gem)
47
+ #end
48
+ #files = paths.select{ |path| File.file?(path) }
49
+ #new(*files)
50
+ end
51
+
52
+ #
53
+ # Load configuration for current project.
54
+ #
55
+ def load_local
56
+ files = lookup(CONFIG_FILE)
57
+ file = files.find{ |f| File.file?(f) }
58
+ new(*file)
59
+
60
+ #if file
61
+ # paths = [file]
62
+ #else
63
+ # dir = lookup(CONFIG_DIR).find{ |f| File.directory?(f) }
64
+ # paths = dir ? Dir.glob(File.join(dir, '**/*')) : []
65
+ #end
66
+ #files = paths.select{ |path| File.file?(path) }
67
+ end
68
+
69
+ private
70
+
71
+ #
72
+ # Search upward from working directory.
73
+ #
74
+ def lookup(glob, flags=0)
75
+ pwd = File.expand_path(Dir.pwd)
76
+ home = File.expand_path('~')
77
+ while pwd != '/' && pwd != home
78
+ paths = Dir.glob(File.join(pwd, glob), flags)
79
+ return paths unless paths.empty?
80
+ break if ROOT_INDICATORS.any?{ |r| File.exist?(File.join(pwd, r)) }
81
+ pwd = File.dirname(pwd)
82
+ end
83
+ return []
84
+ end
85
+
86
+ end
87
+
88
+ #
89
+ # Initialize new Configuration object.
90
+ #
91
+ # @param [Array<String>] files
92
+ # Configuration files (optional).
93
+ #
94
+ def initialize(*files)
95
+ @files = files
96
+
97
+ @_config = Hash.new{ |h,k| h[k]=[] }
98
+ #@_onload = Hash.new{ |h,k| h[k]=[] }
99
+
100
+ load_files(*files)
101
+ end
102
+
103
+ #
104
+ # Import other runtime configuration files.
105
+ #
106
+ # @param [String] glob
107
+ # File pattern of configutation files to load.
108
+ #
109
+ # @param opts [Hash] Load options.
110
+ #
111
+ # @option opts [String] :from
112
+ # Name of gem or library.
113
+ #
114
+ # @option opts [Boolean] :first
115
+ # Only match a single file.
116
+ #
117
+ def import(glob, opts={})
118
+ paths = []
119
+
120
+ glob = glob + '**/*' if glob.end_with?('/')
121
+
122
+ if from = opts[:from]
123
+ paths = Find.path(glob, :from=>from)
124
+ else
125
+ if glob.start_with?('/')
126
+ if root = lookup_root
127
+ glob = File.join(root, glob)
128
+ else
129
+ raise "no project root for #{glob}" unless root
130
+ end
131
+ end
132
+ paths = Dir.glob(glob)
133
+ end
134
+
135
+ paths = paths.select{ |path| File.file?(path) }
136
+ paths = paths[0..0] if opts[:first]
137
+
138
+ load_files(*paths)
139
+
140
+ paths.empty? ? nil : paths
141
+ end
142
+
143
+ #
144
+ # Load configuration files.
145
+ #
146
+ # TODO: begin/rescue around instance_eval?
147
+ #
148
+ # TODO: Does each file need it's own DSL instance?
149
+ #
150
+ def load_files(*files)
151
+ dsl = DSL.new(self)
152
+ files.each do |file|
153
+ next unless File.file?(file) # TODO: warn ?
154
+ #begin
155
+ dsl.instance_eval(File.read(file), file)
156
+ #rescue => e
157
+ # raise e if $DEBUG
158
+ # warn e.message
159
+ #end
160
+ end
161
+ end
162
+
163
+ alias :load_file :load_files
164
+
165
+ #
166
+ # Evaluate configuration code.
167
+ #
168
+ # @yieldparm cfg
169
+ # Configuration code block.
170
+ #
171
+ def evaluate(*args, &cfg)
172
+ dsl = DSL.new(self)
173
+ dsl.instance_eval(*args, &cfg)
174
+ end
175
+
176
+ #
177
+ # Configure a commandline tool or feature.
178
+ #
179
+ # @param [Symbol] target
180
+ # The name of the command or feature to configure.
181
+ #
182
+ # @param [Hash] opts
183
+ # Configuration options.
184
+ #
185
+ # @options opts [String] :command
186
+ # Name of command, or false if not a command configuration.
187
+ #
188
+ # @options opts [String] :feature
189
+ # Alternate require if differnt than command name.
190
+ #
191
+ # @options opts [String] :from
192
+ # Library from which to import configuration.
193
+ #
194
+ # @example
195
+ # profile :coverage do
196
+ # config :qed, :from=>'qed'
197
+ # end
198
+ #
199
+ def config(target, options={}, &block)
200
+ #options[:profile] = (options[:profile] || 'default').to_s
201
+ #options[:command] = command.to_s unless options.key?(:command)
202
+ #options[:feature] = command.to_s unless options.key?(:feature)
203
+ #command = options[:command].to_s
204
+
205
+ # IDEA: other import options such as local file?
206
+
207
+ configs_from(options).each do |c|
208
+ @_config[target.to_s] << c.copy(options)
209
+ end
210
+
211
+ return unless block
212
+
213
+ @_config[target.to_s] << Config.new(target, options, &block)
214
+ end
215
+
216
+ =begin
217
+ #
218
+ #
219
+ #
220
+ def onload(feature, options={}, &block)
221
+ #options[:profile] = (options[:profile] || 'default').to_s
222
+
223
+ #options[:feature] = feature.to_s unless options.key?(:feature)
224
+ #options[:command] = feature.to_s unless options.key?(:command)
225
+
226
+ feature = options[:feature].to_s
227
+
228
+ # IDEA: what about local file import?
229
+ configs_from(options).each do |c|
230
+ @_onload[feature] << c.copy(options)
231
+ end
232
+
233
+ return unless block
234
+
235
+ @_onload[feature] << Config.new(feature, options, &block)
236
+ end
237
+ =end
238
+
239
+ #
240
+ #
241
+ #
242
+ def [](feature)
243
+ @_config[feature.to_s]
244
+ end
245
+
246
+ #
247
+ # Iterate over each feature config.
248
+ #
249
+ # @example
250
+ # confgiuration.each do |feature, configs|
251
+ # configs.each do |config|
252
+ # ...
253
+ # end
254
+ # end
255
+ #
256
+ def each(&block)
257
+ @_config.each(&block)
258
+ end
259
+
260
+ #
261
+ # The number of feature configs.
262
+ #
263
+ def size
264
+ @_config.size
265
+ end
266
+
267
+ #
268
+ # Get a list of the defined configurations.
269
+ #
270
+ # @return [Array] List of all defined configurations.
271
+ #
272
+ def to_a
273
+ list = []
274
+ @_config.each do |feature, configs|
275
+ list.concat(configs)
276
+ end
277
+ list
278
+ end
279
+
280
+ #
281
+ # @deprecated
282
+ #
283
+ alias :configurations :to_a
284
+
285
+ #
286
+ # Get a list of defined profiles names for the given +command+.
287
+ # use the current command if no +command+ is given.
288
+ #
289
+ def profile_names(command=nil)
290
+ command = command || RC.current_command
291
+
292
+ list = []
293
+ @_config.each do |feature, configs|
294
+ configs.each do |c|
295
+ if c.command?(command)
296
+ list << c.profile
297
+ end
298
+ end
299
+ end
300
+ list.uniq
301
+ end
302
+
303
+ #def inspect
304
+ # "#<RC::Configuration:#{object_id} @file=#{@file}>"
305
+ #end
306
+
307
+ private
308
+
309
+ # TODO: other import options such as local file?
310
+
311
+ #
312
+ #
313
+ #
314
+ def configs_from(options)
315
+ from = options[:from]
316
+ list = []
317
+
318
+ return list unless from
319
+
320
+ if Array === from
321
+ from_name, from_opts = *from
322
+ else
323
+ from_name, from_opts = from, {}
324
+ end
325
+
326
+ from_config = RC.configuration(from_name)
327
+
328
+ from_opts[:feature] = options[:feature] unless from_opts.key?(:feature) if options[:feature]
329
+ from_opts[:command] = options[:command] unless from_opts.key?(:command) if options[:command]
330
+ from_opts[:profile] = options[:profile] unless from_opts.key?(:profile) if options[:profile]
331
+
332
+ from_opts[:feature] = from_opts[:feature].to_s if from_opts[:feature]
333
+ from_opts[:command] = from_opts[:command].to_s if from_opts[:command]
334
+ from_opts[:profile] = from_opts[:profile].to_s if from_opts[:profile]
335
+
336
+ from_config.each do |ftr, confs|
337
+ confs.each_with_index do |c, i|
338
+ if c.match?(from_opts)
339
+ list << c.copy(options)
340
+ end
341
+ end
342
+ end
343
+
344
+ list
345
+ end
346
+
347
+ #
348
+ # Search upward from project root directory.
349
+ #
350
+ def lookup_root
351
+ pwd = File.expand_path(Dir.pwd)
352
+ home = File.expand_path('~')
353
+ while pwd != '/' && pwd != home
354
+ return pwd if ROOT_INDICATORS.any?{ |r| File.exist?(File.join(pwd, r)) }
355
+ pwd = File.dirname(pwd)
356
+ end
357
+ return nil
358
+ end
359
+
360
+ end
361
+
362
+ end