bahuvrihi-tap 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/tap +7 -45
- data/cmd/manifest.rb +94 -0
- data/cmd/run.rb +1 -1
- data/lib/tap.rb +0 -5
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/env.rb +195 -187
- data/lib/tap/exe.rb +63 -0
- data/lib/tap/file_task.rb +33 -8
- data/lib/tap/generator/base.rb +7 -28
- data/lib/tap/generator/generators/root/root_generator.rb +21 -15
- data/lib/tap/generator/generators/root/templates/Rakefile +1 -1
- data/lib/tap/generator/generators/root/templates/gemspec +2 -1
- data/lib/tap/patches/rake/testtask.rb +2 -0
- data/lib/tap/support/class_configuration.rb +5 -6
- data/lib/tap/support/configurable_class.rb +15 -18
- data/lib/tap/support/configuration.rb +8 -6
- data/lib/tap/support/declarations.rb +2 -2
- data/lib/tap/support/framework.rb +14 -2
- data/lib/tap/support/framework_class.rb +13 -32
- data/lib/tap/support/gems.rb +63 -0
- data/lib/tap/support/gems/rake.rb +90 -0
- data/lib/tap/support/instance_configuration.rb +8 -8
- data/lib/tap/support/lazy_attributes.rb +30 -0
- data/lib/tap/support/lazydoc.rb +65 -33
- data/lib/tap/support/manifest.rb +117 -54
- data/lib/tap/tasks/rake.rb +1 -0
- data/lib/tap/test/script_methods.rb +34 -71
- data/lib/tap/test/script_methods/script_test.rb +98 -0
- data/lib/tap/test/tap_methods.rb +1 -5
- data/lib/tap/workflow.rb +47 -34
- metadata +8 -2
data/bin/tap
CHANGED
@@ -10,37 +10,14 @@
|
|
10
10
|
# tap command --help # prints help for 'command'
|
11
11
|
#
|
12
12
|
|
13
|
-
|
14
|
-
require
|
13
|
+
require "#{File.dirname(__FILE__)}/../lib/tap.rb"
|
14
|
+
require 'tap/exe'
|
15
15
|
|
16
16
|
# setup the environment
|
17
17
|
begin
|
18
18
|
|
19
19
|
$DEBUG = true if ARGV.delete('-d-')
|
20
|
-
|
21
|
-
after = nil
|
22
|
-
aliases = nil
|
23
|
-
|
24
|
-
app = Tap::App.instance
|
25
|
-
env = Tap::Env.instantiate(app, Tap::Env.load_config(Tap::Env::GLOBAL_CONFIG_FILE), app.logger) do |unhandled_configs|
|
26
|
-
before = unhandled_configs.delete(:before)
|
27
|
-
after = unhandled_configs.delete(:after)
|
28
|
-
|
29
|
-
aliases = unhandled_configs.delete(:alias)
|
30
|
-
Tap::Support::Validation.validate(aliases, [Hash]) if aliases
|
31
|
-
|
32
|
-
unless unhandled_configs.empty?
|
33
|
-
local.log(:warn, "ignoring non-env configs: #{unhandled_configs.keys.join(',')}", Logger::DEBUG)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# add all gems if no gems are specified (Note this is VERY SLOW ~ 1/3 the overhead for tap)
|
38
|
-
if !File.exists?(Tap::Env::DEFAULT_CONFIG_FILE)
|
39
|
-
env.gems = Tap::Env.known_gems(true)
|
40
|
-
end
|
41
|
-
|
42
|
-
tap = Tap::Env.instance_for(tap_root_dir)
|
43
|
-
env.push(tap)
|
20
|
+
env = Tap::Exe.instantiate
|
44
21
|
|
45
22
|
rescue(Tap::Env::ConfigError)
|
46
23
|
# catch errors and exit gracefully
|
@@ -55,7 +32,7 @@ end
|
|
55
32
|
|
56
33
|
at_exit do
|
57
34
|
begin
|
58
|
-
eval(after) if after != nil
|
35
|
+
eval(env.after) if env.after != nil
|
59
36
|
rescue(Exception)
|
60
37
|
puts "Error in after script."
|
61
38
|
env.handle_error($!)
|
@@ -68,7 +45,7 @@ end
|
|
68
45
|
#
|
69
46
|
|
70
47
|
begin
|
71
|
-
eval(before) if before != nil
|
48
|
+
eval(env.before) if env.before != nil
|
72
49
|
rescue(Exception)
|
73
50
|
puts "Error in before script."
|
74
51
|
env.handle_error($!)
|
@@ -81,15 +58,7 @@ end
|
|
81
58
|
|
82
59
|
begin
|
83
60
|
env.activate
|
84
|
-
|
85
|
-
command = ARGV.shift
|
86
|
-
if aliases && aliases.has_key?(command)
|
87
|
-
aliases[command].reverse_each {|arg| ARGV.unshift(arg)}
|
88
|
-
command = ARGV.shift
|
89
|
-
end
|
90
|
-
|
91
|
-
case command
|
92
|
-
when nil, '--help'
|
61
|
+
env.run do
|
93
62
|
# give some help
|
94
63
|
require 'tap/support/command_line'
|
95
64
|
|
@@ -98,14 +67,7 @@ begin
|
|
98
67
|
puts "available commands:"
|
99
68
|
puts env.summarize(:commands)
|
100
69
|
puts
|
101
|
-
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
102
|
-
else
|
103
|
-
if path = env.search(:commands, command)
|
104
|
-
load path # run the command, if it exists
|
105
|
-
else
|
106
|
-
puts "Unknown command: '#{command}'"
|
107
|
-
puts "Type 'tap help' for usage information."
|
108
|
-
end
|
70
|
+
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
109
71
|
end
|
110
72
|
rescue
|
111
73
|
env.handle_error($!)
|
data/cmd/manifest.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# tap manifest
|
2
|
+
#
|
3
|
+
# Prints information about each env.
|
4
|
+
#
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
|
9
|
+
opts.separator ""
|
10
|
+
opts.separator "options:"
|
11
|
+
|
12
|
+
opts.on("-h", "--help", "Show this message") do
|
13
|
+
opts.banner = cmdline.usage(__FILE__)
|
14
|
+
puts opts
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on("-e", "--envs_only", "Only list environments") do
|
19
|
+
options[:envs_only] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-r", "--require FILEPATH", "Require the specified file") do |value|
|
23
|
+
require value
|
24
|
+
end
|
25
|
+
|
26
|
+
end.parse!(ARGV)
|
27
|
+
|
28
|
+
# Simply a method to collect and format paths for
|
29
|
+
# the specified manifest.
|
30
|
+
def collect_map(env, manifest)
|
31
|
+
width = 10
|
32
|
+
map = manifest.minimize.collect do |(key, path)|
|
33
|
+
path = case path
|
34
|
+
when Tap::Support::Constant then path.require_path
|
35
|
+
else path
|
36
|
+
end
|
37
|
+
|
38
|
+
width = key.length if width < key.length
|
39
|
+
[key, env.root.relative_filepath(:root, path) || path]
|
40
|
+
end.collect do |args|
|
41
|
+
"%-#{width}s (%s)" % args
|
42
|
+
end
|
43
|
+
|
44
|
+
map.unshift("") unless map.empty?
|
45
|
+
map
|
46
|
+
end
|
47
|
+
|
48
|
+
# Collect remaining args as
|
49
|
+
env = Tap::Env.instance
|
50
|
+
envs_manifest = if ARGV.empty?
|
51
|
+
env.manifest(:envs, true).minimize
|
52
|
+
else
|
53
|
+
ARGV.collect do |name|
|
54
|
+
entry = env.find(:envs, name, false)
|
55
|
+
raise "could not find an env matching: #{name}" if entry == nil
|
56
|
+
entry
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
width = 10
|
61
|
+
envs_manifest.each {|(env_name, e)| width = env_name.length if width < env_name.length}
|
62
|
+
width += 2
|
63
|
+
|
64
|
+
env.each do |current|
|
65
|
+
env_name, current = envs_manifest.find {|(env_name, e)| e == current }
|
66
|
+
next if env_name == nil
|
67
|
+
|
68
|
+
puts '-' * 80 unless options[:envs_only]
|
69
|
+
puts "%-#{width}s (%s)" % [env_name + ':', current.root.root]
|
70
|
+
|
71
|
+
next if options[:envs_only]
|
72
|
+
|
73
|
+
manifest_keys = (Tap::Env.manifests.keys + current.manifests.keys).uniq
|
74
|
+
manifest_keys.each do |name|
|
75
|
+
next if name == :envs
|
76
|
+
manifest = current.manifest(name, true)
|
77
|
+
next if manifest.empty?
|
78
|
+
|
79
|
+
puts " %-10s %s" % [name, collect_map(current, manifest).join("\n ")]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
if ARGV.empty?
|
84
|
+
puts '-' * 80
|
85
|
+
puts
|
86
|
+
env.recursive_each(0, nil) do |current, nesting_depth, last_env|
|
87
|
+
env_name, current = envs_manifest.find {|(env_name, e)| e == current }
|
88
|
+
|
89
|
+
leader = nesting_depth == 0 ? "" : '| ' * (nesting_depth - 1) + (last_env == current ? "`- " : "|- ")
|
90
|
+
puts("#{leader}#{env_name}")
|
91
|
+
[nesting_depth + 1, current.envs[-1]]
|
92
|
+
end
|
93
|
+
puts
|
94
|
+
end
|
data/cmd/run.rb
CHANGED
data/lib/tap.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
1
|
require 'yaml' # expensive to load
|
4
2
|
require 'thread'
|
5
3
|
|
@@ -7,9 +5,6 @@ require 'thread'
|
|
7
5
|
case RUBY_VERSION
|
8
6
|
when /^1.9/
|
9
7
|
$: << File.expand_path(File.dirname(__FILE__) + "/tap/patches/ruby19")
|
10
|
-
|
11
|
-
# suppresses TDoc warnings
|
12
|
-
$DEBUG_RDOC ||= nil
|
13
8
|
end
|
14
9
|
|
15
10
|
$:.unshift File.expand_path(File.dirname(__FILE__))
|
data/lib/tap/constants.rb
CHANGED
data/lib/tap/env.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'tap/
|
1
|
+
require 'tap/support/manifest'
|
2
2
|
require 'tap/support/constant'
|
3
3
|
require 'tap/support/summary'
|
4
|
-
require 'tap/support/
|
4
|
+
require 'tap/support/gems'
|
5
5
|
|
6
6
|
module Tap
|
7
7
|
|
@@ -12,16 +12,13 @@ module Tap
|
|
12
12
|
include Support::Configurable
|
13
13
|
include Enumerable
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
@@manifests = {}
|
18
|
-
|
19
|
-
class << self
|
15
|
+
class << self
|
16
|
+
|
20
17
|
# Returns the active instance of Env.
|
21
18
|
def instance
|
22
19
|
@@instance
|
23
20
|
end
|
24
|
-
|
21
|
+
|
25
22
|
# A hash of (path, Env instance) pairs, generated by Env#instantiate. Used
|
26
23
|
# to prevent infinite loops of Env dependencies by assigning a single Env
|
27
24
|
# to a given path.
|
@@ -29,6 +26,13 @@ module Tap
|
|
29
26
|
@@instances
|
30
27
|
end
|
31
28
|
|
29
|
+
# A hash of predefined manifest classes that can be initialized
|
30
|
+
# from an env. These classes are instantiated by instances
|
31
|
+
# of Env, as needed.
|
32
|
+
def manifests
|
33
|
+
@@manifests
|
34
|
+
end
|
35
|
+
|
32
36
|
# Creates a new Env for the specified path and adds it to Env#instances, or
|
33
37
|
# returns the existing instance for the path. Paths can point to an env config
|
34
38
|
# file, or to a directory. If a directory is provided, instantiate treats
|
@@ -45,7 +49,7 @@ module Tap
|
|
45
49
|
# The Env is initialized using configurations read from the env config file using
|
46
50
|
# load_config, and a Root initialized to the config file directory. An instance
|
47
51
|
# will be initialized regardless of whether the config file or directory exists.
|
48
|
-
def instantiate(path_or_root, default_config={}, logger=nil)
|
52
|
+
def instantiate(path_or_root, default_config={}, logger=nil, &block)
|
49
53
|
path = path_or_root.kind_of?(Root) ? path_or_root.root : path_or_root
|
50
54
|
path = pathify(path)
|
51
55
|
|
@@ -55,14 +59,17 @@ module Tap
|
|
55
59
|
|
56
60
|
# note the assignment of env to instances MUST occur before
|
57
61
|
# reconfigure to prevent infinite looping
|
58
|
-
(instances[path] =
|
59
|
-
yield(unhandled_configs) if block_given?
|
60
|
-
end
|
62
|
+
(instances[path] = new({}, root, logger)).reconfigure(config, &block)
|
61
63
|
rescue(Exception)
|
62
64
|
raise Env::ConfigError.new($!, path)
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
68
|
+
def instance_for(path)
|
69
|
+
path = pathify(path)
|
70
|
+
instances.has_key?(path) ? instances[path] : instantiate(path)
|
71
|
+
end
|
72
|
+
|
66
73
|
def pathify(path)
|
67
74
|
if File.directory?(path) || (!File.exists?(path) && File.extname(path) == "")
|
68
75
|
path = File.join(path, DEFAULT_CONFIG_FILE)
|
@@ -70,41 +77,60 @@ module Tap
|
|
70
77
|
File.expand_path(path)
|
71
78
|
end
|
72
79
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# figure the version of the gem, by default >= 0.0.0
|
85
|
-
gem_name.to_s =~ /^([^<=>]*)(.*)$/
|
86
|
-
name, version = $1.strip, $2
|
87
|
-
version = ">= 0.0.0" if version.empty?
|
88
|
-
|
89
|
-
return nil if name.empty?
|
90
|
-
|
91
|
-
# load the gem and get the spec
|
92
|
-
gem(name, version)
|
93
|
-
Gem.loaded_specs[name]
|
94
|
-
end
|
95
|
-
|
96
|
-
# Returns the gem name for all installed gems with a DEFAULT_CONFIG_FILE.
|
97
|
-
# If latest==true, then only the names for the most current gem specs
|
98
|
-
# will be returned.
|
99
|
-
def known_gems(latest=true)
|
100
|
-
index = latest ?
|
101
|
-
Gem.source_index.latest_specs :
|
102
|
-
Gem.source_index.gems.collect {|(name, spec)| spec }
|
80
|
+
def manifest(name, pattern, default_paths=[], &block) # :yields: search_path
|
81
|
+
manifest_class = Class.new(Support::Manifest)
|
82
|
+
manifest_class.send(:define_method, :entries_for, &block) if block_given?
|
83
|
+
manifest_class.send(:attr_reader, :env)
|
84
|
+
manifest_class.send(:define_method, :initialize) do |env|
|
85
|
+
@env = env
|
86
|
+
search_paths = default_paths.collect {|path| env.root[path] }
|
87
|
+
search_paths += env.root.glob(:root, pattern)
|
88
|
+
super search_paths.sort_by {|p| File.basename(p) }
|
89
|
+
end
|
103
90
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
91
|
+
manifests[name] = manifest_class
|
92
|
+
end
|
93
|
+
|
94
|
+
#--
|
95
|
+
# To manifest simply requires an glob_<name> method which
|
96
|
+
# yields each (key, path) pair for the manifested object in
|
97
|
+
# a predictable order.
|
98
|
+
#
|
99
|
+
#--
|
100
|
+
# Alternate implementation would create the manifest for each individual
|
101
|
+
# env, then merge the manifests. On the plus side, each env would then
|
102
|
+
# carry it's own slice of the manifest without having to recalculate.
|
103
|
+
# On the down side, the merging would have to occur in some separate
|
104
|
+
# method that cannot be defined here.
|
105
|
+
def path_manifest(name, paths_key, pattern, default_paths=[], &block) # :yields: search_path_root, search_path
|
106
|
+
manifest_class = Class.new(Support::Manifest)
|
107
|
+
manifest_class.send(:define_method, :entries_for, &block) if block_given?
|
108
|
+
manifest_class.send(:attr_reader, :env)
|
109
|
+
manifest_class.send(:define_method, :initialize) do |env|
|
110
|
+
@env = env
|
111
|
+
search_paths = default_paths.collect do |path|
|
112
|
+
[env.root.root, env.root[path]]
|
113
|
+
end
|
114
|
+
|
115
|
+
env.send(paths_key).each do |search_path_root|
|
116
|
+
env.root.glob(search_path_root, pattern).each do |search_path|
|
117
|
+
search_paths << [search_path_root, search_path]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
super search_paths.sort_by {|pr, p| File.basename(p) }
|
122
|
+
end
|
123
|
+
manifests[name] = manifest_class
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns the gemspecs for all installed gems with a DEFAULT_TASK_FILE
|
127
|
+
# or DEFAULT_CONFIG_FILE. If latest==true, then only the specs for the
|
128
|
+
# most current gems will be returned.
|
129
|
+
def gemspecs(latest=true)
|
130
|
+
Support::Gems.select_gems(latest) do |spec|
|
131
|
+
File.exists?(File.join(spec.full_gem_path, DEFAULT_TASK_FILE)) ||
|
132
|
+
File.exists?(File.join(spec.full_gem_path, DEFAULT_CONFIG_FILE))
|
133
|
+
end
|
108
134
|
end
|
109
135
|
|
110
136
|
protected
|
@@ -137,46 +163,21 @@ module Tap
|
|
137
163
|
instance_variable_set(instance_variable, [*input].compact.collect {|path| root[path]}.uniq)
|
138
164
|
end
|
139
165
|
end
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
#--
|
147
|
-
# Alternate implementation would create the manifest for each individual
|
148
|
-
# env, then merge the manifests. On the plus side, each env would then
|
149
|
-
# carry it's own slice of the manifest without having to recalculate.
|
150
|
-
# On the down side, the merging would have to occur in some separate
|
151
|
-
# method that cannot be defined here.
|
152
|
-
def manifest(name, paths_key, pattern, &block)
|
153
|
-
return manifest(name, paths_key, pattern) do |context, path|
|
154
|
-
[[path.chomp(File.extname(path)), path]]
|
155
|
-
end unless block_given?
|
156
|
-
|
157
|
-
glob_method = Support::Manifest.glob_method(name)
|
158
|
-
module_eval %Q{
|
159
|
-
def #{glob_method}
|
160
|
-
paths = []
|
161
|
-
self.#{paths_key}.each do |manifest_path|
|
162
|
-
root.glob(manifest_path, "#{pattern}").each do |path|
|
163
|
-
next if File.directory?(path)
|
164
|
-
paths << [manifest_path, path]
|
165
|
-
end
|
166
|
-
end
|
167
|
-
paths.sort_by {|mp, p| File.basename(p)}
|
168
|
-
end
|
169
|
-
}
|
170
|
-
|
171
|
-
map_method = Support::Manifest.map_method(name)
|
172
|
-
define_method(map_method, &block)
|
173
|
-
|
174
|
-
protected glob_method, map_method
|
166
|
+
end
|
167
|
+
|
168
|
+
class Manifest < Support::Manifest
|
169
|
+
def initialize(env)
|
170
|
+
super([])
|
171
|
+
@entries = env.collect {|e| [e.root.root, e] }
|
175
172
|
end
|
176
173
|
end
|
177
174
|
|
175
|
+
@@instance = nil
|
176
|
+
@@instances = {}
|
177
|
+
@@manifests = {:envs => Manifest}
|
178
|
+
|
178
179
|
# The global config file path
|
179
|
-
GLOBAL_CONFIG_FILE = File.join(
|
180
|
+
GLOBAL_CONFIG_FILE = File.join(Support::Gems.user_home, ".tap.yml")
|
180
181
|
|
181
182
|
# The default config file path
|
182
183
|
DEFAULT_CONFIG_FILE = "tap.yml"
|
@@ -204,7 +205,7 @@ module Tap
|
|
204
205
|
config_attr :gems, [] do |input|
|
205
206
|
check_configurable
|
206
207
|
@gems = [*input].compact.collect do |gem_name|
|
207
|
-
spec =
|
208
|
+
spec = Support::Gems.gemspec(gem_name)
|
208
209
|
|
209
210
|
case spec
|
210
211
|
when nil then log(:warn, "unknown gem: #{gem_name}", Logger::WARN)
|
@@ -224,10 +225,8 @@ module Tap
|
|
224
225
|
end.uniq
|
225
226
|
reset_envs
|
226
227
|
end
|
227
|
-
|
228
|
-
# Designate load paths.
|
229
|
-
# load_paths will be used for automatic loading of modules
|
230
|
-
# through the active_support Dependencies module.
|
228
|
+
|
229
|
+
# Designate load paths.
|
231
230
|
path_config :load_paths, ["lib"]
|
232
231
|
|
233
232
|
# Designate paths for discovering and executing commands.
|
@@ -236,12 +235,12 @@ module Tap
|
|
236
235
|
# Designate paths for discovering generators.
|
237
236
|
path_config :generator_paths, ["lib"]
|
238
237
|
|
239
|
-
|
240
|
-
next unless document = Support::Lazydoc.scan_doc(path, 'manifest')
|
238
|
+
path_manifest(:tasks, :load_paths, "**/*.rb", [DEFAULT_TASK_FILE]) do |load_path, path|
|
239
|
+
next unless File.file?(path) && document = Support::Lazydoc.scan_doc(path, 'manifest')
|
241
240
|
|
242
241
|
document.const_names.collect do |const_name|
|
243
242
|
if const_name.empty?
|
244
|
-
key = root.relative_filepath(load_path, path).chomp('.rb')
|
243
|
+
key = env.root.relative_filepath(load_path, path).chomp('.rb')
|
245
244
|
[key, Support::Constant.new(key.camelize, path)]
|
246
245
|
else
|
247
246
|
[const_name.underscore, Support::Constant.new(const_name, path)]
|
@@ -249,16 +248,18 @@ module Tap
|
|
249
248
|
end
|
250
249
|
end
|
251
250
|
|
252
|
-
|
251
|
+
path_manifest(:commands, :command_paths, "**/*.rb") do |command_path, path|
|
252
|
+
File.file?(path) ? [[path, path]] : nil
|
253
|
+
end
|
253
254
|
|
254
|
-
|
255
|
+
path_manifest(:generators, :generator_paths, '**/*_generator.rb') do |generator_path, path|
|
255
256
|
dirname = File.dirname(path)
|
256
|
-
next unless "#{File.basename(dirname)}_generator.rb" == File.basename(path)
|
257
|
+
next unless File.file?(path) && "#{File.basename(dirname)}_generator.rb" == File.basename(path)
|
257
258
|
|
258
259
|
next unless document = Support::Lazydoc.scan_doc(path, 'generator')
|
259
260
|
document.const_names.collect do |const_name|
|
260
261
|
if const_name.empty?
|
261
|
-
key = root.relative_filepath(
|
262
|
+
key = env.root.relative_filepath(generator_path, dirname)
|
262
263
|
[key, Support::Constant.new((key + '_generator').camelize, path)]
|
263
264
|
else
|
264
265
|
[const_name.underscore, Support::Constant.new(const_name, path)]
|
@@ -304,7 +305,7 @@ module Tap
|
|
304
305
|
unless env == self || envs[0] == env
|
305
306
|
self.envs = envs.dup.unshift(env)
|
306
307
|
end
|
307
|
-
|
308
|
+
self
|
308
309
|
end
|
309
310
|
|
310
311
|
# Pushes env onto envs, removing duplicates.
|
@@ -314,7 +315,7 @@ module Tap
|
|
314
315
|
envs = self.envs.reject {|e| e == env }
|
315
316
|
self.envs = envs.push(env)
|
316
317
|
end
|
317
|
-
|
318
|
+
self
|
318
319
|
end
|
319
320
|
|
320
321
|
# Passes each nested env to the block in order, starting with self.
|
@@ -327,18 +328,40 @@ module Tap
|
|
327
328
|
envs(true).reverse_each {|e| yield(e) }
|
328
329
|
end
|
329
330
|
|
331
|
+
# Visits each nested env in order, starting with self, and passing
|
332
|
+
# to the block the env and any arguments generated by the parent of
|
333
|
+
# the env. The initial arguments are set when recursive_each is
|
334
|
+
# first called; subsequent arguements are the return values of the
|
335
|
+
# block.
|
336
|
+
#
|
337
|
+
# e0, e1, e2, e3, e4 = ('a'..'e').collect {|name| Tap::Env.new(:name => name) }
|
338
|
+
#
|
339
|
+
# e0.push(e1).push(e2)
|
340
|
+
# e1.push(e3).push(e4)
|
341
|
+
#
|
342
|
+
# lines = []
|
343
|
+
# e0.recursive_each(0) do |env, nesting_depth|
|
344
|
+
# lines << "\n#{'..' * nesting_depth}#{env.config[:name]} (#{nesting_depth})"
|
345
|
+
# nesting_depth + 1
|
346
|
+
# end
|
347
|
+
#
|
348
|
+
# lines.join
|
349
|
+
# # => %Q{
|
350
|
+
# # a (0)
|
351
|
+
# # ..b (1)
|
352
|
+
# # ....d (2)
|
353
|
+
# # ....e (2)
|
354
|
+
# # ..c (1)}
|
355
|
+
#
|
356
|
+
def recursive_each(*args, &block) # :yields: env, *parent_args
|
357
|
+
each_nested_env(self, [], args, &block)
|
358
|
+
end
|
359
|
+
|
330
360
|
# Returns the total number of unique envs nested in self (including self).
|
331
361
|
def count
|
332
362
|
envs(true).length
|
333
363
|
end
|
334
364
|
|
335
|
-
# Returns a list of arrays that receive load_paths on activate,
|
336
|
-
# by default [$LOAD_PATH]. If use_dependencies == true, then
|
337
|
-
# Dependencies.load_paths will also be included.
|
338
|
-
def load_path_targets
|
339
|
-
[$LOAD_PATH]
|
340
|
-
end
|
341
|
-
|
342
365
|
# Processes and resets the input configurations for both root
|
343
366
|
# and self. Reconfiguration consists of the following steps:
|
344
367
|
#
|
@@ -412,7 +435,7 @@ module Tap
|
|
412
435
|
return false if active?
|
413
436
|
|
414
437
|
@active = true
|
415
|
-
@@instance = self
|
438
|
+
@@instance = self if @@instance == nil
|
416
439
|
|
417
440
|
# freeze array configs like load_paths
|
418
441
|
config.each_pair do |key, value|
|
@@ -426,15 +449,12 @@ module Tap
|
|
426
449
|
env.activate
|
427
450
|
end
|
428
451
|
|
429
|
-
# add load paths
|
430
|
-
|
431
|
-
|
432
|
-
target.unshift(path)
|
433
|
-
end
|
434
|
-
|
435
|
-
target.uniq!
|
452
|
+
# add load paths
|
453
|
+
load_paths.reverse_each do |path|
|
454
|
+
$LOAD_PATH.unshift(path)
|
436
455
|
end
|
437
456
|
|
457
|
+
$LOAD_PATH.uniq!
|
438
458
|
true
|
439
459
|
end
|
440
460
|
|
@@ -446,13 +466,11 @@ module Tap
|
|
446
466
|
def deactivate
|
447
467
|
return false unless active?
|
448
468
|
|
449
|
-
# remove load paths
|
450
|
-
|
451
|
-
|
452
|
-
target.delete(path)
|
453
|
-
end
|
469
|
+
# remove load paths
|
470
|
+
load_paths.each do |path|
|
471
|
+
$LOAD_PATH.delete(path)
|
454
472
|
end
|
455
|
-
|
473
|
+
|
456
474
|
# unfreeze array configs by duplicating
|
457
475
|
self.config.class_config.each_pair do |key, value|
|
458
476
|
value = send(key)
|
@@ -478,57 +496,76 @@ module Tap
|
|
478
496
|
@active
|
479
497
|
end
|
480
498
|
|
481
|
-
#
|
482
|
-
#
|
483
|
-
#
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
499
|
+
# Returns the manifest in manifests by the specified name. Yields
|
500
|
+
# each entry in the manifest to the block, if given, or simply
|
501
|
+
# builds and returns the manifest.
|
502
|
+
#
|
503
|
+
# If the specified manifest does not exists, the manifest class
|
504
|
+
# in self.class.manifests will be instatiated with self to make
|
505
|
+
# the manifest. Raises an error if no manifest could be found
|
506
|
+
# or instantiated.
|
507
|
+
def manifest(name, build=false)
|
508
|
+
manifest = manifests[name] ||= case
|
509
|
+
when manifests_class = self.class.manifests[name]
|
510
|
+
manifests_class.new(self)
|
511
|
+
else
|
512
|
+
raise "unknown manifest: #{name}"
|
513
|
+
end
|
514
|
+
|
515
|
+
manifest.build if build
|
498
516
|
manifest
|
499
517
|
end
|
500
518
|
|
501
|
-
|
502
|
-
|
503
|
-
|
519
|
+
# Returns the first value in the specified manifest where the key
|
520
|
+
# mini-matches the input pattern. See Tap::Root.minimal_match?
|
521
|
+
# for details on mini-matching.
|
522
|
+
def find(name, pattern, value_only=true)
|
523
|
+
manifest(name).each do |key, value|
|
524
|
+
return(value_only ? value : [key, value]) if Root.minimal_match?(key, pattern)
|
504
525
|
end
|
505
526
|
nil
|
506
527
|
end
|
507
528
|
|
508
|
-
|
509
|
-
|
529
|
+
# Like find, but searches across all envs for the matching value.
|
530
|
+
# An env pattern can be provided in pattern, to select a single
|
531
|
+
# env to search.
|
532
|
+
#
|
533
|
+
# The :envs manifest cannot be searched; use find instead.
|
534
|
+
def search(name, pattern, value_only=true)
|
535
|
+
if name == :envs
|
536
|
+
raise ArgumentError, "cannot search the :envs manifest; use find instead"
|
537
|
+
end
|
510
538
|
|
511
539
|
envs = case pattern
|
512
540
|
when /^(.*):([^:]+)$/
|
513
541
|
env_pattern = $1
|
514
542
|
pattern = $2
|
515
|
-
find(:envs, env_pattern)
|
543
|
+
find(:envs, env_pattern)
|
516
544
|
else manifest(:envs).values
|
517
545
|
end
|
518
546
|
|
519
547
|
envs.each do |env|
|
520
|
-
if result = env.find(name, pattern)
|
548
|
+
if result = env.find(name, pattern, value_only)
|
521
549
|
return result
|
522
550
|
end
|
523
|
-
end
|
551
|
+
end if envs
|
524
552
|
|
525
553
|
nil
|
526
554
|
end
|
527
555
|
|
556
|
+
def constantize(name, *patterns)
|
557
|
+
patterns.collect do |pattern|
|
558
|
+
case const = search(name, pattern)
|
559
|
+
when Support::Constant then const.constantize
|
560
|
+
else raise "could not constantize: #{pattern} (#{name})"
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
528
565
|
def summary(name)
|
529
566
|
summary = Support::Summary.new
|
530
|
-
manifest(:envs).
|
531
|
-
summary.add(key, env, env.manifest(name).
|
567
|
+
manifest(:envs, true).minimize.each do |(key, env)|
|
568
|
+
summary.add(key, env, env.manifest(name, true).minimize)
|
532
569
|
end
|
533
570
|
summary
|
534
571
|
end
|
@@ -546,51 +583,9 @@ module Tap
|
|
546
583
|
def to_s
|
547
584
|
inspect(true)
|
548
585
|
end
|
549
|
-
|
550
|
-
#--
|
551
|
-
# Under construction
|
552
|
-
#++
|
553
|
-
|
554
|
-
def handle_error(err)
|
555
|
-
case
|
556
|
-
when $DEBUG
|
557
|
-
puts err.message
|
558
|
-
puts
|
559
|
-
puts err.backtrace
|
560
|
-
else puts err.message
|
561
|
-
end
|
562
|
-
end
|
563
586
|
|
564
587
|
protected
|
565
588
|
|
566
|
-
# Iterates over each nested env, yielding the root path and env.
|
567
|
-
# This is the manifest method for envs.
|
568
|
-
def manifest_glob_envs
|
569
|
-
collect {|env| [env.root.root, env] }.sort_by {|root, env| File.basename(root) }
|
570
|
-
end
|
571
|
-
|
572
|
-
def manifest_map(context, path)
|
573
|
-
[[context, path]]
|
574
|
-
end
|
575
|
-
|
576
|
-
alias default_manifest_glob_tasks manifest_glob_tasks
|
577
|
-
|
578
|
-
def manifest_glob_tasks
|
579
|
-
paths = default_manifest_glob_tasks
|
580
|
-
|
581
|
-
# very odd behaviors --
|
582
|
-
# * OS X is case-insensitive, apparently. Tapfile.rb and tapfile.rb are the same.
|
583
|
-
# * require 'tapfile' does not work
|
584
|
-
# * require 'tapfile.rb' works
|
585
|
-
# * load 'tapfile' works
|
586
|
-
#
|
587
|
-
root.glob(:root, DEFAULT_TASK_FILE).each do |path|
|
588
|
-
next if File.directory?(path)
|
589
|
-
paths.unshift [root.root, path]
|
590
|
-
end
|
591
|
-
paths
|
592
|
-
end
|
593
|
-
|
594
589
|
# Raises an error if self is already active (and hence, configurations
|
595
590
|
# should not be modified)
|
596
591
|
def check_configurable
|
@@ -619,7 +614,20 @@ module Tap
|
|
619
614
|
|
620
615
|
target
|
621
616
|
end
|
622
|
-
|
617
|
+
|
618
|
+
private
|
619
|
+
|
620
|
+
def each_nested_env(env, visited, args, &block)
|
621
|
+
return if visited.include?(env)
|
622
|
+
|
623
|
+
visited << env
|
624
|
+
next_args = yield(env, *args)
|
625
|
+
next_args = [] if next_args == nil
|
626
|
+
env.envs.each do |nested_env|
|
627
|
+
each_nested_env(nested_env, visited, next_args, &block)
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
623
631
|
# Raised when there is a Env-level configuration error.
|
624
632
|
class ConfigError < StandardError
|
625
633
|
attr_reader :original_error, :env_path
|