tap 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/History +12 -0
  2. data/MIT-LICENSE +0 -2
  3. data/README +23 -32
  4. data/bin/rap +116 -0
  5. data/bin/tap +6 -9
  6. data/cgi/run.rb +67 -0
  7. data/cmd/console.rb +1 -1
  8. data/cmd/destroy.rb +4 -4
  9. data/cmd/generate.rb +4 -4
  10. data/cmd/manifest.rb +61 -53
  11. data/cmd/run.rb +8 -75
  12. data/doc/Class Reference +130 -121
  13. data/doc/Command Reference +76 -124
  14. data/doc/Syntax Reference +290 -0
  15. data/doc/Tutorial +305 -237
  16. data/lib/tap/app.rb +140 -467
  17. data/lib/tap/constants.rb +2 -2
  18. data/lib/tap/declarations.rb +211 -0
  19. data/lib/tap/env.rb +171 -193
  20. data/lib/tap/exe.rb +100 -21
  21. data/lib/tap/file_task.rb +3 -3
  22. data/lib/tap/generator/base.rb +1 -1
  23. data/lib/tap/generator/destroy.rb +10 -10
  24. data/lib/tap/generator/generate.rb +29 -18
  25. data/lib/tap/generator/generators/command/command_generator.rb +2 -2
  26. data/lib/tap/generator/generators/command/templates/command.erb +2 -2
  27. data/lib/tap/generator/generators/config/config_generator.rb +3 -3
  28. data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
  29. data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
  30. data/lib/tap/generator/generators/file_task/templates/task.erb +1 -1
  31. data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
  32. data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
  33. data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
  34. data/lib/tap/generator/generators/root/root_generator.rb +13 -13
  35. data/lib/tap/generator/generators/root/templates/README +0 -0
  36. data/lib/tap/generator/generators/root/templates/Rakefile +2 -2
  37. data/lib/tap/generator/generators/root/templates/gemspec +4 -5
  38. data/lib/tap/generator/generators/root/templates/tapfile +11 -8
  39. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  40. data/lib/tap/generator/generators/task/task_generator.rb +1 -3
  41. data/lib/tap/generator/generators/task/templates/test.erb +1 -3
  42. data/lib/tap/patches/optparse/summarize.rb +62 -0
  43. data/lib/tap/root.rb +41 -29
  44. data/lib/tap/support/aggregator.rb +16 -3
  45. data/lib/tap/support/assignments.rb +10 -9
  46. data/lib/tap/support/audit.rb +58 -64
  47. data/lib/tap/support/class_configuration.rb +33 -44
  48. data/lib/tap/support/combinator.rb +125 -0
  49. data/lib/tap/support/configurable.rb +13 -14
  50. data/lib/tap/support/configurable_class.rb +21 -43
  51. data/lib/tap/support/configuration.rb +55 -9
  52. data/lib/tap/support/constant.rb +87 -13
  53. data/lib/tap/support/constant_manifest.rb +116 -0
  54. data/lib/tap/support/dependencies.rb +54 -0
  55. data/lib/tap/support/dependency.rb +44 -0
  56. data/lib/tap/support/executable.rb +247 -32
  57. data/lib/tap/support/executable_queue.rb +1 -1
  58. data/lib/tap/support/gems/rake.rb +29 -8
  59. data/lib/tap/support/gems.rb +10 -30
  60. data/lib/tap/support/instance_configuration.rb +29 -3
  61. data/lib/tap/support/intern.rb +46 -0
  62. data/lib/tap/support/join.rb +143 -0
  63. data/lib/tap/support/joins/fork.rb +19 -0
  64. data/lib/tap/support/joins/merge.rb +22 -0
  65. data/lib/tap/support/joins/sequence.rb +21 -0
  66. data/lib/tap/support/joins/switch.rb +25 -0
  67. data/lib/tap/support/joins/sync_merge.rb +63 -0
  68. data/lib/tap/support/joins.rb +15 -0
  69. data/lib/tap/support/lazy_attributes.rb +17 -2
  70. data/lib/tap/support/lazydoc/comment.rb +503 -0
  71. data/lib/tap/support/lazydoc/config.rb +17 -0
  72. data/lib/tap/support/lazydoc/definition.rb +36 -0
  73. data/lib/tap/support/lazydoc/document.rb +152 -0
  74. data/lib/tap/support/lazydoc/method.rb +24 -0
  75. data/lib/tap/support/lazydoc.rb +269 -343
  76. data/lib/tap/support/manifest.rb +121 -103
  77. data/lib/tap/support/minimap.rb +90 -0
  78. data/lib/tap/support/node.rb +56 -0
  79. data/lib/tap/support/parser.rb +436 -0
  80. data/lib/tap/support/schema.rb +359 -0
  81. data/lib/tap/support/shell_utils.rb +3 -5
  82. data/lib/tap/support/string_ext.rb +60 -0
  83. data/lib/tap/support/tdoc.rb +7 -2
  84. data/lib/tap/support/templater.rb +30 -16
  85. data/lib/tap/support/validation.rb +77 -8
  86. data/lib/tap/task.rb +431 -143
  87. data/lib/tap/tasks/dump.rb +15 -10
  88. data/lib/tap/tasks/load.rb +112 -0
  89. data/lib/tap/tasks/rake.rb +4 -41
  90. data/lib/tap/test/assertions.rb +38 -0
  91. data/lib/tap/test/env_vars.rb +1 -1
  92. data/lib/tap/test/extensions.rb +79 -0
  93. data/lib/tap/test/file_test.rb +420 -0
  94. data/lib/tap/test/file_test_class.rb +12 -0
  95. data/lib/tap/test/regexp_escape.rb +87 -0
  96. data/lib/tap/test/script_test.rb +46 -0
  97. data/lib/tap/test/script_tester.rb +115 -0
  98. data/lib/tap/test/subset_test.rb +260 -0
  99. data/lib/tap/test/subset_test_class.rb +99 -0
  100. data/lib/tap/test/{tap_methods.rb → tap_test.rb} +45 -43
  101. data/lib/tap/test/utils.rb +231 -0
  102. data/lib/tap/test.rb +53 -26
  103. data/lib/tap.rb +3 -20
  104. metadata +50 -27
  105. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
  106. data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
  107. data/lib/tap/patches/rake/testtask.rb +0 -57
  108. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
  109. data/lib/tap/patches/ruby19/parsedate.rb +0 -16
  110. data/lib/tap/support/batchable.rb +0 -47
  111. data/lib/tap/support/batchable_class.rb +0 -107
  112. data/lib/tap/support/command_line.rb +0 -98
  113. data/lib/tap/support/comment.rb +0 -270
  114. data/lib/tap/support/constant_utils.rb +0 -127
  115. data/lib/tap/support/declarations.rb +0 -111
  116. data/lib/tap/support/framework.rb +0 -83
  117. data/lib/tap/support/framework_class.rb +0 -180
  118. data/lib/tap/support/run_error.rb +0 -39
  119. data/lib/tap/support/summary.rb +0 -30
  120. data/lib/tap/test/file_methods.rb +0 -377
  121. data/lib/tap/test/script_methods/script_test.rb +0 -98
  122. data/lib/tap/test/script_methods.rb +0 -107
  123. data/lib/tap/test/subset_methods.rb +0 -420
  124. data/lib/tap/workflow.rb +0 -200
@@ -1,151 +1,169 @@
1
- require 'tap/root'
1
+ require 'tap/support/minimap'
2
2
 
3
3
  module Tap
4
4
  module Support
5
+
6
+ # Stores an array of paths and makes them available for lookup by
7
+ # minipath. Manifests may be bound to a Tap::Env, allowing searches
8
+ # across a full environment (including nested environments).
9
+ #
10
+ # Manifest has a number of hooks used by subclasses like
11
+ # ConstantManifest to lazily add entries as needed.
5
12
  class Manifest
6
13
  class << self
7
- def normalize(key)
8
- key.to_s.downcase.gsub(/\s/, "_").delete(":")
14
+
15
+ # Interns a new manifest, overriding the minikey
16
+ # method with the block (the minikey method converts
17
+ # entries to the path used during minimap and
18
+ # minimatch lookup, see Minimap).
19
+ def intern(*args, &block)
20
+ instance = new(*args)
21
+ if block_given?
22
+ instance.extend Support::Intern(:minikey)
23
+ instance.minikey_block = block
24
+ end
25
+ instance
9
26
  end
10
27
  end
11
28
 
12
29
  include Enumerable
30
+ include Minimap
31
+
32
+ # Matches a compound manifest search key. After the match,
33
+ # if the key is compound then:
34
+ #
35
+ # $1:: env_key
36
+ # $4:: key
37
+ #
38
+ # If the key is not compound, $4 is nil and $1 is the key.
39
+ SEARCH_REGEXP = /^(([A-z]:)?.*?)(:(.*))?$/
13
40
 
14
- # An array of (key, value) entries in self.
41
+ # An array entries in self.
15
42
  attr_reader :entries
16
43
 
17
- # An array of search_paths to identify entries.
18
- attr_reader :search_paths
44
+ # The bound Tap::Env, or nil.
45
+ attr_reader :env
19
46
 
20
- # The index of the search_path that will be searched
21
- # next when building the manifest.
22
- attr_reader :search_path_index
47
+ # The reader on Tap::Env accessing manifests of the
48
+ # same type as self. reader is set during bind.
49
+ attr_reader :reader
23
50
 
24
- def initialize(search_paths)
25
- self.search_paths = search_paths
51
+ # Initializes a new, unbound Manifest.
52
+ def initialize(entries=[])
53
+ @entries = entries
54
+ @env = nil
55
+ @reader = nil
26
56
  end
27
57
 
28
- # Returns an array of the entries keys.
29
- def keys
30
- entries.collect {|(key, value)| key }
58
+ # Binds self to an env and reader. The manifests returned by env.reader
59
+ # will be used during traversal methods like search. Raises an error if
60
+ # env does not respond to reader; returns self.
61
+ def bind(env, reader)
62
+ if env == nil
63
+ raise ArgumentError, "env may not be nil"
64
+ end
65
+
66
+ unless env.respond_to?(reader)
67
+ raise ArgumentError, "env does not respond to #{reader}"
68
+ end
69
+
70
+ @env = env
71
+ @reader = reader
72
+ self
31
73
  end
32
74
 
33
- # Returns an array of the entries values.
34
- def values
35
- entries.collect {|(key, value)| value }
75
+ # Unbinds self from env. Returns self.
76
+ def unbind
77
+ @env = nil
78
+ @reader = nil
79
+ self
36
80
  end
37
81
 
38
- # True if entries are empty.
39
- def empty?
40
- entries.empty?
82
+ # True if the env and reader have been set.
83
+ def bound?
84
+ @env != nil && @reader != nil
41
85
  end
42
86
 
43
- def search_paths=(search_paths)
44
- @entries = []
45
- @search_paths = search_paths
46
- @search_path_index = 0
87
+ # A hook for dynamically building entries. By default build simply
88
+ # returns self
89
+ def build
90
+ self
47
91
  end
48
92
 
49
- # Clears entries and sets the search_path_index to zero.
50
- def reset
51
- @entries.clear
52
- @search_path_index = 0
93
+ # A hook to flag when self is built. By default built? returns true.
94
+ def built?
95
+ true
53
96
  end
54
97
 
55
- # Builds the manifest, identifying all entries from search_paths.
56
- # Returns self.
57
- def build
58
- each {|k, v|} unless built?
98
+ # A hook to reset a build. By default reset simply returns self.
99
+ def reset
59
100
  self
60
101
  end
61
102
 
62
- # True if all search paths have been checked for entries
63
- # (ie search_path_index == search_paths.length).
64
- def built?
65
- @search_path_index == search_paths.length
103
+ # True if entries are empty.
104
+ def empty?
105
+ entries.empty?
106
+ end
107
+
108
+ # Iterates over each entry entry in self.
109
+ def each
110
+ entries.each {|entry| yield(entry) }
66
111
  end
67
112
 
68
- # Abstract method which should return each (key, value) entry
69
- # for a given search path. Raises a NotImplementedError
70
- # if left not implemented.
71
- def entries_for(search_path)
72
- [[search_path, search_path]]
113
+ # Alias for Minimap#minimatch.
114
+ def [](key)
115
+ minimatch(key)
73
116
  end
74
117
 
75
- # Adds the (key, value) pair to entries and returns the new entry.
76
- # Checks that entries does not already assign key a conflicting value;
77
- # raises an error if this is the case, or returns the existing entry.
118
+ # Search across env.each for the first entry minimatching key.
119
+ # A single env can be specified by using a compound key like
120
+ # 'env_key:key'. Returns nil if no matching entry is found.
78
121
  #
79
- # Keys are normalized using Manifest.normalize before storing.
80
- def store(key, value)
81
- key = Manifest.normalize(key)
82
- existing = entries.find {|(k, v)| key == k }
122
+ # Search raises an error unless bound?
123
+ def search(key)
124
+ raise "cannot search unless bound" unless bound?
83
125
 
84
- if existing
85
- if existing[1] != value
86
- raise ManifestConflict.new(key, value, existing[1])
87
- else
88
- return existing
126
+ key =~ SEARCH_REGEXP
127
+ envs = if $4 != nil
128
+ # compound key, match for env
129
+ key = $4
130
+ [env.minimatch($1)].compact
131
+ else
132
+ # not a compound key, search all
133
+ # envs by iterating env itself
134
+ env
135
+ end
136
+
137
+ # traverse envs looking for the first
138
+ # manifest entry matching key
139
+ envs.each do |env|
140
+ if result = env.send(reader).minimatch(key)
141
+ return result
89
142
  end
90
143
  end
91
144
 
92
- new_entry = [key, value]
93
- entries << new_entry
94
- new_entry
145
+ nil
95
146
  end
96
147
 
97
- # Iterates over each (key, value) entry in self, dynamically identifying entries
98
- # from search_paths if necessary. New entries are identifed using the each_for
99
- # method.
100
- def each
101
- entries.each do |key, path|
102
- yield(key, path)
103
- end
104
-
105
- unless built?
106
- n_to_skip = @search_path_index
107
- search_paths.each do |search_path|
108
- # advance to the current search path
109
- if n_to_skip > 0
110
- n_to_skip -= 1
111
- next
112
- end
113
- @search_path_index += 1
114
-
115
- # collect new entries and yield afterwards to ensure
116
- # that all entries for the search_path get stored
117
- new_entries = entries_for(*search_path)
118
- next if new_entries == nil
148
+ def inspect(traverse=true)
149
+ if traverse && bound?
150
+ lines = []
151
+ env.each do |env|
152
+ manifest = env.send(reader).build
153
+ next if manifest.empty?
119
154
 
120
- new_entries.each {|(key, value)| store(key, value) }
121
- new_entries.each {|(key, value)| yield(key, value) }
155
+ lines << "== #{env.root.root}"
156
+ manifest.minimap.each do |mini, value|
157
+ lines << " #{mini}: #{value.inspect}"
158
+ end
122
159
  end
160
+ return lines.join("\n")
123
161
  end
124
- end
125
-
126
- # Returns an array of (mini_key, value) pairs, matching
127
- # entries by index.
128
- def minimize
129
- hash = {}
130
- Tap::Root.minimize(keys) do |path, mini_path|
131
- hash[path] = mini_path
132
- end
133
-
134
- entries.collect {|path, value| [hash[path], value] }
135
- end
136
-
137
- protected
138
-
139
- # Raised when multiple paths are assigned to the same manifest key.
140
- class ManifestConflict < StandardError
141
- attr_reader :key, :value, :existing
142
162
 
143
- def initialize(key, value, existing)
144
- @key = key
145
- @value = value
146
- @existing = existing
147
- super("attempted to store '%s': %s\nbut already was\n%s" % [key, value, existing])
163
+ lines = minimap.collect do |mini, value|
164
+ " #{mini}: #{value.inspect}"
148
165
  end
166
+ "#{self.class}:#{object_id} (#{bound? ? env.root.root : ''})\n#{lines.join("\n")}"
149
167
  end
150
168
  end
151
169
  end
@@ -0,0 +1,90 @@
1
+ require 'tap/root'
2
+
3
+ module Tap
4
+ module Support
5
+
6
+ # Minimap adds minimization and search methods to an array of paths (see
7
+ # Tap::Root.minimize and Tap::Root.minimal_match?).
8
+ #
9
+ # paths = %w{
10
+ # path/to/file-0.1.0.txt
11
+ # path/to/file-0.2.0.txt
12
+ # path/to/another_file.txt
13
+ # }
14
+ # paths.extend Minimap
15
+ #
16
+ # paths.minimatch('file') # => 'path/to/file-0.1.0.txt'
17
+ # paths.minimatch('file-0.2.0') # => 'path/to/file-0.2.0.txt'
18
+ # paths.minimatch('another_file') # => 'path/to/another_file.txt'
19
+ #
20
+ # More generally, Minimap may extend any object responding to each.
21
+ # Override the minikey method to convert objects into paths.
22
+ #
23
+ # class ConstantMap < Array
24
+ # include Minimap
25
+ #
26
+ # def minikey(const)
27
+ # const.underscore
28
+ # end
29
+ # end
30
+ #
31
+ # constants = ConstantMap[Tap::Support::Minimap Tap::Root]
32
+ # constants.minimatch('root') # => Tap::Root
33
+ # constants.minimatch('minimap') # => Tap::Support::Minimap
34
+ #
35
+ module Minimap
36
+
37
+ # Provides a minimized map of the entries using keys provided minikey.
38
+ #
39
+ # paths = %w{
40
+ # path/to/file-0.1.0.txt
41
+ # path/to/file-0.2.0.txt
42
+ # path/to/another_file.txt
43
+ # }.extend Minimap
44
+ #
45
+ # paths.minimap
46
+ # # => [
47
+ # # ['file-0.1.0', 'path/to/file-0.1.0.txt'],
48
+ # # ['file-0.2.0', 'path/to/file-0.2.0.txt'],
49
+ # # ['another_file','path/to/another_file.txt']]
50
+ #
51
+ def minimap
52
+ hash = {}
53
+ map = []
54
+ each {|entry| map << (hash[minikey(entry)] = [entry]) }
55
+ Tap::Root.minimize(hash.keys) do |key, mini_key|
56
+ hash[key].unshift mini_key
57
+ end
58
+
59
+ map
60
+ end
61
+
62
+ # Returns the first entry whose minikey mini-matches the input, or nil if
63
+ # no such entry exists.
64
+ #
65
+ # paths = %w{
66
+ # path/to/file-0.1.0.txt
67
+ # path/to/file-0.2.0.txt
68
+ # path/to/another_file.txt
69
+ # }.extend Minimap
70
+ #
71
+ # paths.minimatch('file-0.2.0') # => 'path/to/file-0.2.0.txt'
72
+ # paths.minimatch('file-0.3.0') # => nil
73
+ #
74
+ def minimatch(key)
75
+ each do |entry|
76
+ return entry if Tap::Root.minimal_match?(minikey(entry), key)
77
+ end
78
+ nil
79
+ end
80
+
81
+ protected
82
+
83
+ # A hook to convert a non-path entry into a path for minimap and
84
+ # minimatch. Returns the entry by default.
85
+ def minikey(entry)
86
+ entry
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,56 @@
1
+ module Tap
2
+ module Support
3
+
4
+ # Represents a task node in a Schema.
5
+ class Node
6
+
7
+ # An array of arguments used to instantiate
8
+ # the node
9
+ attr_accessor :argv
10
+
11
+ # The input or source for the node. Inputs
12
+ # may be a Join, nil, or an Integer. An
13
+ # Integer input indicates that the node should
14
+ # be enqued to a round using argv as inputs.
15
+ attr_accessor :input
16
+
17
+ # The output for the node. Output may be a
18
+ # a Join or nil.
19
+ attr_accessor :output
20
+
21
+ def initialize(argv=[], input=nil, output=nil)
22
+ @argv = argv
23
+ @input = input
24
+ @output = output
25
+ end
26
+
27
+ # Resets the source and join to nil.
28
+ def globalize
29
+ self.input = nil
30
+ self.output = nil
31
+ end
32
+
33
+ # True if the input and output are nil.
34
+ def global?
35
+ input == nil && output == nil
36
+ end
37
+
38
+ # Returns the round for self; a round is indicated
39
+ # by an integer input. If input is anything but
40
+ # an integer, round returns nil.
41
+ def round
42
+ input.kind_of?(Integer) ? input : nil
43
+ end
44
+
45
+ # Alias for input=
46
+ def round=(input)
47
+ self.input = input
48
+ end
49
+
50
+ def inspect
51
+ "#<#{self.class}:#{object_id} argv=[#{argv.join(' ')}] input=#{input.inspect} output=#{output.inspect}>"
52
+ end
53
+
54
+ end
55
+ end
56
+ end