tap 0.18.0 → 0.19.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/History +21 -0
- data/MIT-LICENSE +17 -15
- data/README +13 -30
- data/bin/tap +19 -24
- data/cmd/console.rb +1 -12
- data/cmd/manifest.rb +14 -19
- data/cmd/run.rb +96 -86
- data/doc/API +194 -54
- data/doc/Examples/Command Line +27 -1
- data/lib/tap.rb +2 -1
- data/lib/tap/app.rb +613 -166
- data/lib/tap/app/api.rb +115 -0
- data/lib/tap/app/queue.rb +36 -37
- data/lib/tap/app/state.rb +2 -1
- data/lib/tap/env.rb +454 -270
- data/lib/tap/env/constant.rb +83 -33
- data/lib/tap/env/context.rb +61 -0
- data/lib/tap/env/manifest.rb +140 -50
- data/lib/tap/env/minimap.rb +55 -39
- data/lib/tap/join.rb +71 -53
- data/lib/tap/joins/sync.rb +3 -1
- data/lib/tap/middleware.rb +4 -25
- data/lib/tap/middlewares/debugger.rb +75 -0
- data/lib/tap/parser.rb +268 -0
- data/lib/tap/prompt.rb +36 -0
- data/lib/tap/root.rb +3 -3
- data/lib/tap/signals.rb +26 -0
- data/lib/tap/signals/class_methods.rb +222 -0
- data/lib/tap/signals/help.rb +40 -0
- data/lib/tap/signals/module_methods.rb +20 -0
- data/lib/tap/signals/signal.rb +68 -0
- data/lib/tap/task.rb +28 -79
- data/lib/tap/tasks/dump.rb +6 -0
- data/lib/tap/tasks/load.rb +9 -37
- data/lib/tap/templater.rb +12 -1
- data/lib/tap/version.rb +1 -1
- metadata +22 -16
- data/doc/Class Reference +0 -330
- data/lib/tap/exe.rb +0 -130
- data/lib/tap/schema.rb +0 -374
- data/lib/tap/schema/parser.rb +0 -425
- data/lib/tap/schema/utils.rb +0 -56
data/lib/tap/app/api.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'configurable'
|
2
|
+
require 'tap/signals/help'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
class App
|
6
|
+
|
7
|
+
# Api implements the application interface described in the
|
8
|
+
# API[link:files/doc/API.html] document, and provides additional
|
9
|
+
# functionality shared by the Tap base classes.
|
10
|
+
class Api
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# The type of the class.
|
14
|
+
attr_reader :type
|
15
|
+
|
16
|
+
def inherited(child) # :nodoc:
|
17
|
+
super
|
18
|
+
|
19
|
+
type = self.type || child.to_s.split('::').last.downcase
|
20
|
+
child.instance_variable_set(:@type, type)
|
21
|
+
|
22
|
+
unless child.respond_to?(:desc)
|
23
|
+
child.lazy_attr(:desc, type)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a ConfigParser setup to parse the configurations for the
|
28
|
+
# subclass. The parser is also setup to print usage (using the desc
|
29
|
+
# for the subclass) and exit for the '-h' and '--help' options.
|
30
|
+
#
|
31
|
+
# The parse method uses parser by default, so subclasses can simply
|
32
|
+
# modify parser and ensure parse still works correctly.
|
33
|
+
def parser
|
34
|
+
opts = ConfigParser.new
|
35
|
+
|
36
|
+
unless configurations.empty?
|
37
|
+
opts.separator "configurations:"
|
38
|
+
opts.add(configurations)
|
39
|
+
opts.separator ""
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.separator "options:"
|
43
|
+
|
44
|
+
# add option to print help
|
45
|
+
opts.on("-h", "--help", "Print this help") do
|
46
|
+
puts "#{self}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"
|
47
|
+
puts help
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
opts
|
53
|
+
end
|
54
|
+
|
55
|
+
# Parses the argv into an instance of self. Internally parse parses
|
56
|
+
# an argh then calls build, but there is no requirement that this
|
57
|
+
# occurs in subclasses.
|
58
|
+
def parse(argv=ARGV, app=Tap::App.instance)
|
59
|
+
parse!(argv.dup, app)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Same as parse, but removes arguments destructively.
|
63
|
+
def parse!(argv=ARGV, app=Tap::App.instance)
|
64
|
+
parser = self.parser
|
65
|
+
argv = parser.parse!(argv, :add_defaults => false)
|
66
|
+
|
67
|
+
[build({'config' => parser.nested_config}, app), argv]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an instance of self. By default build calls new with the
|
71
|
+
# configurations specified by spec['config'], and app.
|
72
|
+
def build(spec={}, app=Tap::App.instance)
|
73
|
+
new(spec['config'] || {}, app)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns a help string that formats the desc documentation.
|
77
|
+
def help
|
78
|
+
lines = desc.kind_of?(Lazydoc::Comment) ? desc.wrap(77, 2, nil) : []
|
79
|
+
lines.collect! {|line| " #{line}"}
|
80
|
+
unless lines.empty?
|
81
|
+
line = '-' * 80
|
82
|
+
lines.unshift(line)
|
83
|
+
lines.push(line)
|
84
|
+
end
|
85
|
+
|
86
|
+
lines.join("\n")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
include Configurable
|
91
|
+
include Signals
|
92
|
+
|
93
|
+
signal :help, :class => Help, :bind => nil # signals help
|
94
|
+
|
95
|
+
# The App receiving self during enq
|
96
|
+
attr_reader :app
|
97
|
+
|
98
|
+
def initialize(config={}, app=Tap::App.instance)
|
99
|
+
@app = app
|
100
|
+
initialize_config(config)
|
101
|
+
end
|
102
|
+
|
103
|
+
# By default associations returns nil.
|
104
|
+
def associations
|
105
|
+
end
|
106
|
+
|
107
|
+
# By default to_spec returns a hash like {'config' => config} where
|
108
|
+
# config is a stringified representation of the configurations for self.
|
109
|
+
def to_spec
|
110
|
+
config = self.config.to_hash {|hash, key, value| hash[key.to_s] = value }
|
111
|
+
{'config' => config}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/tap/app/queue.rb
CHANGED
@@ -5,71 +5,70 @@ module Tap
|
|
5
5
|
|
6
6
|
# Queue allows thread-safe enqueing and dequeing of nodes and inputs for
|
7
7
|
# execution.
|
8
|
+
#
|
9
|
+
# === API
|
10
|
+
#
|
11
|
+
# The following methods are required in alternative implementations of an
|
12
|
+
# applicaton queue, where a job is a [node, inputs] array:
|
13
|
+
#
|
14
|
+
# enq(node, inputs) # pushes the job onto the queue
|
15
|
+
# unshift(node, inputs) # unshifts the job onto the queue
|
16
|
+
# deq # shifts a job off the queue
|
17
|
+
# size # returns the number of jobs in the queue
|
18
|
+
# clear # clears the queue, returns current jobs
|
19
|
+
# synchronize # yields to the block
|
20
|
+
# to_a # returns the queue as an array
|
21
|
+
#
|
22
|
+
# Note that synchronize must be implemented even if it does nothing but
|
23
|
+
# yield to the block.
|
8
24
|
class Queue < Monitor
|
9
25
|
|
10
|
-
attr_reader :queue
|
11
|
-
|
12
26
|
# Creates a new Queue
|
13
27
|
def initialize
|
14
28
|
super
|
15
29
|
@queue = []
|
16
30
|
end
|
17
31
|
|
18
|
-
#
|
19
|
-
|
20
|
-
def clear
|
32
|
+
# Enqueues the node and inputs as a job.
|
33
|
+
def enq(node, inputs)
|
21
34
|
synchronize do
|
22
|
-
|
23
|
-
@queue = []
|
24
|
-
current
|
35
|
+
@queue.push [node, inputs]
|
25
36
|
end
|
26
37
|
end
|
27
38
|
|
28
|
-
#
|
29
|
-
def
|
39
|
+
# Enqueues the node and inputs, but to the top of the queue.
|
40
|
+
def unshift(node, inputs)
|
30
41
|
synchronize do
|
31
|
-
queue.
|
42
|
+
@queue.unshift [node, inputs]
|
32
43
|
end
|
33
44
|
end
|
34
45
|
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
# Enqueues the method and inputs.
|
41
|
-
def enq(method, inputs)
|
42
|
-
synchronize do
|
43
|
-
queue.push [method, inputs]
|
44
|
-
end
|
46
|
+
# Dequeues the next job as an array like [node, inputs]. Returns nil if
|
47
|
+
# the queue is empty.
|
48
|
+
def deq
|
49
|
+
synchronize { @queue.shift }
|
45
50
|
end
|
46
51
|
|
47
|
-
#
|
48
|
-
def
|
52
|
+
# Returns the number of enqueued jobs.
|
53
|
+
def size
|
49
54
|
synchronize do
|
50
|
-
queue.
|
55
|
+
@queue.size
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
54
|
-
#
|
55
|
-
def
|
59
|
+
# Clears self and returns an array of the currently enqueued jobs.
|
60
|
+
def clear
|
56
61
|
synchronize do
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
current = @queue
|
63
|
+
@queue = []
|
64
|
+
current
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
63
|
-
#
|
64
|
-
# [method, inputs]. Returns nil if the queue is empty.
|
65
|
-
def deq
|
66
|
-
synchronize { queue.shift }
|
67
|
-
end
|
68
|
-
|
69
|
-
# Converts self to an array.
|
68
|
+
# Returns the enqueued jobs as an array.
|
70
69
|
def to_a
|
71
70
|
synchronize do
|
72
|
-
queue.dup
|
71
|
+
@queue.dup
|
73
72
|
end
|
74
73
|
end
|
75
74
|
end
|
data/lib/tap/app/state.rb
CHANGED
@@ -15,7 +15,8 @@ module Tap
|
|
15
15
|
# State.state_str(0) # => 'READY'
|
16
16
|
# State.state_str(12) # => nil
|
17
17
|
def state_str(state)
|
18
|
-
constants.
|
18
|
+
const = constants.find {|const_name| const_get(const_name) == state }
|
19
|
+
const ? const.to_s : nil
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
data/lib/tap/env.rb
CHANGED
@@ -1,24 +1,243 @@
|
|
1
1
|
require 'tap/root'
|
2
|
+
require 'tap/env/constant'
|
3
|
+
require 'tap/env/context'
|
2
4
|
require 'tap/env/manifest'
|
3
5
|
require 'tap/templater'
|
4
6
|
autoload(:YAML, 'yaml')
|
5
7
|
|
6
8
|
module Tap
|
7
|
-
|
9
|
+
|
10
|
+
# == Description
|
11
|
+
#
|
12
|
+
# Env provides access to an execution environment spanning many directories,
|
13
|
+
# such as the working directory plus a series of gem directories. Envs merge
|
14
|
+
# the files from each directory into an abstract directory that may be
|
15
|
+
# globbed and accessed as a single unit. For example:
|
16
|
+
#
|
17
|
+
# # /one
|
18
|
+
# # |-- a.rb
|
19
|
+
# # `-- b.rb
|
20
|
+
# #
|
21
|
+
# # /two
|
22
|
+
# # |-- b.rb
|
23
|
+
# # `-- c.rb
|
24
|
+
# env = Env.new('/one')
|
25
|
+
# env << Env.new('/two')
|
26
|
+
#
|
27
|
+
# env.collect {|e| e.root.root}
|
28
|
+
# # => ["/one", "/two"]
|
29
|
+
#
|
30
|
+
# env.glob(:root, "*.rb")
|
31
|
+
# # => [
|
32
|
+
# # "/one/a.rb",
|
33
|
+
# # "/one/b.rb",
|
34
|
+
# # "/two/c.rb"
|
35
|
+
# # ]
|
36
|
+
#
|
37
|
+
# As illustrated, files in the nested environment are accessible within the
|
38
|
+
# nesting environment. Envs provide methods for finding files associated
|
39
|
+
# with a specific class, and allow the generation of manifests that provide
|
40
|
+
# succinct access to various environment resources.
|
41
|
+
#
|
42
|
+
# Usage of Envs is fairly straightforward, but the internals and default
|
43
|
+
# setup require some study as they have to span numerous functional domains.
|
44
|
+
# The most common features are detailed below.
|
45
|
+
#
|
46
|
+
# ==== Class Paths
|
47
|
+
#
|
48
|
+
# Class paths are a kind of inheritance for files associated with a class.
|
49
|
+
# Say we had the following classes:
|
50
|
+
#
|
51
|
+
# class A; end
|
52
|
+
# class B < A; end
|
53
|
+
#
|
54
|
+
# The naturally associated directories are 'a' and 'b'. To look these up:
|
55
|
+
#
|
56
|
+
# env.class_path(:root, A) # => "/one/a"
|
57
|
+
# env.class_path(:root, B) # => "/one/b"
|
58
|
+
#
|
59
|
+
# And to look up an associated file:
|
60
|
+
#
|
61
|
+
# env.class_path(:root, A, "index.html") # => "/one/a/index.html"
|
62
|
+
# env.class_path(:root, B, "index.html") # => "/one/b/index.html"
|
63
|
+
#
|
64
|
+
# A block may be given to filter paths, for instance to test if a given file
|
65
|
+
# exists. The class_path method will check each env then roll up the
|
66
|
+
# inheritance hierarchy until the block returns true.
|
67
|
+
#
|
68
|
+
# FileUtils.touch("/two/a/index.html")
|
69
|
+
#
|
70
|
+
# visited_paths = []
|
71
|
+
# env.class_path(:root, B, "index.html) do |path|
|
72
|
+
# visited_paths << path
|
73
|
+
# File.exists?(path)
|
74
|
+
# end # => "/two/a/index.html"
|
75
|
+
#
|
76
|
+
# visited_paths
|
77
|
+
# # => [
|
78
|
+
# # "/one/b/index.html",
|
79
|
+
# # "/two/b/index.html",
|
80
|
+
# # "/one/a/index.html",
|
81
|
+
# # "/two/a/index.html"
|
82
|
+
# # ]
|
83
|
+
#
|
84
|
+
# This behavior is very useful for associating views with a class.
|
85
|
+
#
|
86
|
+
# ==== Manifest
|
87
|
+
#
|
88
|
+
# Envs can generate manifests of various resources so they may be identified
|
89
|
+
# using minipaths (see Minimap for details regarding minipaths). Command
|
90
|
+
# files used by the tap executable are one example of a resource, and the
|
91
|
+
# constants used in building a workflow are another.
|
92
|
+
#
|
93
|
+
# Manifest are generated by defining a builder, typically a block, that
|
94
|
+
# receives an env and returns an array of the associated resources.
|
95
|
+
# Using the same env as above:
|
96
|
+
#
|
97
|
+
# manifest = env.manifest {|e| e.root.glob(:root, "*.rb") }
|
98
|
+
#
|
99
|
+
# manifest.seek("a") # => "/one/a.rb"
|
100
|
+
# manifest.seek("b") # => "/one/b.rb"
|
101
|
+
# manifest.seek("c") # => "/two/c.rb"
|
102
|
+
#
|
103
|
+
# As illustrated, seek finds the first entry across all envs that matches the
|
104
|
+
# input minipath. A minipath for the env may be prepended to only search
|
105
|
+
# within a specific env.
|
106
|
+
#
|
107
|
+
# manifest.seek("one:b") # => "/one/b.rb"
|
108
|
+
# manifest.seek("two:b") # => "/two/b.rb"
|
109
|
+
#
|
110
|
+
# Env caches a manifest of constants identified by {constant attributes}[http://tap.rubyforge.org/lazydoc]
|
111
|
+
# in files specified by under the Env.const_paths. These constants are used
|
112
|
+
# when interpreting signals from the command line. Constants may be manually
|
113
|
+
# registered to the constants manifest and classified by type like this:
|
114
|
+
#
|
115
|
+
# class CustomTask
|
116
|
+
# def call; end
|
117
|
+
# end
|
118
|
+
# env.register(CustomTask).register_as(:task, "this is a custom task")
|
119
|
+
#
|
120
|
+
# const = env.constants.seek('custom_task')
|
121
|
+
# const.const_name # => "CustomTask"
|
122
|
+
# const.types # => {:task => "this is a custom task"}
|
123
|
+
# const.constantize # => CustomTask
|
124
|
+
#
|
125
|
+
# == Setup
|
126
|
+
#
|
127
|
+
# Envs may be manually setup in code by individually generating instances
|
128
|
+
# and nesting them. More commonly envs are defined in configuration files
|
129
|
+
# and instantiated by specifying where the files are located. The default
|
130
|
+
# config basename is 'tap.yml'; any env_paths specified in the config file
|
131
|
+
# will be added.
|
132
|
+
#
|
133
|
+
# This type of instantiation is recursive:
|
134
|
+
#
|
135
|
+
# # [/one/tap.yml]
|
136
|
+
# # env_paths: [/two]
|
137
|
+
# #
|
138
|
+
# # [/two/tap.yml]
|
139
|
+
# # env_paths: [/three]
|
140
|
+
# #
|
141
|
+
#
|
142
|
+
# env = Env.new("/one", :basename => 'tap.yml')
|
143
|
+
# env.collect {|e| e.root.root}
|
144
|
+
# # => ["/one", "/two", "/three"]
|
145
|
+
#
|
146
|
+
# Gem directories are fair game. Env allows specific gems to be specified
|
147
|
+
# by name (via the 'gems' config), and if a gem has a tap.yml file then it
|
148
|
+
# will be used to configure the gem env. Alternatively, an env may be set
|
149
|
+
# to automatically discover and nest gem environments. In this case gems
|
150
|
+
# are discovered when they have a tap.yml file.
|
151
|
+
#
|
152
|
+
# ==== ENV configs
|
153
|
+
#
|
154
|
+
# Configurations may be also specified as an ENV variables. This type of
|
155
|
+
# configuration is very useful on the command line. Config variables
|
156
|
+
# should be prefixed by TAP_ and named like the capitalized config key
|
157
|
+
# (ex: TAP_GEMS or TAP_ENV_PATHS). See the
|
158
|
+
# {Command Line Examples}[link:files/doc/Examples/Command%20Line.html]
|
159
|
+
# to see ENV configs in action.
|
160
|
+
#
|
161
|
+
# These configurations may be accessed from Env#config, and are
|
162
|
+
# automatically incorporated by Env#setup.
|
163
|
+
#
|
8
164
|
class Env
|
9
165
|
autoload(:Gems, 'tap/env/gems')
|
10
166
|
|
11
167
|
class << self
|
12
|
-
attr_writer :instance
|
13
168
|
|
14
|
-
|
15
|
-
|
169
|
+
# Returns the Env configs specified in ENV. Config variables are
|
170
|
+
# prefixed by TAP_ and named like the capitalized config key
|
171
|
+
# (ex: TAP_GEMS or TAP_ENV_PATHS).
|
172
|
+
def config(env_vars=ENV)
|
173
|
+
config = {}
|
174
|
+
env_vars.each_pair do |key, value|
|
175
|
+
if key =~ /\ATAP_(.*)\z/
|
176
|
+
config[$1.downcase] = value
|
177
|
+
end
|
178
|
+
end
|
179
|
+
config
|
16
180
|
end
|
17
181
|
|
18
|
-
|
182
|
+
# Initializes and activates an env as described in the config file under
|
183
|
+
# dir. The config file should be a relative path and will be used for
|
184
|
+
# determining configuration files under each env_path.
|
185
|
+
#
|
186
|
+
# The env configuration is determined by merging the following in order:
|
187
|
+
# * defaults {root => dir, gems => all}
|
188
|
+
# * ENV configs
|
189
|
+
# * config_file configs
|
190
|
+
#
|
191
|
+
# The HOME directory for Tap will be added as an additonal environment
|
192
|
+
# if not already added somewhere in the env hierarchy. By default all
|
193
|
+
# gems will be included in the Env.
|
194
|
+
def setup(dir=Dir.pwd, config_file=CONFIG_FILE)
|
195
|
+
# setup configurations
|
196
|
+
config = {'root' => dir, 'gems' => :all}
|
197
|
+
|
198
|
+
user_config_file = config_file ? File.join(dir, config_file) : nil
|
199
|
+
user = load_config(user_config_file)
|
200
|
+
|
201
|
+
config.merge!(self.config)
|
202
|
+
config.merge!(user)
|
203
|
+
|
204
|
+
# keys must be symbolized as they are immediately
|
205
|
+
# used to initialize the Env configs
|
206
|
+
config = config.inject({}) do |options, (key, value)|
|
207
|
+
options[key.to_sym || key] = value
|
208
|
+
options
|
209
|
+
end
|
210
|
+
|
211
|
+
# instantiate
|
212
|
+
context = Context.new(:basename => config_file)
|
213
|
+
env = new(config, context)
|
214
|
+
|
215
|
+
# add the tap env if necessary
|
216
|
+
unless env.any? {|e| e.root.root == HOME }
|
217
|
+
env.push new(HOME, context)
|
218
|
+
end
|
219
|
+
|
220
|
+
env.activate
|
221
|
+
env
|
222
|
+
end
|
223
|
+
|
224
|
+
# Generates an Env for the specified gem or Gem::Specification. The
|
225
|
+
# gemspec for the gem is used to determine the env configuration in
|
226
|
+
# the following way:
|
227
|
+
#
|
228
|
+
# root: the gem path
|
229
|
+
# gems: all gem dependencies with a config_file
|
230
|
+
# const_paths: the gem require paths
|
231
|
+
# set_const_paths: false (because RubyGems sets them for you)
|
232
|
+
#
|
233
|
+
# Configurations specified in the gem config_file override these
|
234
|
+
# defaults.
|
235
|
+
def setup_gem(gem_name, context=Context.new)
|
236
|
+
spec = Gems.gemspec(gem_name)
|
19
237
|
path = spec.full_gem_path
|
20
|
-
basename = context[:basename]
|
21
238
|
|
239
|
+
# determine gem dependencies that have a config_file;
|
240
|
+
# these will be set as the gems for the new Env
|
22
241
|
dependencies = []
|
23
242
|
spec.dependencies.each do |dependency|
|
24
243
|
unless dependency.type == :runtime
|
@@ -32,8 +251,8 @@ module Tap
|
|
32
251
|
next
|
33
252
|
end
|
34
253
|
|
35
|
-
if
|
36
|
-
next
|
254
|
+
if config_file = context.config_file(gemspec.full_gem_path)
|
255
|
+
next unless File.exists?(config_file)
|
37
256
|
end
|
38
257
|
|
39
258
|
dependencies << gemspec
|
@@ -42,12 +261,14 @@ module Tap
|
|
42
261
|
config = {
|
43
262
|
'root' => path,
|
44
263
|
'gems' => dependencies,
|
45
|
-
'
|
46
|
-
'
|
264
|
+
'const_paths' => spec.require_paths,
|
265
|
+
'set_const_paths' => false
|
47
266
|
}
|
48
267
|
|
49
|
-
|
50
|
-
|
268
|
+
# override the default configs with whatever configs
|
269
|
+
# are specified in the gem config file
|
270
|
+
if config_file = context.config_file(path)
|
271
|
+
config.merge!(load_config(config_file))
|
51
272
|
end
|
52
273
|
|
53
274
|
new(config, context)
|
@@ -55,6 +276,8 @@ module Tap
|
|
55
276
|
|
56
277
|
# Loads configurations from path as YAML. Returns an empty hash if the path
|
57
278
|
# loads to nil or false (as happens for empty files), or doesn't exist.
|
279
|
+
#
|
280
|
+
# Raises a ConfigError if the configurations do not load properly.
|
58
281
|
def load_config(path)
|
59
282
|
return {} unless path
|
60
283
|
|
@@ -64,88 +287,42 @@ module Tap
|
|
64
287
|
raise ConfigError.new($!, path)
|
65
288
|
end
|
66
289
|
end
|
67
|
-
|
68
|
-
def scan_dir(load_path, pattern='**/*.rb')
|
69
|
-
Dir.chdir(load_path) do
|
70
|
-
Dir.glob(pattern).each do |require_path|
|
71
|
-
next unless File.file?(require_path)
|
72
|
-
|
73
|
-
default_const_name = require_path.chomp('.rb').camelize
|
74
|
-
|
75
|
-
# note: the default const name has to be set here to allow for implicit
|
76
|
-
# constant attributes. An error can arise if the same path is globed
|
77
|
-
# from two different dirs... no surefire solution.
|
78
|
-
Lazydoc[require_path].default_const_name = default_const_name
|
79
|
-
|
80
|
-
# scan for constants
|
81
|
-
Lazydoc::Document.scan(File.read(require_path)) do |const_name, type, comment|
|
82
|
-
const_name = default_const_name if const_name.empty?
|
83
|
-
constant = Constant.new(const_name, require_path, comment)
|
84
|
-
yield(type, constant)
|
85
|
-
|
86
|
-
###############################################################
|
87
|
-
# [depreciated] manifest as a task key will be removed at 1.0
|
88
|
-
if type == 'manifest'
|
89
|
-
warn "depreciation: ::task should be used instead of ::manifest as a resource key (#{require_path})"
|
90
|
-
yield('task', constant)
|
91
|
-
end
|
92
|
-
###############################################################
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def scan(path, key='[a-z_]+')
|
99
|
-
Lazydoc::Document.scan(File.read(path), key) do |const_name, type, comment|
|
100
|
-
if const_name.empty?
|
101
|
-
unless const_name = Lazydoc[path].default_const_name
|
102
|
-
raise "could not determine a constant name for #{type} in: #{path.inspect}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
constant = Constant.new(const_name, path, comment)
|
107
|
-
yield(type, constant)
|
108
|
-
|
109
|
-
###############################################################
|
110
|
-
# [depreciated] manifest as a task key will be removed at 1.0
|
111
|
-
if type == 'manifest'
|
112
|
-
warn "depreciation: ::task should be used instead of ::manifest as a resource key (#{require_path})"
|
113
|
-
yield('task', constant)
|
114
|
-
end
|
115
|
-
###############################################################
|
116
|
-
end
|
117
|
-
end
|
118
290
|
end
|
119
|
-
self.instance = nil
|
120
291
|
|
121
|
-
include Enumerable
|
122
292
|
include Configurable
|
293
|
+
include Enumerable
|
123
294
|
include Minimap
|
124
295
|
|
125
|
-
#
|
126
|
-
|
127
|
-
|
128
|
-
#
|
129
|
-
#
|
130
|
-
|
131
|
-
# If the key is not compound, $2 is nil and $1 is the key.
|
132
|
-
COMPOUND_KEY = /^((?:[A-z]:(?:\/|\\))?.*?)(?::(.*))?$/
|
133
|
-
|
296
|
+
# The config file path
|
297
|
+
CONFIG_FILE = "tap.yml"
|
298
|
+
|
299
|
+
# The home directory for Tap
|
300
|
+
HOME = File.expand_path("#{File.dirname(__FILE__)}/../..")
|
301
|
+
|
134
302
|
# An array of nested Envs, by default comprised of the env_path
|
135
|
-
# + gem environments (in that order).
|
303
|
+
# + gem environments (in that order). Envs can be manually set
|
304
|
+
# to override these defaults.
|
136
305
|
attr_reader :envs
|
137
306
|
|
307
|
+
# A Context tracking information shared among a set of envs.
|
138
308
|
attr_reader :context
|
139
309
|
|
140
|
-
attr_reader :manifests
|
141
|
-
|
142
310
|
# The Root directory structure for self.
|
143
|
-
nest(:root, Root, :
|
311
|
+
nest(:root, Root, :init => false)
|
144
312
|
|
145
|
-
# Specify gems to add as nested Envs. Gems may be specified
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
313
|
+
# Specify gems to add as nested Envs. Gems may be specified by name
|
314
|
+
# and/or version, like 'gemname >= 1.2'; by default the latest version
|
315
|
+
# of the gem is selected.
|
316
|
+
#
|
317
|
+
# Several special values also exist:
|
318
|
+
#
|
319
|
+
# :NONE, :none indicates no gems (same as nil, false)
|
320
|
+
# :LATEST the latest version of all gems
|
321
|
+
# :ALL all gems
|
322
|
+
# :latest the latest version of all gems with a config file
|
323
|
+
# :all all gems with a config file
|
324
|
+
#
|
325
|
+
# Gems are not activated by Env.
|
149
326
|
config_attr :gems, [] do |input|
|
150
327
|
input = yaml_load(input) if input.kind_of?(String)
|
151
328
|
|
@@ -156,9 +333,12 @@ module Tap
|
|
156
333
|
# latest and all, no filter
|
157
334
|
Gems.select_gems(input == :LATEST)
|
158
335
|
when :latest, :all
|
159
|
-
# latest and all, filtering by
|
336
|
+
# latest and all, filtering by the existence of a
|
337
|
+
# config file; all gems are selected if no config
|
338
|
+
# file can be determined.
|
160
339
|
Gems.select_gems(input == :latest) do |spec|
|
161
|
-
|
340
|
+
config_file = context.config_file(spec.full_gem_path)
|
341
|
+
config_file == nil || File.exists?(config_file)
|
162
342
|
end
|
163
343
|
else
|
164
344
|
# resolve gem names manually
|
@@ -170,46 +350,45 @@ module Tap
|
|
170
350
|
reset_envs
|
171
351
|
end
|
172
352
|
|
173
|
-
# Specify directories to load as nested Envs.
|
353
|
+
# Specify directories to load as nested Envs. Configurations for the
|
354
|
+
# env are loaded from the config file under dir, if it exists.
|
174
355
|
config_attr :env_paths, [] do |input|
|
175
356
|
@env_paths = resolve_paths(input)
|
176
357
|
reset_envs
|
177
358
|
end
|
178
359
|
|
179
|
-
# Designates
|
180
|
-
#
|
181
|
-
config_attr :
|
182
|
-
raise "
|
183
|
-
@
|
360
|
+
# Designates directories searched for constants. The const_paths are
|
361
|
+
# added to $LOAD_PATH on activation if set_const_paths is specified.
|
362
|
+
config_attr :const_paths, [:lib] do |input|
|
363
|
+
raise "const_paths cannot be modified once active" if active?
|
364
|
+
@const_paths = resolve_paths(input)
|
184
365
|
end
|
185
366
|
|
186
|
-
# If set to true
|
187
|
-
config_attr :
|
188
|
-
raise "
|
189
|
-
@
|
367
|
+
# If set to true const_paths are added to $LOAD_PATH on activation.
|
368
|
+
config_attr :set_const_paths, true do |input|
|
369
|
+
raise "set_const_paths cannot be modified once active" if active?
|
370
|
+
@set_const_paths = Configurable::Validation.boolean[input]
|
190
371
|
end
|
191
372
|
|
192
|
-
# Initializes a new Env linked to the specified directory.
|
193
|
-
#
|
194
|
-
#
|
195
|
-
# load configurations for nested envs.
|
373
|
+
# Initializes a new Env linked to the specified directory. Configurations
|
374
|
+
# for the env will be loaded from the config file (as determined by the
|
375
|
+
# context) if it exists.
|
196
376
|
#
|
197
|
-
#
|
198
|
-
# case,
|
199
|
-
#
|
377
|
+
# A configuration hash may be manually provided in the place of dir. In
|
378
|
+
# that case, no configurations will be loaded, even if the config file
|
379
|
+
# exists.
|
200
380
|
#
|
201
|
-
#
|
202
|
-
#
|
381
|
+
# Context can be specified as a Context, or a Hash used to initialize a
|
382
|
+
# Context.
|
203
383
|
def initialize(config_or_dir=Dir.pwd, context={})
|
204
|
-
@active = false
|
205
|
-
@manifests = {}
|
206
|
-
@context = context
|
207
384
|
|
208
385
|
# setup root
|
209
386
|
config = nil
|
210
387
|
@root = case config_or_dir
|
211
|
-
when Root
|
212
|
-
|
388
|
+
when Root
|
389
|
+
config_or_dir
|
390
|
+
when String
|
391
|
+
Root.new(config_or_dir)
|
213
392
|
else
|
214
393
|
config = config_or_dir
|
215
394
|
|
@@ -221,24 +400,28 @@ module Tap
|
|
221
400
|
root.kind_of?(Root) ? root : Root.new(root)
|
222
401
|
end
|
223
402
|
|
224
|
-
|
225
|
-
|
226
|
-
|
403
|
+
# note registration requires root.root, and so the
|
404
|
+
# setup of context must follow the setup of root.
|
405
|
+
@context = case context
|
406
|
+
when Context
|
407
|
+
context
|
408
|
+
when Hash
|
409
|
+
Context.new(context)
|
410
|
+
else raise "cannot convert #{context.inspect} to Tap::Env::Context"
|
411
|
+
end
|
412
|
+
@context.register(self)
|
227
413
|
|
228
|
-
|
229
|
-
|
230
|
-
end
|
231
|
-
instances << self
|
232
|
-
|
233
|
-
# set these for reset_env
|
414
|
+
# these need to be set for reset_env
|
415
|
+
@active = false
|
234
416
|
@gems = nil
|
235
417
|
@env_paths = nil
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
418
|
+
|
419
|
+
# only load configurations if configs were not provided
|
420
|
+
config ||= Env.load_config(@context.config_file(@root.root))
|
421
|
+
initialize_config(config)
|
422
|
+
|
423
|
+
# set the invert flag
|
424
|
+
@invert = false
|
242
425
|
end
|
243
426
|
|
244
427
|
# Sets envs removing duplicates and instances of self. Setting envs
|
@@ -265,6 +448,7 @@ module Tap
|
|
265
448
|
end
|
266
449
|
self
|
267
450
|
end
|
451
|
+
alias_method :<<, :push
|
268
452
|
|
269
453
|
# Passes each nested env to the block in order, starting with self.
|
270
454
|
def each
|
@@ -306,33 +490,29 @@ module Tap
|
|
306
490
|
|
307
491
|
# Activates self by doing the following, in order:
|
308
492
|
#
|
309
|
-
# * sets Env.instance to self (unless already set)
|
310
493
|
# * activate nested environments
|
311
|
-
# * unshift
|
494
|
+
# * unshift const_paths to $LOAD_PATH (if set_const_paths is true)
|
312
495
|
#
|
313
|
-
# Once active, the current envs and
|
496
|
+
# Once active, the current envs and const_paths are frozen and cannot be
|
314
497
|
# modified until deactivated. Returns true if activate succeeded, or
|
315
498
|
# false if self is already active.
|
316
499
|
def activate
|
317
500
|
return false if active?
|
318
501
|
|
319
502
|
@active = true
|
320
|
-
unless self.class.instance(false)
|
321
|
-
self.class.instance = self
|
322
|
-
end
|
323
503
|
|
324
|
-
# freeze envs and
|
504
|
+
# freeze envs and const paths
|
325
505
|
@envs.freeze
|
326
|
-
@
|
506
|
+
@const_paths.freeze
|
327
507
|
|
328
508
|
# activate nested envs
|
329
509
|
envs.reverse_each do |env|
|
330
510
|
env.activate
|
331
511
|
end
|
332
512
|
|
333
|
-
# add
|
334
|
-
if
|
335
|
-
|
513
|
+
# add const paths
|
514
|
+
if set_const_paths
|
515
|
+
const_paths.reverse_each do |path|
|
336
516
|
$LOAD_PATH.unshift(path)
|
337
517
|
end
|
338
518
|
|
@@ -345,12 +525,19 @@ module Tap
|
|
345
525
|
# Deactivates self by doing the following in order:
|
346
526
|
#
|
347
527
|
# * deactivates nested environments
|
348
|
-
# * removes
|
349
|
-
# * sets Env.instance to nil (if set to self)
|
350
|
-
# * clears cached manifest data
|
528
|
+
# * removes const_paths from $LOAD_PATH (if set_const_paths is true)
|
351
529
|
#
|
352
|
-
# Once deactivated, envs and
|
530
|
+
# Once deactivated, envs and const_paths are unfrozen and may be modified.
|
353
531
|
# Returns true if deactivate succeeded, or false if self is not active.
|
532
|
+
#
|
533
|
+
# ==== Note
|
534
|
+
#
|
535
|
+
# Deactivation does not necessarily leave $LOAD_PATH in the same condition
|
536
|
+
# as before activation. A pre-existing $LOAD_PATH entry can go missing if
|
537
|
+
# it is also registered as an env load_path (deactivation doesn't know to
|
538
|
+
# leave such paths alone).
|
539
|
+
#
|
540
|
+
# Deactivation, like constant unloading should be done with caution.
|
354
541
|
def deactivate
|
355
542
|
return false unless active?
|
356
543
|
@active = false
|
@@ -360,20 +547,14 @@ module Tap
|
|
360
547
|
env.deactivate
|
361
548
|
end
|
362
549
|
|
363
|
-
# remove
|
364
|
-
|
550
|
+
# remove const paths
|
551
|
+
const_paths.each do |path|
|
365
552
|
$LOAD_PATH.delete(path)
|
366
|
-
end if
|
553
|
+
end if set_const_paths
|
367
554
|
|
368
|
-
# unfreeze envs and
|
555
|
+
# unfreeze envs and const paths
|
369
556
|
@envs = @envs.dup
|
370
|
-
@
|
371
|
-
|
372
|
-
# clear cached data
|
373
|
-
klass = self.class
|
374
|
-
if klass.instance(false) == self
|
375
|
-
klass.instance = nil
|
376
|
-
end
|
557
|
+
@const_paths = @const_paths.dup
|
377
558
|
|
378
559
|
true
|
379
560
|
end
|
@@ -383,6 +564,16 @@ module Tap
|
|
383
564
|
@active
|
384
565
|
end
|
385
566
|
|
567
|
+
# Globs the abstract directory for files in the specified directory alias,
|
568
|
+
# matching the pattern. The expanded path of each matching file is
|
569
|
+
# returned.
|
570
|
+
def glob(dir, pattern="**/*")
|
571
|
+
hlob(dir, pattern).values.sort!
|
572
|
+
end
|
573
|
+
|
574
|
+
# Same as glob but returns results as a hash of (relative_path, path)
|
575
|
+
# pairs. In short the hash defines matching files in the abstract
|
576
|
+
# directory, linked to the actual path for these files.
|
386
577
|
def hlob(dir, pattern="**/*")
|
387
578
|
results = {}
|
388
579
|
each do |env|
|
@@ -395,11 +586,11 @@ module Tap
|
|
395
586
|
results
|
396
587
|
end
|
397
588
|
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
def path(dir, *paths)
|
589
|
+
# Returns the path to the specified file, as determined by root.
|
590
|
+
#
|
591
|
+
# If a block is given, a path for each env will be yielded until the block
|
592
|
+
# returns a true value. Returns nil if the block never returns true.
|
593
|
+
def path(dir = :root, *paths)
|
403
594
|
each do |env|
|
404
595
|
path = env.root.path(dir, *paths)
|
405
596
|
return path if !block_given? || yield(path)
|
@@ -413,13 +604,12 @@ module Tap
|
|
413
604
|
#
|
414
605
|
# path(dir, module_path, *paths)
|
415
606
|
#
|
416
|
-
# By default
|
607
|
+
# By default 'module_path' is 'module.to_s.underscore' but modules can
|
417
608
|
# specify an alternative by providing a module_path method.
|
418
609
|
#
|
419
|
-
#
|
420
|
-
# the path
|
421
|
-
# is returned. Returns nil if the block never returns true.
|
422
|
-
#
|
610
|
+
# Paths are yielded to the block until the block returns true, at which
|
611
|
+
# point the current the path is returned. If no block is given, the
|
612
|
+
# first path is returned. Returns nil if the block never returns true.
|
423
613
|
def module_path(dir, modules, *paths, &block)
|
424
614
|
paths.compact!
|
425
615
|
while current = modules.shift
|
@@ -446,111 +636,119 @@ module Tap
|
|
446
636
|
module_path(dir, superclasses, *paths, &block)
|
447
637
|
end
|
448
638
|
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
639
|
+
# Generates a Manifest for self using the block as a builder. The builder
|
640
|
+
# receives an env and should return an array of resources, each of which
|
641
|
+
# can be minimappped. Minimapping requires that the resource is either
|
642
|
+
# a path string, or provides a 'path' method that returns a path string.
|
643
|
+
# Alternatively, a Minimap may be returned.
|
644
|
+
#
|
645
|
+
# If a type is specified, then the manifest cache will be linked to the
|
646
|
+
# context cache.
|
647
|
+
def manifest(type=nil, &block) # :yields: env
|
648
|
+
cache = type ? (context.cache[type] ||= {}) : {}
|
649
|
+
Manifest.new(self, block, cache)
|
650
|
+
end
|
651
|
+
|
652
|
+
# Returns a manifest of Constants located in .rb files under each of the
|
653
|
+
# const_paths. Constants are identified using Lazydoc constant attributes;
|
654
|
+
# all attributes are registered to the constants for classification
|
655
|
+
# (for example as a task, join, etc).
|
656
|
+
def constants
|
657
|
+
@constants ||= manifest(:constants) do |env|
|
658
|
+
constants = {}
|
659
|
+
|
660
|
+
env.const_paths.each do |load_path|
|
457
661
|
next unless File.directory?(load_path)
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
662
|
+
Constant.scan(load_path, "**/*.rb", constants)
|
663
|
+
end
|
664
|
+
|
665
|
+
constants.keys.sort!.collect! do |key|
|
666
|
+
constants[key]
|
462
667
|
end
|
463
|
-
|
464
|
-
registry
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
def register(type, override=false, &block)
|
469
|
-
type = type.to_sym
|
470
|
-
|
471
|
-
# error for existing, or overwrite
|
472
|
-
case
|
473
|
-
when override
|
474
|
-
builders.delete(type)
|
475
|
-
registries.each {|root, registry| registry.delete(type) }
|
476
|
-
when builders.has_key?(type)
|
477
|
-
raise "a builder is already registered for: #{type.inspect}"
|
478
|
-
when registries.any? {|root, registry| registry.has_key?(type) }
|
479
|
-
raise "entries are already registered for: #{type.inspect}"
|
480
668
|
end
|
481
|
-
|
482
|
-
builders[type] = block
|
483
669
|
end
|
484
670
|
|
485
|
-
|
486
|
-
#
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
671
|
+
# Seeks a constant for the key, constantizing if necessary. If invert is
|
672
|
+
# true, this method seeks and returns a key for the input constant. In
|
673
|
+
# both cases AGET returns nil if no key-constant pair can be found.
|
674
|
+
def [](key, invert=invert?)
|
675
|
+
if invert
|
676
|
+
const_name = key.to_s
|
677
|
+
constants.unseek(true) do |const|
|
678
|
+
const_name == const.const_name
|
679
|
+
end
|
680
|
+
else
|
681
|
+
if constant = constants.seek(key)
|
682
|
+
constant.constantize
|
683
|
+
else
|
684
|
+
nil
|
685
|
+
end
|
491
686
|
end
|
492
687
|
end
|
493
688
|
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
builder = builders[type]
|
499
|
-
builder ? builder.call(self) : []
|
500
|
-
end
|
501
|
-
|
502
|
-
manifests[type] ||= Manifest.new(self, type)
|
689
|
+
# Indicates AGET looks up constants from keys (false), or keys from
|
690
|
+
# constants (true).
|
691
|
+
def invert?
|
692
|
+
@invert
|
503
693
|
end
|
504
694
|
|
505
|
-
|
506
|
-
|
695
|
+
# Inverts the AGET lookup for self.
|
696
|
+
def invert!
|
697
|
+
@invert = !@invert
|
698
|
+
self
|
507
699
|
end
|
508
700
|
|
509
|
-
|
510
|
-
|
511
|
-
|
701
|
+
# Returns a duplicate of self with inverted AGET lookup.
|
702
|
+
def invert
|
703
|
+
dup.invert!
|
512
704
|
end
|
513
705
|
|
514
|
-
#
|
515
|
-
#
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
each do |env|
|
542
|
-
manifest = env.manifest(type)
|
543
|
-
if value = manifest.find(&block)
|
544
|
-
key = manifest.minihash(true)[value]
|
545
|
-
return key_only ? key : "#{minihash(true)[env]}:#{key}"
|
546
|
-
end
|
706
|
+
# Scans the files matched under the directory and pattern for constants
|
707
|
+
# and adds them to the existing constants for self.
|
708
|
+
def scan(dir, pattern="**/*.rb")
|
709
|
+
new_entries = {}
|
710
|
+
entries = constants.entries(self)
|
711
|
+
entries.each {|const| new_entries[const.const_name] = const }
|
712
|
+
|
713
|
+
Constant.scan(root[dir], pattern, new_entries)
|
714
|
+
|
715
|
+
entries.replace(new_entries.keys)
|
716
|
+
entries.sort!.collect! {|key| new_entries[key] }
|
717
|
+
entries
|
718
|
+
end
|
719
|
+
|
720
|
+
# Registers a constant with self. The constant is stored as a new
|
721
|
+
# Constant in the constants manifest. Returns the new Constant.
|
722
|
+
# If the constant is already registered, the existing Constant is
|
723
|
+
# returned.
|
724
|
+
def register(constant)
|
725
|
+
const_name = constant.to_s
|
726
|
+
entries = constants.entries(self)
|
727
|
+
|
728
|
+
# try to find the existing Constant before making a new constant
|
729
|
+
unless constant = entries.find {|const| const.const_name == const_name}
|
730
|
+
constant = Constant.new(const_name)
|
731
|
+
entries << constant
|
732
|
+
entries.replace entries.sort_by {|const| const.const_name }
|
547
733
|
end
|
548
|
-
|
549
|
-
|
734
|
+
|
735
|
+
constant
|
550
736
|
end
|
551
737
|
|
552
|
-
#
|
553
|
-
#
|
738
|
+
# When no template is specified, inspect generates a fairly standard
|
739
|
+
# inspection string. When a template is provided, inspect builds a
|
740
|
+
# Templater for each env with the following local variables:
|
741
|
+
#
|
742
|
+
# variable value
|
743
|
+
# env the current env
|
744
|
+
# env_keys a minihash for all envs
|
745
|
+
#
|
746
|
+
# If a block is given, the globals and templater are yielded before
|
747
|
+
# any templater is built; this allows each env to add env-specific
|
748
|
+
# variables. After this preparation, each templater is built with
|
749
|
+
# the globals and the results concatenated.
|
750
|
+
#
|
751
|
+
# The template is built with filename, if specified (for debugging).
|
554
752
|
def inspect(template=nil, globals={}, filename=nil) # :yields: templater, globals
|
555
753
|
if template == nil
|
556
754
|
return "#<#{self.class}:#{object_id} root='#{root.root}'>"
|
@@ -565,27 +763,13 @@ module Tap
|
|
565
763
|
templater.build(globals, filename)
|
566
764
|
end.join
|
567
765
|
end
|
568
|
-
|
766
|
+
|
569
767
|
protected
|
570
768
|
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
def basename # :nodoc:
|
576
|
-
context[:basename]
|
577
|
-
end
|
578
|
-
|
579
|
-
def builders # :nodoc:
|
580
|
-
context[:builders] ||= {}
|
581
|
-
end
|
582
|
-
|
583
|
-
def instances # :nodoc:
|
584
|
-
context[:instances] ||= []
|
585
|
-
end
|
586
|
-
|
587
|
-
def instance(path) # :nodoc:
|
588
|
-
instances.find {|env| env.root.root == path }
|
769
|
+
# helper for Minimap; note that specifying env.root.root via path
|
770
|
+
# is not possible because path is required for other purposes.
|
771
|
+
def entry_to_path(env) # :nodoc:
|
772
|
+
env.root.root
|
589
773
|
end
|
590
774
|
|
591
775
|
# resets envs using the current env_paths and gems. does nothing
|
@@ -593,15 +777,15 @@ module Tap
|
|
593
777
|
def reset_envs # :nodoc:
|
594
778
|
if env_paths && gems
|
595
779
|
self.envs = env_paths.collect do |path|
|
596
|
-
instance(path) || Env.new(path, context)
|
780
|
+
context.instance(path) || Env.new(path, context)
|
597
781
|
end + gems.collect do |spec|
|
598
|
-
instance(spec.full_gem_path) || Env.
|
782
|
+
context.instance(spec.full_gem_path) || Env.setup_gem(spec, context)
|
599
783
|
end
|
600
784
|
end
|
601
785
|
end
|
602
786
|
|
603
|
-
# arrayifies, compacts, and resolves input paths using root
|
604
|
-
# removes duplicates. in short:
|
787
|
+
# arrayifies, compacts, and resolves input paths using root.
|
788
|
+
# also removes duplicates. in short:
|
605
789
|
#
|
606
790
|
# resolve_paths ['lib', nil, 'lib', 'alt] # => [root['lib'], root['alt']]
|
607
791
|
#
|