rc 0.1.1 → 0.2.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.
- metadata +22 -73
- data/.ruby +0 -51
- data/.yardopts +0 -8
- data/Config.rb +0 -68
- data/HISTORY.md +0 -10
- data/LICENSE.txt +0 -27
- data/NOTES.md +0 -38
- data/README.md +0 -182
- data/lib/c.rb +0 -1
- data/lib/rc.rb +0 -10
- data/lib/rc/config.rb +0 -142
- data/lib/rc/configuration.rb +0 -192
- data/lib/rc/core_ext.rb +0 -49
- data/lib/rc/interface.rb +0 -163
- data/lib/rc/properties.rb +0 -44
- data/lib/rc/tool_configuration.rb +0 -54
- data/lib/rc/tweaks/rake.rb +0 -28
- data/spec/00_concept.md +0 -22
- data/spec/01_config.md +0 -14
- data/spec/02_configuration.md +0 -65
- data/spec/03_import.md +0 -48
- data/spec/06_interface.md +0 -36
- data/spec/applique/ae.rb +0 -1
- data/spec/applique/file.rb +0 -8
- data/spec/applique/fixture.rb +0 -10
- data/spec/applique/fixture/config.rb +0 -16
data/lib/c.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'rc'
|
data/lib/rc.rb
DELETED
data/lib/rc/config.rb
DELETED
@@ -1,142 +0,0 @@
|
|
1
|
-
module RC
|
2
|
-
|
3
|
-
# Config encapsulates a single configuration entry as defined
|
4
|
-
# in a project's configuration file.
|
5
|
-
#
|
6
|
-
class Config
|
7
|
-
|
8
|
-
#
|
9
|
-
# Initialize Config instance. Config instances are per-configuration,
|
10
|
-
# which means they are associated with one and only one config entry.
|
11
|
-
#
|
12
|
-
def initialize(tool, profile, &block)
|
13
|
-
self.tool = tool
|
14
|
-
self.profile = profile
|
15
|
-
self.block = block
|
16
|
-
end
|
17
|
-
|
18
|
-
#
|
19
|
-
# The name of tool being configured.
|
20
|
-
#
|
21
|
-
attr :tool
|
22
|
-
|
23
|
-
#
|
24
|
-
# Change the tool name. Note, this will rarely be used since,
|
25
|
-
# generally speaking, configurations tend to be very tool
|
26
|
-
# specific.
|
27
|
-
#
|
28
|
-
def tool=(name)
|
29
|
-
@tool = name.to_sym
|
30
|
-
end
|
31
|
-
|
32
|
-
#
|
33
|
-
# The name of the profile to which this configuration belongs.
|
34
|
-
#
|
35
|
-
attr :profile
|
36
|
-
|
37
|
-
#
|
38
|
-
# Change the profile name.
|
39
|
-
#
|
40
|
-
def profile=(name)
|
41
|
-
@profile = name.to_sym if name
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# Most configuration are scripted. In thos cases the
|
46
|
-
# `@block` attributes holds the Proc instance, otherwise
|
47
|
-
# it is `nil`.
|
48
|
-
#
|
49
|
-
attr :block
|
50
|
-
|
51
|
-
#
|
52
|
-
# Set the configuration procedure.
|
53
|
-
#
|
54
|
-
# @param [Proc] procedure
|
55
|
-
# The configuration procedure.
|
56
|
-
#
|
57
|
-
def block=(block)
|
58
|
-
@block = block.to_proc
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# The arity of the configuration procedure.
|
63
|
-
#
|
64
|
-
# @return [Fixnum] number of arguments
|
65
|
-
#
|
66
|
-
def arity
|
67
|
-
@block ? @block.arity : 0
|
68
|
-
end
|
69
|
-
|
70
|
-
#
|
71
|
-
# Call the configuration procedure.
|
72
|
-
#
|
73
|
-
def call(*args)
|
74
|
-
block.call(*args)
|
75
|
-
end
|
76
|
-
|
77
|
-
#
|
78
|
-
# Returns underlying block.
|
79
|
-
#
|
80
|
-
def to_proc
|
81
|
-
block
|
82
|
-
end
|
83
|
-
|
84
|
-
##
|
85
|
-
## Convert block into a Hash.
|
86
|
-
##
|
87
|
-
## @return [Hash]
|
88
|
-
##
|
89
|
-
#def to_h
|
90
|
-
# (@value || HashBuilder.new(&@block)).to_h
|
91
|
-
#end
|
92
|
-
|
93
|
-
#
|
94
|
-
# Copy the configuration with alterations.
|
95
|
-
#
|
96
|
-
# @param [Hash] alt
|
97
|
-
# Alternate values for configuration attributes.
|
98
|
-
#
|
99
|
-
# @return [Config] copied config
|
100
|
-
#
|
101
|
-
def copy(alt={})
|
102
|
-
copy = dup
|
103
|
-
alt.each do |k,v|
|
104
|
-
copy.__send__("#{k}=", v)
|
105
|
-
end
|
106
|
-
copy
|
107
|
-
end
|
108
|
-
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
def match?(tool, profile)
|
113
|
-
tool = tool.to_sym
|
114
|
-
profile = profile.to_sym if profile
|
115
|
-
|
116
|
-
self.tool == tool && self.profile == profile
|
117
|
-
end
|
118
|
-
|
119
|
-
#
|
120
|
-
# Does the given `tool` match the config's tool?
|
121
|
-
#
|
122
|
-
def tool?(tool)
|
123
|
-
self.tool == tool.to_sym
|
124
|
-
end
|
125
|
-
|
126
|
-
#
|
127
|
-
# Does the given `profile` match the config's profile?
|
128
|
-
#
|
129
|
-
def profile?(profile)
|
130
|
-
self.profile == profile.to_sym
|
131
|
-
end
|
132
|
-
|
133
|
-
##
|
134
|
-
## Ruby 1.9 defines #inspect as #to_s, ugh.
|
135
|
-
##
|
136
|
-
#def inspect
|
137
|
-
# "#<#{self.class.name}:#{object_id} @tool=%s @profile=%s>" % [tool.inspect, profile.inspect]
|
138
|
-
#end
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
data/lib/rc/configuration.rb
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
module RC
|
2
|
-
|
3
|
-
# Configuration
|
4
|
-
#
|
5
|
-
class Configuration < Module
|
6
|
-
|
7
|
-
#
|
8
|
-
# Configuration file pattern. The standard configuration file name is
|
9
|
-
# `Config.rb`, and that name should be used in most cases. However,
|
10
|
-
# `.config.rb` can also be use and will take precedence if found.
|
11
|
-
# Conversely, `config.rb` (lowercase form) can also be used but has
|
12
|
-
# the least precedence.
|
13
|
-
#
|
14
|
-
# Config files looked for in the order or precedence:
|
15
|
-
#
|
16
|
-
# * `.config.rb`
|
17
|
-
# * `Config.rb`
|
18
|
-
# * `config.rb`
|
19
|
-
#
|
20
|
-
CONFIG_FILE = '{.c,C,c}onfig{.rb,}'
|
21
|
-
|
22
|
-
#
|
23
|
-
# When looking up config file, it one of these is found
|
24
|
-
# then there is no point to looking further.
|
25
|
-
#
|
26
|
-
ROOT_INDICATORS = %w{.git .hg _darcs} #.ruby
|
27
|
-
|
28
|
-
#
|
29
|
-
# Load configuration file from local project or other gem.
|
30
|
-
#
|
31
|
-
# @param options [Hash] Load options.
|
32
|
-
#
|
33
|
-
# @option options [String] :from
|
34
|
-
# Name of gem or library.
|
35
|
-
#
|
36
|
-
def self.load(options={})
|
37
|
-
if from = options[:from]
|
38
|
-
file = Find.path(CONFIG_FILE, :from=>from).first
|
39
|
-
else
|
40
|
-
file = lookup(CONFIG_FILE)
|
41
|
-
end
|
42
|
-
new(file)
|
43
|
-
end
|
44
|
-
|
45
|
-
#
|
46
|
-
# Initialize new Configuration object.
|
47
|
-
#
|
48
|
-
# @param [String] file
|
49
|
-
# Configuration file (optional).
|
50
|
-
#
|
51
|
-
def initialize(file=nil)
|
52
|
-
@file = file
|
53
|
-
|
54
|
-
@_list = []
|
55
|
-
@_state = {}
|
56
|
-
|
57
|
-
# TODO: does this rescue make sense here?
|
58
|
-
begin
|
59
|
-
import_relative(@file) if @file
|
60
|
-
rescue => e
|
61
|
-
raise e if $DEBUG
|
62
|
-
warn e.message
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# Profile block.
|
68
|
-
#
|
69
|
-
# @param [String,Symbol] name
|
70
|
-
# A profile name.
|
71
|
-
#
|
72
|
-
def profile(name, &block)
|
73
|
-
raise SyntaxError, "nested profile sections" if @_state[:profile]
|
74
|
-
original_state = @_state.dup
|
75
|
-
@_state[:profile] = name.to_s
|
76
|
-
instance_eval(&block)
|
77
|
-
@_state = original_state
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# Configure a tool.
|
82
|
-
#
|
83
|
-
# @param [Symbol] tool
|
84
|
-
# The name of the tool to configure.
|
85
|
-
#
|
86
|
-
# @param [Hash] opts
|
87
|
-
# Configuration options.
|
88
|
-
#
|
89
|
-
# @options opts [String] :from
|
90
|
-
# Library from which to extract configuration.
|
91
|
-
#
|
92
|
-
# @example
|
93
|
-
# profile :coverage do
|
94
|
-
# config :qed, :from=>'qed'
|
95
|
-
# end
|
96
|
-
#
|
97
|
-
# @todo Clean this code up.
|
98
|
-
#
|
99
|
-
def config(tool, *args, &block)
|
100
|
-
options = (Hash===args.last ? args.pop : {})
|
101
|
-
|
102
|
-
# @todo Might we have an option to lockdown tool
|
103
|
-
# So that we do without ToolConfiguration?
|
104
|
-
|
105
|
-
case args.first
|
106
|
-
when Symbol
|
107
|
-
profile = args.shift
|
108
|
-
when String
|
109
|
-
profile = args.shift unless args.first.index("\n")
|
110
|
-
end
|
111
|
-
|
112
|
-
data = args.shift
|
113
|
-
raise ArgumentError, "must use data or block, not both" if data && block
|
114
|
-
if data
|
115
|
-
data = data.tabto(0)
|
116
|
-
block = Proc.new do
|
117
|
-
YAML.load(data)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
from = options[:from]
|
122
|
-
|
123
|
-
raise ArgumentError, "too many arguments" if args.first
|
124
|
-
raise SyntaxError, "nested profile sections" if profile && @_state[:profile]
|
125
|
-
#raise ArgumentError, "use block or :from setting" if options[:from] && block
|
126
|
-
|
127
|
-
profile = @_state[:profile] unless profile
|
128
|
-
|
129
|
-
if from
|
130
|
-
from_config = RC.configuration(from)
|
131
|
-
from_tool = options[:tool] || tool
|
132
|
-
from_profile = options[:profile] || profile
|
133
|
-
from_config.each do |c|
|
134
|
-
if c.match?(from_tool, from_profile)
|
135
|
-
@_list << Config.new(tool, profile, &c)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
return unless block
|
140
|
-
end
|
141
|
-
|
142
|
-
@_list << Config.new(tool, profile, &block)
|
143
|
-
end
|
144
|
-
|
145
|
-
#
|
146
|
-
# @return [Hash] Defined configurations.
|
147
|
-
#
|
148
|
-
def configurations
|
149
|
-
@_list
|
150
|
-
end
|
151
|
-
|
152
|
-
#
|
153
|
-
# @return [ToolConfiguration] Subset of Configuration.
|
154
|
-
#
|
155
|
-
def [](tool)
|
156
|
-
ToolConfiguration.new(tool, self)
|
157
|
-
end
|
158
|
-
|
159
|
-
# Configuration is Enumerable.
|
160
|
-
include Enumerable
|
161
|
-
|
162
|
-
#
|
163
|
-
def each(&block)
|
164
|
-
@_list.each(&block)
|
165
|
-
end
|
166
|
-
|
167
|
-
#
|
168
|
-
def size
|
169
|
-
@_list.size
|
170
|
-
end
|
171
|
-
|
172
|
-
private
|
173
|
-
|
174
|
-
#
|
175
|
-
# Search upward from working directory.
|
176
|
-
#
|
177
|
-
def self.lookup(glob, flags=0)
|
178
|
-
pwd = File.expand_path(Dir.pwd)
|
179
|
-
home = File.expand_path('~')
|
180
|
-
while pwd != '/' && pwd != home
|
181
|
-
if file = Dir.glob(File.join(pwd, glob), flags).first
|
182
|
-
return file
|
183
|
-
end
|
184
|
-
break if ROOT_INDICATORS.any?{ |r| File.exist?(File.join(pwd, r)) }
|
185
|
-
pwd = File.dirname(pwd)
|
186
|
-
end
|
187
|
-
return nil
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
191
|
-
|
192
|
-
end
|
data/lib/rc/core_ext.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
module Kernel
|
2
|
-
#
|
3
|
-
# Evaluate script directly into current scope.
|
4
|
-
#
|
5
|
-
def import(feature)
|
6
|
-
file = Find.load_path(feature).first
|
7
|
-
raise LoadError, "no such file -- #{feature}" unless file
|
8
|
-
instance_eval(::File.read(file), file) if file
|
9
|
-
end
|
10
|
-
|
11
|
-
#
|
12
|
-
# Evaluate script directly into current scope.
|
13
|
-
#
|
14
|
-
def import_relative(file)
|
15
|
-
raise LoadError, "no such file -- #{file}" unless File.file?(file)
|
16
|
-
instance_eval(::File.read(file), file) if file
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class Hash
|
21
|
-
def to_h
|
22
|
-
dup #rehash
|
23
|
-
end unless method_defined?(:to_h)
|
24
|
-
end
|
25
|
-
|
26
|
-
class String
|
27
|
-
def tabto(n)
|
28
|
-
if self =~ /^( *)\S/
|
29
|
-
indent(n - $1.length)
|
30
|
-
else
|
31
|
-
self
|
32
|
-
end
|
33
|
-
end unless method_defined?(:tabto)
|
34
|
-
|
35
|
-
def indent(n, c=' ')
|
36
|
-
if n >= 0
|
37
|
-
gsub(/^/, c * n)
|
38
|
-
else
|
39
|
-
gsub(/^#{Regexp.escape(c)}{0,#{-n}}/, "")
|
40
|
-
end
|
41
|
-
end unless method_defined?(:indent)
|
42
|
-
end
|
43
|
-
|
44
|
-
#class Symbol
|
45
|
-
# def /(other)
|
46
|
-
# "#{self}/#{other}".to_sym
|
47
|
-
# end
|
48
|
-
#end
|
49
|
-
|
data/lib/rc/interface.rb
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
module RC
|
2
|
-
# External requirements.
|
3
|
-
require 'yaml'
|
4
|
-
require 'finder'
|
5
|
-
|
6
|
-
# Internal requirements.
|
7
|
-
require 'rc/core_ext'
|
8
|
-
require 'rc/config'
|
9
|
-
require 'rc/configuration'
|
10
|
-
require 'rc/tool_configuration'
|
11
|
-
require 'rc/properties'
|
12
|
-
|
13
|
-
#
|
14
|
-
# Configuration file pattern. The standard configuration file name is
|
15
|
-
# `Config.rb`, and that name should be used in most cases. However,
|
16
|
-
# `.config.rb` can also be use and will take precedence if found.
|
17
|
-
# Conversely, `config.rb` (lowercase form) can also be used but has
|
18
|
-
# the least precedence.
|
19
|
-
#
|
20
|
-
# Config files looked for in the order or precedence:
|
21
|
-
#
|
22
|
-
# * `.config.rb`
|
23
|
-
# * `Config.rb`
|
24
|
-
# * `config.rb`
|
25
|
-
#
|
26
|
-
FILE_PATTERN = '{.c,C,c}onfig{.rb,}'
|
27
|
-
|
28
|
-
#
|
29
|
-
def self.cache
|
30
|
-
@cache ||= {}
|
31
|
-
end
|
32
|
-
|
33
|
-
#
|
34
|
-
def self.clear!
|
35
|
-
@cache = {}
|
36
|
-
end
|
37
|
-
|
38
|
-
#
|
39
|
-
def self.configuration(gem=nil)
|
40
|
-
key = gem ? gem.to_s : nil #Dir.pwd
|
41
|
-
cache[key] ||= Configuration.load(:from=>gem)
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# @return [Array] List of profiles for given `tool`.
|
46
|
-
#
|
47
|
-
def self.profiles(tool, options={})
|
48
|
-
tool = tool.to_s
|
49
|
-
gem = options[:from]
|
50
|
-
configuration(gem).map{ |c| c.tool.to_s }
|
51
|
-
end
|
52
|
-
|
53
|
-
#
|
54
|
-
# Get current tool.
|
55
|
-
#
|
56
|
-
def self.current_tool
|
57
|
-
File.basename(ENV['tool'] || $0)
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
# Set current tool.
|
62
|
-
#
|
63
|
-
def self.current_tool=(tool)
|
64
|
-
ENV['tool'] = tool.to_s
|
65
|
-
end
|
66
|
-
|
67
|
-
#
|
68
|
-
# Get current profile.
|
69
|
-
#
|
70
|
-
def self.current_profile
|
71
|
-
ENV['profile']
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# Set current profile.
|
76
|
-
#
|
77
|
-
def self.current_profile=(profile)
|
78
|
-
if profile
|
79
|
-
ENV['profile'] = profile.to_s
|
80
|
-
else
|
81
|
-
ENV['profile'] = nil
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
#
|
86
|
-
# Project properties.
|
87
|
-
#
|
88
|
-
def self.properties
|
89
|
-
$properties ||= Properties.new
|
90
|
-
end
|
91
|
-
|
92
|
-
#
|
93
|
-
# Get/set configuration processor. Tools can use this
|
94
|
-
# to gain control over the configuration procedure.
|
95
|
-
#
|
96
|
-
# The block should take a single argument of the current
|
97
|
-
# Configuration.
|
98
|
-
#
|
99
|
-
# This might be used to save the configuration for
|
100
|
-
# a later execution, or to evaluate the procedures
|
101
|
-
# in a special scope, or both.
|
102
|
-
#
|
103
|
-
# Keep in mind that if configurations are evaluated in
|
104
|
-
# a different scope, they may not be able to utilize
|
105
|
-
# any shared methods defined in the config file.
|
106
|
-
#
|
107
|
-
# @example
|
108
|
-
# RC.processor('qed') do |config|
|
109
|
-
# if i = ARGV.index('--profile') || ARGV.index('-p')
|
110
|
-
# ENV['profile'] = ARGV[i+1]
|
111
|
-
# end
|
112
|
-
# RC.configure
|
113
|
-
# end
|
114
|
-
#
|
115
|
-
def self.processor(tool, &block)
|
116
|
-
@processors ||= {}
|
117
|
-
@processors[tool.to_s] = block if block
|
118
|
-
@processors[tool.to_s]
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
# Setup configuration.
|
123
|
-
#
|
124
|
-
def self.configure(options={})
|
125
|
-
tool = options[:tool] || current_tool
|
126
|
-
profile = options[:profile] || current_profile
|
127
|
-
|
128
|
-
configuration.each do |c|
|
129
|
-
c.call if c.match?(tool, profile)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
#
|
134
|
-
# Start RC.
|
135
|
-
#
|
136
|
-
def self.bootstrap
|
137
|
-
properties # prime global properties
|
138
|
-
|
139
|
-
tweak = File.join(File.dirname(__FILE__), 'tweaks', current_tool + '.rb')
|
140
|
-
if File.exist?(tweak)
|
141
|
-
require tweak
|
142
|
-
else
|
143
|
-
begin
|
144
|
-
require current_tool
|
145
|
-
rescue LoadError
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
if proc = processor(current_tool)
|
150
|
-
tool_config = ToolConfiguration.new(current_tool, configuration)
|
151
|
-
proc.call(tool_config)
|
152
|
-
else
|
153
|
-
configure
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# @todo: I'm sure this, #bootstrap and #processor can be simplifed.
|
158
|
-
def self.run(tool, &block)
|
159
|
-
processor(tool, &block)
|
160
|
-
require 'rc'
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|