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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "<%= project_name %>"
|
|
3
|
+
s.version = "0.0.1"
|
|
4
|
+
#s.author = "Your Name Here"
|
|
5
|
+
#s.email = "your.email@pubfactory.edu"
|
|
6
|
+
#s.homepage = "http://rubyforge.org/projects/<%= project_name %>/"
|
|
7
|
+
s.platform = Gem::Platform::RUBY
|
|
8
|
+
s.summary = "<%= project_name %> task library"
|
|
9
|
+
s.require_path = "lib"
|
|
10
|
+
s.test_file = "test/tap_test_suite.rb"
|
|
11
|
+
#s.rubyforge_project = "<%= project_name %>"
|
|
12
|
+
#s.has_rdoc = true
|
|
13
|
+
s.add_dependency("tap", "~> <%= Tap::VERSION %>")
|
|
14
|
+
|
|
15
|
+
# list extra rdoc files like README here.
|
|
16
|
+
s.extra_rdoc_files = %W{
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# list the files you want to include here. you can
|
|
20
|
+
# check this manifest using 'rake :print_manifest'
|
|
21
|
+
s.files = %W{
|
|
22
|
+
tapfile.rb
|
|
23
|
+
test/tap_test_helper.rb
|
|
24
|
+
test/tap_test_suite.rb
|
|
25
|
+
test/tapfile_test.rb
|
|
26
|
+
}
|
|
27
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/tap_test_helper.rb'
|
|
2
|
+
require File.dirname(__FILE__) + '/../tapfile.rb'
|
|
3
|
+
|
|
4
|
+
class TapfileTest < Test::Unit::TestCase
|
|
5
|
+
acts_as_tap_test
|
|
6
|
+
|
|
7
|
+
def test_goodnight
|
|
8
|
+
task = Goodnight.new :message => "goodnight"
|
|
9
|
+
|
|
10
|
+
# a simple test
|
|
11
|
+
assert_equal({:message => 'goodnight'}, task.config)
|
|
12
|
+
assert_equal "goodnight moon", task.process("moon")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
module Tap::Generator::Generators
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
task_manifest(m)
|
|
2
|
+
|
|
3
|
+
# :startdoc::generator a task and test
|
|
4
|
+
#
|
|
5
|
+
# Generates a new Tap::Task and an associated test file.
|
|
6
|
+
class TaskGenerator < Tap::Generator::Base
|
|
7
|
+
|
|
8
|
+
config :test, true, &c.switch # Generates the task without test files.
|
|
9
|
+
|
|
10
|
+
def manifest(m, const_name)
|
|
11
|
+
const = Constant.new(const_name.camelize)
|
|
12
|
+
|
|
13
|
+
task_path = app.filepath('lib', "#{const.path}.rb")
|
|
14
|
+
m.directory File.dirname(task_path)
|
|
15
|
+
m.template task_path, "task.erb", :const => const
|
|
16
|
+
|
|
17
|
+
if test
|
|
18
|
+
test_path = app.filepath('test', "#{const.path}_test.rb")
|
|
19
|
+
m.directory File.dirname(test_path)
|
|
20
|
+
m.template test_path, "test.erb", :const => const
|
|
22
21
|
end
|
|
22
|
+
|
|
23
|
+
const
|
|
23
24
|
end
|
|
24
|
-
|
|
25
|
-
def task_manifest(m)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def add_options!(opt)
|
|
29
|
-
options[:test] = true
|
|
30
|
-
opt.on(nil, '--[no-]test', 'Generates the task without test files.') { |value| options[:test] = value }
|
|
31
|
-
end
|
|
32
25
|
|
|
33
26
|
end
|
|
34
27
|
end
|
|
@@ -1,24 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# process defines what the task does; use the
|
|
14
|
-
# same number of inputs to enque the task
|
|
15
|
-
# as specified here
|
|
16
|
-
def process(input)
|
|
17
|
-
# use log to record information
|
|
18
|
-
result = "#{input} was processed with #{key}"
|
|
19
|
-
log self.name, result
|
|
20
|
-
|
|
21
|
-
result
|
|
1
|
+
<% redirect do |target| %># <%= const.name %>::manifest <replace with manifest summary>
|
|
2
|
+
# <replace with command line description>
|
|
3
|
+
|
|
4
|
+
# <%= const.const_name %> Documentation
|
|
5
|
+
class <%= const.const_name %> < Tap::Task
|
|
6
|
+
|
|
7
|
+
# <config file documentation>
|
|
8
|
+
config :message, 'goodnight' # a sample config
|
|
9
|
+
|
|
10
|
+
def process(name)
|
|
11
|
+
log message, name
|
|
12
|
+
"#{message} #{name}"
|
|
22
13
|
end
|
|
23
|
-
|
|
24
|
-
end
|
|
14
|
+
end <% module_nest(const.nesting, ' ') { target } end %>
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), '<%= '../' *
|
|
2
|
-
require '<%=
|
|
1
|
+
require File.join(File.dirname(__FILE__), '<%= '../' * const.nesting_depth %>tap_test_helper.rb')
|
|
2
|
+
require '<%= const.path %>'
|
|
3
3
|
|
|
4
|
-
class <%=
|
|
4
|
+
class <%= const.name %>Test < Test::Unit::TestCase
|
|
5
5
|
acts_as_tap_test
|
|
6
6
|
|
|
7
|
-
def test_<%=
|
|
8
|
-
|
|
7
|
+
def test_<%= const.basename %>
|
|
8
|
+
task = <%= const.name %>.new :message => "goodnight"
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
end
|
|
10
|
+
# a simple test
|
|
11
|
+
assert_equal({:message => 'goodnight'}, task.config)
|
|
12
|
+
assert_equal "goodnight moon", task.process("moon")
|
|
13
|
+
|
|
14
|
+
# a more complex test
|
|
15
|
+
task.enq("moon")
|
|
16
|
+
app.run
|
|
17
|
+
|
|
18
|
+
assert_equal ["goodnight moon"], app.results(task)
|
|
19
|
+
assert_audit_equal ExpAudit[[nil, "moon"], [task, "goodnight moon"]], app._results(task)[0]
|
|
22
20
|
end
|
|
23
|
-
|
|
24
21
|
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/lib/tap/root.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'tap/support/versions'
|
|
2
|
+
require 'tap/support/configurable'
|
|
2
3
|
autoload(:FileUtils, 'fileutils')
|
|
3
4
|
|
|
4
5
|
module Tap
|
|
@@ -62,8 +63,8 @@ module Tap
|
|
|
62
63
|
include Support::Versions
|
|
63
64
|
|
|
64
65
|
# Returns the filepath of path relative to dir. Both dir and path are
|
|
65
|
-
# expanded before the relative filepath is determined.
|
|
66
|
-
#
|
|
66
|
+
# expanded before the relative filepath is determined. Returns nil if
|
|
67
|
+
# the path is not relative to dir.
|
|
67
68
|
#
|
|
68
69
|
# Root.relative_filepath('dir', "dir/path/to/file.txt") # => "path/to/file.txt"
|
|
69
70
|
#
|
|
@@ -71,9 +72,7 @@ module Tap
|
|
|
71
72
|
expanded_dir = File.expand_path(dir, dir_string)
|
|
72
73
|
expanded_path = File.expand_path(path, dir_string)
|
|
73
74
|
|
|
74
|
-
unless expanded_path.index(expanded_dir) == 0
|
|
75
|
-
raise "\n#{expanded_path}\nis not relative to:\n#{expanded_dir}"
|
|
76
|
-
end
|
|
75
|
+
return nil unless expanded_path.index(expanded_dir) == 0
|
|
77
76
|
|
|
78
77
|
# use dir.length + 1 to remove a leading '/'. If dir.length + 1 >= expanded.length
|
|
79
78
|
# as in: relative_filepath('/path', '/path') then the first arg returns nil, and an
|
|
@@ -101,6 +100,15 @@ module Tap
|
|
|
101
100
|
end.flatten.uniq
|
|
102
101
|
end
|
|
103
102
|
|
|
103
|
+
# Path suffix glob. Globs along the base paths for
|
|
104
|
+
# paths that match the specified suffix pattern.
|
|
105
|
+
def sglob(suffix_pattern, *base_paths)
|
|
106
|
+
base_paths.collect do |base|
|
|
107
|
+
base = File.expand_path(base)
|
|
108
|
+
Dir.glob(File.join(base, suffix_pattern))
|
|
109
|
+
end.flatten.uniq
|
|
110
|
+
end
|
|
111
|
+
|
|
104
112
|
# Executes the block in the specified directory. Makes the directory, if
|
|
105
113
|
# necessary when mkdir is specified. Otherwise, indir raises an error
|
|
106
114
|
# for non-existant directories, as well as non-directory inputs.
|
|
@@ -109,7 +117,7 @@ module Tap
|
|
|
109
117
|
if !File.exists?(dir) && mkdir
|
|
110
118
|
FileUtils.mkdir_p(dir)
|
|
111
119
|
else
|
|
112
|
-
raise "
|
|
120
|
+
raise "not a directory: #{dir}"
|
|
113
121
|
end
|
|
114
122
|
end
|
|
115
123
|
|
|
@@ -160,15 +168,242 @@ module Tap
|
|
|
160
168
|
nil
|
|
161
169
|
end
|
|
162
170
|
end
|
|
171
|
+
|
|
172
|
+
# Minimizes a set of paths to the set of shortest basepaths that unqiuely
|
|
173
|
+
# identify the paths. The path extension and versions are removed from
|
|
174
|
+
# the basepath if possible. For example:
|
|
175
|
+
#
|
|
176
|
+
# Tap::Root.minimize ['path/to/a.rb', 'path/to/b.rb']
|
|
177
|
+
# # => ['a', 'b']
|
|
178
|
+
#
|
|
179
|
+
# Tap::Root.minimize ['path/to/a-0.1.0.rb', 'path/to/b-0.1.0.rb']
|
|
180
|
+
# # => ['a', 'b']
|
|
181
|
+
#
|
|
182
|
+
# Tap::Root.minimize ['path/to/file.rb', 'path/to/file.txt']
|
|
183
|
+
# # => ['file.rb', 'file.txt']
|
|
184
|
+
#
|
|
185
|
+
# Tap::Root.minimize ['path-0.1/to/file.rb', 'path-0.2/to/file.rb']
|
|
186
|
+
# # => ['path-0.1/to/file', 'path-0.2/to/file']
|
|
187
|
+
#
|
|
188
|
+
# Minimized paths that carry their extension will always carry
|
|
189
|
+
# their version as well, but the converse is not true; paths
|
|
190
|
+
# can be minimized to carry just the version and not the path
|
|
191
|
+
# extension.
|
|
192
|
+
#
|
|
193
|
+
# Tap::Root.minimize ['path/to/a-0.1.0.rb', 'path/to/a-0.1.0.txt']
|
|
194
|
+
# # => ['a-0.1.0.rb', 'a-0.1.0.txt']
|
|
195
|
+
#
|
|
196
|
+
# Tap::Root.minimize ['path/to/a-0.1.0.rb', 'path/to/a-0.2.0.rb']
|
|
197
|
+
# # => ['a-0.1.0', 'a-0.2.0']
|
|
198
|
+
#
|
|
199
|
+
# If a block is given, each (path, mini-path) pair will be passed
|
|
200
|
+
# to it after minimization.
|
|
201
|
+
def minimize(paths) # :yields: path, mini_path
|
|
202
|
+
unless block_given?
|
|
203
|
+
mini_paths = []
|
|
204
|
+
minimize(paths) {|p, mp| mini_paths << mp }
|
|
205
|
+
return mini_paths
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
splits = paths.uniq.collect do |path|
|
|
209
|
+
extname = File.extname(path)
|
|
210
|
+
extname = '' if extname =~ /^\.\d+$/
|
|
211
|
+
base = File.basename(path.chomp(extname))
|
|
212
|
+
version = base =~ /(-\d+(\.\d+)*)$/ ? $1 : ''
|
|
213
|
+
|
|
214
|
+
[dirname_or_array(path), base.chomp(version), extname, version, false, path]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
while !splits.empty?
|
|
218
|
+
index = 0
|
|
219
|
+
splits = splits.collect do |(dir, base, extname, version, flagged, path)|
|
|
220
|
+
index += 1
|
|
221
|
+
case
|
|
222
|
+
when !flagged && just_one?(splits, index, base)
|
|
223
|
+
|
|
224
|
+
# found just one
|
|
225
|
+
yield(path, base)
|
|
226
|
+
nil
|
|
227
|
+
when dir.kind_of?(Array)
|
|
228
|
+
|
|
229
|
+
# no more path segments to use, try to add
|
|
230
|
+
# back version and extname
|
|
231
|
+
if dir.empty?
|
|
232
|
+
dir << File.dirname(base)
|
|
233
|
+
base = File.basename(base)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
case
|
|
237
|
+
when !version.empty?
|
|
238
|
+
# add back version (occurs first)
|
|
239
|
+
[dir, "#{base}#{version}", extname, '', false, path]
|
|
240
|
+
|
|
241
|
+
when !extname.empty?
|
|
242
|
+
|
|
243
|
+
# add back extension (occurs second)
|
|
244
|
+
[dir, "#{base}#{extname}", '', version, false, path]
|
|
245
|
+
else
|
|
246
|
+
|
|
247
|
+
# nothing more to distinguish... path is minimized (occurs third)
|
|
248
|
+
yield(path, min_join(dir[0], base))
|
|
249
|
+
nil
|
|
250
|
+
end
|
|
251
|
+
else
|
|
252
|
+
|
|
253
|
+
# shift path segment. dirname_or_array returns an
|
|
254
|
+
# array if this is the last path segment to shift.
|
|
255
|
+
[dirname_or_array(dir), min_join(File.basename(dir), base), extname, version, false, path]
|
|
256
|
+
end
|
|
257
|
+
end.compact
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Returns true if the mini_path matches path. Matching logic
|
|
262
|
+
# reverses that of minimize:
|
|
263
|
+
# * a match occurs when path ends with mini_path
|
|
264
|
+
# * if mini_path doesn't specify an extension, then mini_path
|
|
265
|
+
# must only match path up to the path extension
|
|
266
|
+
# * if mini_path doesn't specify a version, then mini_path
|
|
267
|
+
# must only match path up to the path basename (minus the
|
|
268
|
+
# version and extname)
|
|
269
|
+
#
|
|
270
|
+
# For example:
|
|
271
|
+
#
|
|
272
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'file') # => true
|
|
273
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'dir/file') # => true
|
|
274
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'file-0.1.0') # => true
|
|
275
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'file-0.1.0.rb') # => true
|
|
276
|
+
#
|
|
277
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'file.rb') # => false
|
|
278
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'file-0.2.0') # => false
|
|
279
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.rb', 'another') # => false
|
|
280
|
+
#
|
|
281
|
+
# In matching, partial basenames are not allowed but partial directories
|
|
282
|
+
# are allowed. Hence:
|
|
283
|
+
#
|
|
284
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.txt', 'file') # => true
|
|
285
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.txt', 'ile') # => false
|
|
286
|
+
# Tap::Root.minimal_match?('dir/file-0.1.0.txt', 'r/file') # => true
|
|
287
|
+
#
|
|
288
|
+
def minimal_match?(path, mini_path)
|
|
289
|
+
extname = File.extname(mini_path)
|
|
290
|
+
extname = '' if extname =~ /^\.\d+$/
|
|
291
|
+
version = mini_path =~ /(-\d+(\.\d+)*)#{extname}$/ ? $1 : ''
|
|
292
|
+
|
|
293
|
+
match_path = case
|
|
294
|
+
when !extname.empty?
|
|
295
|
+
# force full match
|
|
296
|
+
path
|
|
297
|
+
when !version.empty?
|
|
298
|
+
# match up to version
|
|
299
|
+
path.chomp(File.extname(path))
|
|
300
|
+
else
|
|
301
|
+
# match up base
|
|
302
|
+
path.chomp(File.extname(path)).sub(/(-\d+(\.\d+)*)$/, '')
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# key ends with pattern AND basenames of each are equal...
|
|
306
|
+
# the last check ensures that a full path segment has
|
|
307
|
+
# been specified
|
|
308
|
+
match_path[-mini_path.length, mini_path.length] == mini_path && File.basename(match_path) == File.basename(mini_path)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Returns the path segments for the given path, splitting along the path
|
|
312
|
+
# divider. Root paths are always represented by a string, if only an
|
|
313
|
+
# empty string.
|
|
314
|
+
#
|
|
315
|
+
# os divider example
|
|
316
|
+
# windows '\' Root.split('C:\path\to\file') # => ["C:", "path", "to", "file"]
|
|
317
|
+
# *nix '/' Root.split('/path/to/file') # => ["", "path", "to", "file"]
|
|
318
|
+
#
|
|
319
|
+
# The path is always expanded relative to the expand_dir; so '.' and '..' are
|
|
320
|
+
# resolved. However, unless expand_path == true, only the segments relative
|
|
321
|
+
# to the expand_dir are returned.
|
|
322
|
+
#
|
|
323
|
+
# On windows (note that expanding paths allows the use of slashes or backslashes):
|
|
324
|
+
#
|
|
325
|
+
# Dir.pwd # => 'C:/'
|
|
326
|
+
# Root.split('path\to\..\.\to\file') # => ["C:", "path", "to", "file"]
|
|
327
|
+
# Root.split('path/to/.././to/file', false) # => ["path", "to", "file"]
|
|
328
|
+
#
|
|
329
|
+
# On *nix (or more generally systems with '/' roots):
|
|
330
|
+
#
|
|
331
|
+
# Dir.pwd # => '/'
|
|
332
|
+
# Root.split('path/to/.././to/file') # => ["", "path", "to", "file"]
|
|
333
|
+
# Root.split('path/to/.././to/file', false) # => ["path", "to", "file"]
|
|
334
|
+
#
|
|
335
|
+
def split(path, expand_path=true, expand_dir=Dir.pwd)
|
|
336
|
+
path = if expand_path
|
|
337
|
+
File.expand_path(path, expand_dir)
|
|
338
|
+
else
|
|
339
|
+
# normalize the path by expanding it, then
|
|
340
|
+
# work back to the relative filepath as needed
|
|
341
|
+
expanded_dir = File.expand_path(expand_dir)
|
|
342
|
+
expanded_path = File.expand_path(path, expand_dir)
|
|
343
|
+
expanded_path.index(expanded_dir) != 0 ? expanded_path : Tap::Root.relative_filepath(expanded_dir, expanded_path)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
segments = path.scan(/[^\/]+/)
|
|
347
|
+
|
|
348
|
+
# add back the root filepath as needed on *nix
|
|
349
|
+
segments.unshift "" if path[0] == ?/
|
|
350
|
+
segments
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
private
|
|
354
|
+
|
|
355
|
+
# utility method for minimize -- joins the
|
|
356
|
+
# dir and path, preventing results like:
|
|
357
|
+
#
|
|
358
|
+
# "./path"
|
|
359
|
+
# "//path"
|
|
360
|
+
def min_join(dir, path) # :nodoc:
|
|
361
|
+
case dir
|
|
362
|
+
when "." then path
|
|
363
|
+
when "/" then "/#{path}"
|
|
364
|
+
else "#{dir}/#{path}"
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# utility method for minimize -- returns the
|
|
369
|
+
# dirname of path, or an array if the dirname
|
|
370
|
+
# is effectively empty.
|
|
371
|
+
def dirname_or_array(path) # :nodoc:
|
|
372
|
+
dir = File.dirname(path)
|
|
373
|
+
case dir
|
|
374
|
+
when path, '.' then []
|
|
375
|
+
else dir
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# utility method for minimize -- determines if there
|
|
380
|
+
# is just one of the base in splits, while flagging
|
|
381
|
+
# all matching entries.
|
|
382
|
+
def just_one?(splits, index, base) # :nodoc:
|
|
383
|
+
just_one = true
|
|
384
|
+
index.upto(splits.length-1) do |i|
|
|
385
|
+
if splits[i][1] == base
|
|
386
|
+
splits[i][4] = true
|
|
387
|
+
just_one = false
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
just_one
|
|
392
|
+
end
|
|
393
|
+
|
|
163
394
|
end
|
|
164
395
|
|
|
165
396
|
include Support::Versions
|
|
397
|
+
include Support::Configurable
|
|
398
|
+
|
|
399
|
+
# The root directory.
|
|
400
|
+
config_attr(:root, '.', :writer => false)
|
|
166
401
|
|
|
167
|
-
#
|
|
168
|
-
|
|
402
|
+
# A hash of (alias, relative path) pairs for aliased subdirectories.
|
|
403
|
+
config_attr(:directories, {}, :writer => false)
|
|
169
404
|
|
|
170
|
-
# A hash of (alias, relative path) pairs for aliased
|
|
171
|
-
|
|
405
|
+
# A hash of (alias, relative path) pairs for aliased absolute paths.
|
|
406
|
+
config_attr(:absolute_paths, {}, :reader => false, :writer => false)
|
|
172
407
|
|
|
173
408
|
# A hash of (alias, expanded path) pairs for aliased subdirectories and absolute paths.
|
|
174
409
|
attr_reader :paths
|
|
@@ -182,29 +417,30 @@ module Tap
|
|
|
182
417
|
# and no aliased directories or absolute paths are specified.
|
|
183
418
|
def initialize(root=Dir.pwd, directories={}, absolute_paths={})
|
|
184
419
|
assign_paths(root, directories, absolute_paths)
|
|
420
|
+
@config = self.class.configurations.instance_config(self)
|
|
185
421
|
end
|
|
186
|
-
|
|
187
|
-
# Sets the root directory.
|
|
422
|
+
|
|
423
|
+
# Sets the root directory. All paths are reassigned accordingly.
|
|
188
424
|
def root=(path)
|
|
189
425
|
assign_paths(path, directories, absolute_paths)
|
|
190
426
|
end
|
|
191
427
|
|
|
192
|
-
# Sets the directories to those provided.
|
|
428
|
+
# Sets the directories to those provided. 'root' and :root are reserved
|
|
193
429
|
# and cannot be set using this method (use root= instead).
|
|
194
430
|
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
431
|
+
# r['alt'] # => File.join(r.root, 'alt')
|
|
432
|
+
# r.directories = {'alt' => 'dir'}
|
|
433
|
+
# r['alt'] # => File.join(r.root, 'dir')
|
|
198
434
|
def directories=(dirs)
|
|
199
435
|
assign_paths(root, dirs, absolute_paths)
|
|
200
436
|
end
|
|
201
437
|
|
|
202
|
-
# Sets the absolute paths to those provided. 'root' and :root are reserved
|
|
438
|
+
# Sets the absolute paths to those provided. 'root' and :root are reserved
|
|
203
439
|
# directory keys and cannot be set using this method (use root= instead).
|
|
204
440
|
#
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
#
|
|
441
|
+
# r['abs'] # => File.join(r.root, 'abs')
|
|
442
|
+
# r.absolute_paths = {'abs' => '/path/to/dir'}
|
|
443
|
+
# r['abs'] # => '/path/to/dir'
|
|
208
444
|
def absolute_paths=(paths)
|
|
209
445
|
assign_paths(root, directories, paths)
|
|
210
446
|
end
|
|
@@ -298,7 +534,10 @@ module Tap
|
|
|
298
534
|
# fp = r.filepath(:in, 'path/to/file.txt') # => '/root_dir/in/path/to/file.txt'
|
|
299
535
|
# r.translate(fp, :in, :out) # => '/root_dir/out/path/to/file.txt'
|
|
300
536
|
def translate(filepath, input_dir, output_dir)
|
|
301
|
-
|
|
537
|
+
unless relative_path = relative_filepath(input_dir, filepath)
|
|
538
|
+
raise "\n#{filepath}\nis not relative to:\n#{input_dir}"
|
|
539
|
+
end
|
|
540
|
+
filepath(output_dir, relative_path)
|
|
302
541
|
end
|
|
303
542
|
|
|
304
543
|
# Lists all files in the aliased dir matching the input patterns. Patterns
|