tap 0.9.1 → 0.10.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 +37 -30
- data/MIT-LICENSE +1 -1
- data/README +92 -44
- data/bin/tap +62 -75
- data/cmd/console.rb +42 -0
- data/cmd/destroy.rb +16 -0
- data/cmd/generate.rb +16 -0
- data/cmd/run.rb +126 -0
- data/doc/Class Reference +362 -0
- data/doc/Command Reference +153 -0
- data/doc/Tutorial +237 -0
- data/lib/tap.rb +6 -45
- data/lib/tap/app.rb +126 -500
- data/lib/tap/constants.rb +2 -29
- data/lib/tap/env.rb +555 -250
- data/lib/tap/file_task.rb +60 -103
- data/lib/tap/generator/base.rb +109 -0
- data/lib/tap/generator/destroy.rb +37 -0
- data/lib/tap/generator/generate.rb +61 -0
- data/lib/tap/generator/generators/command/command_generator.rb +16 -12
- data/lib/tap/generator/generators/command/templates/command.erb +13 -19
- data/lib/tap/generator/generators/config/config_generator.rb +18 -27
- data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
- data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
- data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
- data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
- data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
- data/lib/tap/generator/generators/root/root_generator.rb +45 -31
- data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
- data/lib/tap/generator/generators/root/templates/gemspec +27 -0
- data/lib/tap/generator/generators/root/templates/tapfile +8 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
- data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
- data/lib/tap/generator/generators/task/task_generator.rb +21 -28
- data/lib/tap/generator/generators/task/templates/task.erb +13 -23
- data/lib/tap/generator/generators/task/templates/test.erb +15 -18
- data/lib/tap/generator/manifest.rb +14 -0
- data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
- data/lib/tap/patches/rake/testtask.rb +0 -0
- data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
- data/lib/tap/patches/ruby19/parsedate.rb +0 -0
- data/lib/tap/root.rb +260 -21
- data/lib/tap/support/aggregator.rb +11 -11
- data/lib/tap/support/assignments.rb +172 -0
- data/lib/tap/support/audit.rb +20 -18
- data/lib/tap/support/batchable.rb +21 -10
- data/lib/tap/support/batchable_class.rb +107 -0
- data/lib/tap/support/class_configuration.rb +154 -239
- data/lib/tap/support/command_line.rb +97 -102
- data/lib/tap/support/comment.rb +270 -0
- data/lib/tap/support/configurable.rb +86 -65
- data/lib/tap/support/configurable_class.rb +296 -0
- data/lib/tap/support/configuration.rb +122 -0
- data/lib/tap/support/constant.rb +70 -0
- data/lib/tap/support/constant_utils.rb +127 -0
- data/lib/tap/support/declarations.rb +111 -0
- data/lib/tap/support/executable.rb +30 -17
- data/lib/tap/support/executable_queue.rb +0 -0
- data/lib/tap/support/framework.rb +71 -0
- data/lib/tap/support/framework_class.rb +199 -0
- data/lib/tap/support/instance_configuration.rb +147 -0
- data/lib/tap/support/lazydoc.rb +428 -0
- data/lib/tap/support/manifest.rb +89 -0
- data/lib/tap/support/run_error.rb +0 -0
- data/lib/tap/support/shell_utils.rb +33 -9
- data/lib/tap/support/summary.rb +30 -0
- data/lib/tap/support/tdoc.rb +339 -134
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
- data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
- data/lib/tap/support/templater.rb +180 -0
- data/lib/tap/support/validation.rb +409 -76
- data/lib/tap/support/versions.rb +5 -3
- data/lib/tap/task.rb +78 -174
- data/lib/tap/tasks/dump.rb +56 -0
- data/lib/tap/tasks/rake.rb +93 -0
- data/lib/tap/test.rb +3 -3
- data/lib/tap/test/env_vars.rb +2 -2
- data/lib/tap/test/file_methods.rb +19 -20
- data/lib/tap/test/script_methods.rb +144 -0
- data/lib/tap/test/subset_methods.rb +1 -1
- data/lib/tap/test/tap_methods.rb +28 -62
- data/lib/tap/workflow.rb +22 -39
- metadata +48 -179
- data/Basic Overview +0 -151
- data/Command Reference +0 -99
- data/Rakefile +0 -127
- data/Tutorial +0 -287
- data/lib/tap/cmd/console.rb +0 -31
- data/lib/tap/cmd/destroy.rb +0 -20
- data/lib/tap/cmd/generate.rb +0 -20
- data/lib/tap/cmd/run.rb +0 -151
- data/lib/tap/dump.rb +0 -57
- data/lib/tap/generator.rb +0 -91
- data/lib/tap/generator/generators/command/USAGE +0 -6
- data/lib/tap/generator/generators/config/USAGE +0 -21
- data/lib/tap/generator/generators/config/templates/config.erb +0 -1
- data/lib/tap/generator/generators/file_task/USAGE +0 -3
- data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
- data/lib/tap/generator/generators/generator/USAGE +0 -0
- data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
- data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
- data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
- data/lib/tap/generator/generators/root/USAGE +0 -0
- data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
- data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
- data/lib/tap/generator/generators/task/USAGE +0 -3
- data/lib/tap/generator/generators/workflow/USAGE +0 -0
- data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
- data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
- data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
- data/lib/tap/generator/options.rb +0 -26
- data/lib/tap/generator/usage.rb +0 -26
- data/lib/tap/support/batchable_methods.rb +0 -34
- data/lib/tap/support/command_line_methods.rb +0 -76
- data/lib/tap/support/configurable_methods.rb +0 -224
- data/lib/tap/support/logger.rb +0 -88
- data/lib/tap/support/rake.rb +0 -43
- data/lib/tap/support/tdoc/config_attr.rb +0 -362
- data/test/app/config/another/task.yml +0 -1
- data/test/app/config/batch.yml +0 -2
- data/test/app/config/empty.yml +0 -0
- data/test/app/config/erb.yml +0 -2
- data/test/app/config/some/task.yml +0 -1
- data/test/app/config/template.yml +0 -2
- data/test/app/config/version-0.1.yml +0 -1
- data/test/app/config/version.yml +0 -1
- data/test/app/lib/app_test_task.rb +0 -3
- data/test/app_test.rb +0 -1849
- data/test/env/test_configure/recurse_a.yml +0 -2
- data/test/env/test_configure/recurse_b.yml +0 -2
- data/test/env/test_configure/tap.yml +0 -23
- data/test/env/test_load_env_config/dir/tap.yml +0 -3
- data/test/env/test_load_env_config/recurse_a.yml +0 -2
- data/test/env/test_load_env_config/recurse_b.yml +0 -2
- data/test/env/test_load_env_config/tap.yml +0 -3
- data/test/env_test.rb +0 -198
- data/test/file_task/config/batch.yml +0 -2
- data/test/file_task/config/configured.yml +0 -1
- data/test/file_task/old_file_one.txt +0 -0
- data/test/file_task/old_file_two.txt +0 -0
- data/test/file_task_test.rb +0 -1291
- data/test/root/alt_lib/alt_module.rb +0 -4
- data/test/root/file.txt +0 -0
- data/test/root/glob/one.txt +0 -0
- data/test/root/glob/two.txt +0 -0
- data/test/root/lib/absolute_alt_filepath.rb +0 -2
- data/test/root/lib/alternative_filepath.rb +0 -2
- data/test/root/lib/another_module.rb +0 -2
- data/test/root/lib/nested/some_module.rb +0 -4
- data/test/root/lib/no_module_included.rb +0 -0
- data/test/root/lib/some/module.rb +0 -4
- data/test/root/lib/some_class.rb +0 -2
- data/test/root/lib/some_module.rb +0 -3
- data/test/root/load_path/load_path_module.rb +0 -2
- data/test/root/load_path/skip_module.rb +0 -2
- data/test/root/mtime/older.txt +0 -0
- data/test/root/unload/full_path.rb +0 -2
- data/test/root/unload/loaded_by_nested.rb +0 -2
- data/test/root/unload/nested/nested_load.rb +0 -6
- data/test/root/unload/nested/nested_with_ext.rb +0 -4
- data/test/root/unload/nested/relative_path.rb +0 -4
- data/test/root/unload/older.rb +0 -2
- data/test/root/unload/unload_base.rb +0 -9
- data/test/root/versions/another.yml +0 -0
- data/test/root/versions/file-0.1.2.yml +0 -0
- data/test/root/versions/file-0.1.yml +0 -0
- data/test/root/versions/file.yml +0 -0
- data/test/root_test.rb +0 -718
- data/test/support/aggregator_test.rb +0 -99
- data/test/support/audit_test.rb +0 -445
- data/test/support/batchable_test.rb +0 -74
- data/test/support/class_configuration_test.rb +0 -331
- data/test/support/command_line_test.rb +0 -58
- data/test/support/configurable/config/configured.yml +0 -2
- data/test/support/configurable_test.rb +0 -295
- data/test/support/executable_queue_test.rb +0 -103
- data/test/support/executable_test.rb +0 -38
- data/test/support/logger_test.rb +0 -31
- data/test/support/rake_test.rb +0 -37
- data/test/support/shell_utils_test.rb +0 -24
- data/test/support/tdoc_test.rb +0 -370
- data/test/support/validation_test.rb +0 -54
- data/test/support/versions_test.rb +0 -103
- data/test/tap_test_helper.rb +0 -57
- data/test/tap_test_suite.rb +0 -7
- data/test/task/config/batch.yml +0 -2
- data/test/task/config/batched.yml +0 -2
- data/test/task/config/configured.yml +0 -1
- data/test/task/config/example.yml +0 -1
- data/test/task_base_test.rb +0 -24
- data/test/task_syntax_test.rb +0 -300
- data/test/task_test.rb +0 -320
- data/test/test/env_vars_test.rb +0 -48
- data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
- data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
- data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
- data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
- data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
- data/test/test/file_methods_doc_test.rb +0 -29
- data/test/test/file_methods_test.rb +0 -275
- data/test/test/subset_methods_test.rb +0 -171
- data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
- data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
- data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
- data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
- data/test/test/tap_methods_test.rb +0 -399
- data/test/workflow_test.rb +0 -120
- data/vendor/rails_generator.rb +0 -56
- data/vendor/rails_generator/base.rb +0 -263
- data/vendor/rails_generator/commands.rb +0 -581
- data/vendor/rails_generator/generated_attribute.rb +0 -42
- data/vendor/rails_generator/lookup.rb +0 -209
- data/vendor/rails_generator/manifest.rb +0 -53
- data/vendor/rails_generator/options.rb +0 -143
- data/vendor/rails_generator/scripts.rb +0 -83
- data/vendor/rails_generator/scripts/destroy.rb +0 -7
- data/vendor/rails_generator/scripts/generate.rb +0 -7
- data/vendor/rails_generator/scripts/update.rb +0 -12
- data/vendor/rails_generator/simple_logger.rb +0 -46
- data/vendor/rails_generator/spec.rb +0 -44
data/lib/tap/constants.rb
CHANGED
|
@@ -1,35 +1,8 @@
|
|
|
1
1
|
module Tap
|
|
2
2
|
MAJOR = 0
|
|
3
|
-
MINOR =
|
|
4
|
-
TINY =
|
|
3
|
+
MINOR = 10
|
|
4
|
+
TINY = 0
|
|
5
5
|
|
|
6
6
|
VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
|
|
7
7
|
WEBSITE="http://tap.rubyforge.org"
|
|
8
|
-
|
|
9
|
-
# Under Construction
|
|
10
|
-
module Constants
|
|
11
|
-
def try_constantize
|
|
12
|
-
begin
|
|
13
|
-
constantize
|
|
14
|
-
rescue(NameError)
|
|
15
|
-
yield
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def constants_split
|
|
20
|
-
camel_cased_word = camelize
|
|
21
|
-
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
|
22
|
-
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
constants = $1.split(/::/)
|
|
26
|
-
current = Object
|
|
27
|
-
while !constants.empty?
|
|
28
|
-
break unless current.const_defined?(constants[0])
|
|
29
|
-
current = current.const_get(constants.shift)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
[current, constants]
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
8
|
end
|
data/lib/tap/env.rb
CHANGED
|
@@ -1,213 +1,386 @@
|
|
|
1
1
|
require 'tap/root'
|
|
2
|
-
require '
|
|
3
|
-
|
|
2
|
+
require 'tap/support/constant'
|
|
3
|
+
require 'tap/support/summary'
|
|
4
|
+
require 'tap/support/manifest'
|
|
4
5
|
|
|
5
6
|
module Tap
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# specification of gems that should be available through the tap command.
|
|
8
|
+
#--
|
|
9
|
+
# Note that gems and env_paths reset envs -- custom modifications to envs will be lost
|
|
10
|
+
# whenever these configs are reset.
|
|
11
11
|
class Env
|
|
12
|
+
include Support::Configurable
|
|
13
|
+
include Enumerable
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
@@instance = nil
|
|
16
|
+
@@instances = {}
|
|
17
|
+
@@manifests = {}
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
# Returns the active instance of Env.
|
|
21
|
+
def instance
|
|
22
|
+
@@instance
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# A hash of (path, Env instance) pairs, generated by Env#instantiate. Used
|
|
26
|
+
# to prevent infinite loops of Env dependencies by assigning a single Env
|
|
27
|
+
# to a given path.
|
|
28
|
+
def instances
|
|
29
|
+
@@instances
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Creates a new Env for the specified path and adds it to Env#instances, or
|
|
33
|
+
# returns the existing instance for the path. Paths can point to an env config
|
|
34
|
+
# file, or to a directory. If a directory is provided, instantiate treats
|
|
35
|
+
# path as the DEFAULT_CONFIG_FILE in that directory. All paths are expanded.
|
|
36
|
+
#
|
|
37
|
+
# e1 = Env.instantiate("./path/to/config.yml")
|
|
38
|
+
# e2 = Env.instantiate("./path/to/dir")
|
|
39
|
+
#
|
|
40
|
+
# Env.instances
|
|
41
|
+
# # => {
|
|
42
|
+
# # File.expand_path("./path/to/config.yml") => e1,
|
|
43
|
+
# # File.expand_path("./path/to/dir/#{Tap::Env::DEFAULT_CONFIG_FILE}") => e2 }
|
|
44
|
+
#
|
|
45
|
+
# The Env is initialized using configurations read from the env config file using
|
|
46
|
+
# load_config, and a Root initialized to the config file directory. An instance
|
|
47
|
+
# will be initialized regardless of whether the config file or directory exists.
|
|
48
|
+
def instantiate(path_or_root, default_config={}, logger=nil)
|
|
49
|
+
path = path_or_root.kind_of?(Root) ? path_or_root.root : path_or_root
|
|
50
|
+
path = pathify(path)
|
|
25
51
|
|
|
26
|
-
|
|
27
|
-
|
|
52
|
+
begin
|
|
53
|
+
root = path_or_root.kind_of?(Root) ? path_or_root : Root.new(File.dirname(path))
|
|
54
|
+
config = default_config.merge(load_config(path))
|
|
55
|
+
|
|
56
|
+
# note the assignment of env to instances MUST occur before
|
|
57
|
+
# reconfigure to prevent infinite looping
|
|
58
|
+
(instances[path] = Env.new({}, root, logger)).reconfigure(config) do |unhandled_configs|
|
|
59
|
+
yield(unhandled_configs) if block_given?
|
|
60
|
+
end
|
|
61
|
+
rescue(Exception)
|
|
62
|
+
raise Env::ConfigError.new($!, path)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
28
65
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
else
|
|
33
|
-
raise "expected hash from config file: #{filepath}"
|
|
66
|
+
def pathify(path)
|
|
67
|
+
if File.directory?(path) || (!File.exists?(path) && File.extname(path) == "")
|
|
68
|
+
path = File.join(path, DEFAULT_CONFIG_FILE)
|
|
34
69
|
end
|
|
70
|
+
File.expand_path(path)
|
|
35
71
|
end
|
|
36
72
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def partition_configs(hash, *sets)
|
|
42
|
-
partitions = Array.new(sets.length + 1) { Hash.new }
|
|
73
|
+
def instance_for(path)
|
|
74
|
+
path = pathify(path)
|
|
75
|
+
instances.has_key?(path) ? instances[path] : instantiate(path)
|
|
76
|
+
end
|
|
43
77
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
78
|
+
# Returns the gemspec for the specified gem. A gem version
|
|
79
|
+
# can be specified in the name, like 'gem >= 1.2'. The gem
|
|
80
|
+
# will be activated using +gem+ if necessary.
|
|
81
|
+
def gemspec(gem_name)
|
|
82
|
+
return gem_name if gem_name.kind_of?(Gem::Specification)
|
|
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 }
|
|
103
|
+
|
|
104
|
+
index.select do |spec|
|
|
105
|
+
File.exists?(File.join(spec.full_gem_path, DEFAULT_CONFIG_FILE)) ||
|
|
106
|
+
File.exists?(File.join(spec.full_gem_path, DEFAULT_TASK_FILE))
|
|
107
|
+
end.sort
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
protected
|
|
111
|
+
|
|
112
|
+
# Defines a config that raises an error if set when the
|
|
113
|
+
# instance is active. static_config MUST take a block
|
|
114
|
+
# and raises an error if a block is not given.
|
|
115
|
+
def static_config(key, value=nil, &block)
|
|
116
|
+
raise ArgumentError.new("active config requires block") unless block_given?
|
|
117
|
+
|
|
118
|
+
instance_variable = "@#{key}".to_sym
|
|
119
|
+
config_attr(key, value) do |input|
|
|
120
|
+
check_configurable
|
|
121
|
+
instance_variable_set(instance_variable, block.call(input))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Defines a config that collects the input into a unique,
|
|
126
|
+
# compact array where each member has been resolved using
|
|
127
|
+
# root[]. In short, ['lib', nil, 'lib', 'alt] becomes
|
|
128
|
+
# [root['lib'], root['alt']].
|
|
129
|
+
#
|
|
130
|
+
# Single and nil arguments are allowed; they are arrayified
|
|
131
|
+
# and handled as above. Path configs raise an error if
|
|
132
|
+
# modified when the instance is active.
|
|
133
|
+
def path_config(key, value=[])
|
|
134
|
+
instance_variable = "@#{key}".to_sym
|
|
135
|
+
config_attr(key, value) do |input|
|
|
136
|
+
check_configurable
|
|
137
|
+
instance_variable_set(instance_variable, [*input].compact.collect {|path| root[path]}.uniq)
|
|
52
138
|
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
#--
|
|
142
|
+
# To manifest simply requires an glob_<name> method which
|
|
143
|
+
# yields each (key, path) pair for the manifested object in
|
|
144
|
+
# a predictable order.
|
|
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?
|
|
53
156
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
values = [values] unless values.kind_of?(Array)
|
|
66
|
-
(merge[key] ||= []).concat(values)
|
|
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)}
|
|
67
168
|
end
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
map_method = Support::Manifest.map_method(name)
|
|
172
|
+
define_method(map_method, &block)
|
|
173
|
+
|
|
174
|
+
protected glob_method, map_method
|
|
71
175
|
end
|
|
72
176
|
end
|
|
73
177
|
|
|
74
|
-
|
|
75
|
-
|
|
178
|
+
# The global config file path
|
|
179
|
+
GLOBAL_CONFIG_FILE = File.join(Gem.user_home, ".tap.yml")
|
|
76
180
|
|
|
181
|
+
# The default config file path
|
|
77
182
|
DEFAULT_CONFIG_FILE = "tap.yml"
|
|
78
183
|
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"generator_paths" => ["lib/generators"]
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
attr_reader :config
|
|
184
|
+
# The default task file path
|
|
185
|
+
DEFAULT_TASK_FILE = "tapfile.rb"
|
|
186
|
+
|
|
187
|
+
# The Root directory structure for self.
|
|
188
|
+
attr_reader :root
|
|
189
|
+
|
|
190
|
+
# Gets or sets the logger for self
|
|
90
191
|
attr_accessor :logger
|
|
192
|
+
|
|
193
|
+
# A hash of the manifests for self.
|
|
194
|
+
attr_reader :manifests
|
|
195
|
+
|
|
196
|
+
# Specify gems to load as nested Envs. Gems may be specified
|
|
197
|
+
# by name and/or version, like 'gemname >= 1.2'; by default the
|
|
198
|
+
# latest version of the gem is selected.
|
|
199
|
+
#
|
|
200
|
+
# Gems are immediately loaded (via gem) through this method.
|
|
201
|
+
#--
|
|
202
|
+
# Note that the gems are resolved to gemspecs using Env.gemspec,
|
|
203
|
+
# so self.gems returns an array of gemspecs.
|
|
204
|
+
config_attr :gems, [] do |input|
|
|
205
|
+
check_configurable
|
|
206
|
+
@gems = [*input].compact.collect do |gem_name|
|
|
207
|
+
spec = Env.gemspec(gem_name)
|
|
208
|
+
|
|
209
|
+
case spec
|
|
210
|
+
when nil then log(:warn, "unknown gem: #{gem_name}", Logger::WARN)
|
|
211
|
+
else Env.instance_for(spec.full_gem_path)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
spec
|
|
215
|
+
end.uniq
|
|
216
|
+
reset_envs
|
|
217
|
+
end
|
|
91
218
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
219
|
+
# Specify configuration files to load as nested Envs.
|
|
220
|
+
config_attr :env_paths, [] do |input|
|
|
221
|
+
check_configurable
|
|
222
|
+
@env_paths = [*input].compact.collect do |path|
|
|
223
|
+
Env.instance_for(root[path]).env_path
|
|
224
|
+
end.uniq
|
|
225
|
+
reset_envs
|
|
96
226
|
end
|
|
227
|
+
|
|
228
|
+
# Designate load paths. If use_dependencies == true, then
|
|
229
|
+
# load_paths will be used for automatic loading of modules
|
|
230
|
+
# through the active_support Dependencies module.
|
|
231
|
+
path_config :load_paths, ["lib"]
|
|
97
232
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
233
|
+
# Designate paths for discovering and executing commands.
|
|
234
|
+
path_config :command_paths, ["cmd"]
|
|
235
|
+
|
|
236
|
+
# Designate paths for discovering generators.
|
|
237
|
+
path_config :generator_paths, ["lib"]
|
|
102
238
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
239
|
+
manifest(:tasks, :load_paths, "**/*.rb") do |load_path, path|
|
|
240
|
+
next unless document = Support::Lazydoc.scan_doc(path, 'manifest')
|
|
241
|
+
|
|
242
|
+
document.const_names.collect do |const_name|
|
|
243
|
+
if const_name.empty?
|
|
244
|
+
key = root.relative_filepath(load_path, path).chomp('.rb')
|
|
245
|
+
[key, Support::Constant.new(key.camelize, path)]
|
|
246
|
+
else
|
|
247
|
+
[const_name.underscore, Support::Constant.new(const_name, path)]
|
|
248
|
+
end
|
|
249
|
+
end
|
|
107
250
|
end
|
|
108
251
|
|
|
109
|
-
|
|
110
|
-
Tap::Support.autoload(:Rake, 'tap/support/rake')
|
|
111
|
-
|
|
112
|
-
# setup
|
|
113
|
-
app.extend Tap::Support::Rake
|
|
114
|
-
rake = Rake.application
|
|
115
|
-
options = rake.options
|
|
252
|
+
manifest(:commands, :command_paths, "**/*.rb")
|
|
116
253
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
254
|
+
manifest(:generators, :generator_paths, '**/*_generator.rb') do |load_path, path|
|
|
255
|
+
dirname = File.dirname(path)
|
|
256
|
+
next unless "#{File.basename(dirname)}_generator.rb" == File.basename(path)
|
|
257
|
+
|
|
258
|
+
next unless document = Support::Lazydoc.scan_doc(path, 'generator')
|
|
259
|
+
document.const_names.collect do |const_name|
|
|
260
|
+
if const_name.empty?
|
|
261
|
+
key = root.relative_filepath(load_path, dirname)
|
|
262
|
+
[key, Support::Constant.new((key + '_generator').camelize, path)]
|
|
263
|
+
else
|
|
264
|
+
[const_name.underscore, Support::Constant.new(const_name, path)]
|
|
265
|
+
end
|
|
120
266
|
end
|
|
121
|
-
|
|
267
|
+
end
|
|
122
268
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
ARGV.concat(current_argv)
|
|
135
|
-
end
|
|
269
|
+
def initialize(config={}, root=Tap::Root.new, logger=nil)
|
|
270
|
+
@root = root
|
|
271
|
+
@logger = logger
|
|
272
|
+
@envs = []
|
|
273
|
+
@active = false
|
|
274
|
+
@manifests = {}
|
|
275
|
+
@manifested = []
|
|
276
|
+
|
|
277
|
+
# initialize these for reset_env
|
|
278
|
+
@gems = []
|
|
279
|
+
@env_paths = []
|
|
136
280
|
|
|
137
|
-
|
|
281
|
+
initialize_config(config)
|
|
138
282
|
end
|
|
139
283
|
|
|
140
|
-
#
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
284
|
+
# Sets envs removing duplicates and instances of self.
|
|
285
|
+
def envs=(envs)
|
|
286
|
+
@envs = envs.uniq.delete_if {|e| e == self }
|
|
287
|
+
@envs.freeze
|
|
288
|
+
@flat_envs = nil
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# An array of nested Envs, by default comprised of the
|
|
292
|
+
# env_path + gem environments (in that order). These
|
|
293
|
+
# nested Envs are activated/deactivated with self.
|
|
144
294
|
#
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
295
|
+
# Returns a flattened array of the unique nested envs
|
|
296
|
+
# when flat == true.
|
|
297
|
+
def envs(flat=false)
|
|
298
|
+
flat ? (@flat_envs ||= self.flatten_envs.freeze) : @envs
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Unshifts env onto envs, removing duplicates.
|
|
302
|
+
# Self cannot be unshifted onto self.
|
|
303
|
+
def unshift(env)
|
|
304
|
+
unless env == self || envs[0] == env
|
|
305
|
+
self.envs = envs.dup.unshift(env)
|
|
153
306
|
end
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
307
|
+
envs
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Pushes env onto envs, removing duplicates.
|
|
311
|
+
# Self cannot be pushed onto self.
|
|
312
|
+
def push(env)
|
|
313
|
+
unless env == self || envs[-1] == env
|
|
314
|
+
envs = self.envs.reject {|e| e == env }
|
|
315
|
+
self.envs = envs.push(env)
|
|
158
316
|
end
|
|
317
|
+
envs
|
|
159
318
|
end
|
|
160
|
-
|
|
161
|
-
#
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
logger.add(level, msg, action.to_s) if logger
|
|
319
|
+
|
|
320
|
+
# Passes each nested env to the block in order, starting with self.
|
|
321
|
+
def each
|
|
322
|
+
envs(true).each {|e| yield(e) }
|
|
165
323
|
end
|
|
166
324
|
|
|
167
|
-
#
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
325
|
+
# Passes each nested env to the block in reverse order, ending with self.
|
|
326
|
+
def reverse_each
|
|
327
|
+
envs(true).reverse_each {|e| yield(e) }
|
|
328
|
+
end
|
|
171
329
|
|
|
172
|
-
#
|
|
173
|
-
|
|
174
|
-
|
|
330
|
+
# Returns the total number of unique envs nested in self (including self).
|
|
331
|
+
def count
|
|
332
|
+
envs(true).length
|
|
333
|
+
end
|
|
334
|
+
|
|
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
|
+
# Processes and resets the input configurations for both root
|
|
343
|
+
# and self. Reconfiguration consists of the following steps:
|
|
175
344
|
#
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
log(:load_config, path, Logger::DEBUG)
|
|
189
|
-
config_paths << path
|
|
345
|
+
# * partition overrides into env, root, and other configs
|
|
346
|
+
# * reconfigure root with the root configs
|
|
347
|
+
# * reconfigure self with the env configs
|
|
348
|
+
# * yield other configs to the block (if given)
|
|
349
|
+
#
|
|
350
|
+
# Reconfigure will always yields to the block, even if there
|
|
351
|
+
# are no non-root, non-env configurations. Unspecified
|
|
352
|
+
# configurations are NOT reconfigured. (Note this means
|
|
353
|
+
# that existing path configurations like load_paths will
|
|
354
|
+
# not automatically be reset using reconfigured root.)
|
|
355
|
+
def reconfigure(overrides={})
|
|
356
|
+
check_configurable
|
|
190
357
|
|
|
191
|
-
config
|
|
192
|
-
|
|
358
|
+
# partiton config into its parts
|
|
359
|
+
env_configs = {}
|
|
360
|
+
root_configs = {}
|
|
361
|
+
other_configs = {}
|
|
193
362
|
|
|
194
|
-
|
|
195
|
-
|
|
363
|
+
env_configurations = self.class.configurations
|
|
364
|
+
root_configurations = root.class.configurations
|
|
365
|
+
overrides.each_pair do |key, value|
|
|
366
|
+
key = key.to_sym
|
|
196
367
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
#
|
|
210
|
-
|
|
368
|
+
partition = case
|
|
369
|
+
when env_configurations.key?(key) then env_configs
|
|
370
|
+
when root_configurations.key?(key) then root_configs
|
|
371
|
+
else other_configs
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
partition[key] = value
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# reconfigure root so it can resolve path_configs
|
|
378
|
+
root.reconfigure(root_configs)
|
|
379
|
+
|
|
380
|
+
# reconfigure self
|
|
381
|
+
super(env_configs)
|
|
382
|
+
|
|
383
|
+
# handle other configs
|
|
211
384
|
case
|
|
212
385
|
when block_given?
|
|
213
386
|
yield(other_configs)
|
|
@@ -215,121 +388,253 @@ module Tap
|
|
|
215
388
|
log(:warn, "ignoring non-env configs: #{other_configs.keys.join(',')}", Logger::DEBUG)
|
|
216
389
|
end
|
|
217
390
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
391
|
+
self
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Returns the path for self in Env.instances.
|
|
395
|
+
def env_path
|
|
396
|
+
Env.instances.each_pair {|path, env| return path if env == self }
|
|
397
|
+
nil
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Logs the action and message at the input level (default INFO).
|
|
401
|
+
# Logging is suppressed if no logger is set.
|
|
402
|
+
def log(action, msg="", level=Logger::INFO)
|
|
403
|
+
logger.add(level, msg, action.to_s) if logger
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Activates self by unshifting load_paths for self to the load_path_targets.
|
|
407
|
+
# Once active, self can be referenced from Env.instance and the current
|
|
408
|
+
# configurations are frozen. Env.instance is deactivated, if set, before
|
|
409
|
+
# self is activated. Returns true if activate succeeded, or false if self
|
|
410
|
+
# is already active.
|
|
411
|
+
def activate
|
|
412
|
+
return false if active?
|
|
224
413
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
when /_paths$/
|
|
233
|
-
assign_paths(root, value, self.config[key])
|
|
234
|
-
else
|
|
235
|
-
handle_unknown_env_config(root, key, value)
|
|
414
|
+
@active = true
|
|
415
|
+
@@instance = self unless @@instance
|
|
416
|
+
|
|
417
|
+
# freeze array configs like load_paths
|
|
418
|
+
config.each_pair do |key, value|
|
|
419
|
+
case value
|
|
420
|
+
when Array then value.freeze
|
|
236
421
|
end
|
|
237
422
|
end
|
|
423
|
+
|
|
424
|
+
# activate nested envs
|
|
425
|
+
envs.reverse_each do |env|
|
|
426
|
+
env.activate
|
|
427
|
+
end
|
|
238
428
|
|
|
429
|
+
# add load paths to load_path_targets
|
|
430
|
+
load_path_targets.each do |target|
|
|
431
|
+
load_paths.reverse_each do |path|
|
|
432
|
+
target.unshift(path)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
target.uniq!
|
|
436
|
+
end
|
|
437
|
+
|
|
239
438
|
true
|
|
240
439
|
end
|
|
241
440
|
|
|
242
|
-
#
|
|
243
|
-
#
|
|
244
|
-
#
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
441
|
+
# Deactivates self by clearing manifests and deleting load_paths for self
|
|
442
|
+
# from the load_path_targets. Env.instance will no longer reference self
|
|
443
|
+
# and the configurations are unfrozen (using duplication).
|
|
444
|
+
#
|
|
445
|
+
# Returns true if deactivate succeeded, or false if self is not active.
|
|
446
|
+
def deactivate
|
|
447
|
+
return false unless active?
|
|
448
|
+
|
|
449
|
+
# remove load paths from load_path_targets
|
|
450
|
+
load_path_targets.each do |target|
|
|
451
|
+
load_paths.each do |path|
|
|
452
|
+
target.delete(path)
|
|
453
|
+
end
|
|
454
|
+
end
|
|
254
455
|
|
|
255
|
-
|
|
256
|
-
|
|
456
|
+
# unfreeze array configs by duplicating
|
|
457
|
+
self.config.class_config.each_pair do |key, value|
|
|
458
|
+
value = send(key)
|
|
459
|
+
case value
|
|
460
|
+
when Array then instance_variable_set("@#{key}", value.dup)
|
|
461
|
+
end
|
|
257
462
|
end
|
|
258
463
|
|
|
259
|
-
|
|
464
|
+
@active = false
|
|
465
|
+
@manifests.clear
|
|
466
|
+
@@instance = nil if @@instance == self
|
|
467
|
+
|
|
468
|
+
# dectivate nested envs
|
|
469
|
+
envs.reverse_each do |env|
|
|
470
|
+
env.deactivate
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
true
|
|
260
474
|
end
|
|
261
475
|
|
|
262
|
-
#
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
load_config(full_gem_path(gem_name))
|
|
476
|
+
# Return true if self has been activated.
|
|
477
|
+
def active?
|
|
478
|
+
@active
|
|
266
479
|
end
|
|
267
480
|
|
|
268
|
-
#
|
|
269
|
-
#
|
|
270
|
-
#
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
481
|
+
# Cycles through all items yielded by the iterate_<name> method and
|
|
482
|
+
# adds each to the manifests[name] hash. Freezes the hash when complete.
|
|
483
|
+
# Simply returns the manifests[name] hash if frozen.
|
|
484
|
+
def manifest(name)
|
|
485
|
+
manifest = manifests[name] ||= Support::Manifest.new(name, self)
|
|
486
|
+
|
|
487
|
+
manifest.entries.each do |key, path|
|
|
488
|
+
yield(key, path)
|
|
489
|
+
end if block_given?
|
|
490
|
+
|
|
491
|
+
manifest.each_path do |context, path|
|
|
492
|
+
next unless keys = send(manifest.map_method, context, path)
|
|
493
|
+
|
|
494
|
+
keys.each {|entry| manifest.store(entry) }
|
|
495
|
+
keys.each {|key, value| yield(key, value) } if block_given?
|
|
496
|
+
end unless manifest.complete?
|
|
497
|
+
|
|
498
|
+
manifest
|
|
283
499
|
end
|
|
284
500
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
load_config(config_file)
|
|
501
|
+
def find(name, pattern)
|
|
502
|
+
manifest(name) do |key, path|
|
|
503
|
+
return path if Root.minimal_match?(key, pattern)
|
|
289
504
|
end
|
|
505
|
+
nil
|
|
290
506
|
end
|
|
291
507
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
508
|
+
def search(name, pattern)
|
|
509
|
+
return find(name, pattern) if name == :envs
|
|
510
|
+
|
|
511
|
+
envs = case pattern
|
|
512
|
+
when /^(.*):([^:]+)$/
|
|
513
|
+
env_pattern = $1
|
|
514
|
+
pattern = $2
|
|
515
|
+
find(:envs, env_pattern) or raise(ArgumentError, "could not find env: #{env_pattern}")
|
|
516
|
+
else manifest(:envs).values
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
envs.each do |env|
|
|
520
|
+
if result = env.find(name, pattern)
|
|
521
|
+
return result
|
|
305
522
|
end
|
|
306
523
|
end
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
524
|
+
|
|
525
|
+
nil
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def summary(name)
|
|
529
|
+
summary = Support::Summary.new
|
|
530
|
+
manifest(:envs).mini_map.each do |(key, env)|
|
|
531
|
+
summary.add(key, env, env.manifest(name).mini_map)
|
|
314
532
|
end
|
|
533
|
+
summary
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def summarize(name, &block)
|
|
537
|
+
lines = summary(name).lines(&block)
|
|
538
|
+
lines << "=== no #{name} found" if lines.empty?
|
|
539
|
+
lines.join("\n")
|
|
540
|
+
end
|
|
315
541
|
|
|
316
|
-
|
|
542
|
+
def inspect(brief=false)
|
|
543
|
+
brief ? "#<#{self.class}:#{object_id} root='#{root.root}'>" : super()
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def to_s
|
|
547
|
+
inspect(true)
|
|
548
|
+
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
|
|
317
562
|
end
|
|
318
563
|
|
|
319
564
|
protected
|
|
320
565
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
+
# Raises an error if self is already active (and hence, configurations
|
|
595
|
+
# should not be modified)
|
|
596
|
+
def check_configurable
|
|
597
|
+
raise "path configurations are disabled when active" if active?
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
# Resets envs using the current env_paths and gems.
|
|
601
|
+
def reset_envs
|
|
602
|
+
self.envs = env_paths.collect do |path|
|
|
603
|
+
Env.instance_for(path)
|
|
604
|
+
end + gems.collect do |spec|
|
|
605
|
+
Env.instance_for(spec.full_gem_path)
|
|
328
606
|
end
|
|
329
607
|
end
|
|
330
608
|
|
|
331
|
-
|
|
332
|
-
|
|
609
|
+
# Recursively iterates through envs collecting all envs into
|
|
610
|
+
# the target. The result is a unique array of all nested
|
|
611
|
+
# envs, in order, beginning with self.
|
|
612
|
+
def flatten_envs(target=[])
|
|
613
|
+
unless target.include?(self)
|
|
614
|
+
target << self
|
|
615
|
+
envs.each do |env|
|
|
616
|
+
env.flatten_envs(target)
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
target
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
# Raised when there is a Env-level configuration error.
|
|
624
|
+
class ConfigError < StandardError
|
|
625
|
+
attr_reader :original_error, :env_path
|
|
626
|
+
|
|
627
|
+
def initialize(original_error, env_path)
|
|
628
|
+
@original_error = original_error
|
|
629
|
+
@env_path = env_path
|
|
630
|
+
super()
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
def message
|
|
634
|
+
"Configuration error: #{original_error.message}\n" +
|
|
635
|
+
($DEBUG ? "#{original_error.backtrace}\n" : "") +
|
|
636
|
+
"Check '#{env_path}' configurations"
|
|
637
|
+
end
|
|
333
638
|
end
|
|
334
639
|
end
|
|
335
640
|
end
|