bahuvrihi-tap 0.10.4 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/bin/rap +112 -0
  2. data/bin/tap +21 -10
  3. data/cmd/destroy.rb +1 -1
  4. data/cmd/generate.rb +1 -1
  5. data/cmd/run.rb +4 -48
  6. data/cmd/server.rb +3 -1
  7. data/lib/tap/constants.rb +1 -1
  8. data/lib/tap/env.rb +37 -39
  9. data/lib/tap/exe.rb +59 -29
  10. data/lib/tap/generator/base.rb +1 -1
  11. data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
  12. data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
  13. data/lib/tap/generator/generators/root/templates/README +0 -0
  14. data/lib/tap/generator/generators/root/templates/gemspec +3 -4
  15. data/lib/tap/generator/generators/root/templates/tapfile +3 -3
  16. data/lib/tap/parser.rb +35 -0
  17. data/lib/tap/patches/optparse/summarize.rb +62 -0
  18. data/lib/tap/root.rb +24 -18
  19. data/lib/tap/support/class_configuration.rb +1 -1
  20. data/lib/tap/support/configurable_class.rb +3 -1
  21. data/lib/tap/support/configuration.rb +19 -0
  22. data/lib/tap/support/constant.rb +14 -2
  23. data/lib/tap/support/declarations.rb +33 -39
  24. data/lib/tap/support/dependable.rb +21 -2
  25. data/lib/tap/support/gems.rb +4 -30
  26. data/lib/tap/support/gems/rack.rb +14 -11
  27. data/lib/tap/support/lazy_attributes.rb +1 -1
  28. data/lib/tap/support/lazydoc.rb +257 -340
  29. data/lib/tap/support/lazydoc/comment.rb +499 -0
  30. data/lib/tap/support/lazydoc/config.rb +17 -0
  31. data/lib/tap/support/lazydoc/declaration.rb +20 -0
  32. data/lib/tap/support/lazydoc/document.rb +118 -0
  33. data/lib/tap/support/lazydoc/method.rb +24 -0
  34. data/lib/tap/support/manifest.rb +33 -4
  35. data/lib/tap/support/validation.rb +56 -0
  36. data/lib/tap/task.rb +46 -44
  37. data/lib/tap/tasks/dump.rb +15 -10
  38. data/lib/tap/tasks/load.rb +25 -0
  39. data/lib/tap/tasks/rake.rb +2 -2
  40. data/lib/tap/test.rb +55 -36
  41. data/lib/tap/test/file_methods.rb +204 -178
  42. data/lib/tap/test/file_methods_class.rb +4 -18
  43. data/lib/tap/test/script_methods.rb +76 -90
  44. data/lib/tap/test/script_methods/regexp_escape.rb +92 -0
  45. data/lib/tap/test/script_methods/script_test.rb +4 -2
  46. data/lib/tap/test/subset_methods.rb +46 -49
  47. data/lib/tap/test/subset_methods_class.rb +17 -54
  48. data/lib/tap/test/tap_methods.rb +1 -5
  49. data/lib/tap/test/utils.rb +142 -32
  50. metadata +12 -3
  51. data/lib/tap/support/command_line.rb +0 -55
  52. data/lib/tap/support/comment.rb +0 -270
@@ -2,6 +2,8 @@ require 'tap/test/env_vars'
2
2
 
3
3
  module Tap
4
4
  module Test
5
+
6
+ # Class methods extending tests which include SubsetMethods.
5
7
  module SubsetMethodsClass
6
8
  include Tap::Test::EnvVars
7
9
 
@@ -14,51 +16,9 @@ module Tap
14
16
  subclass.instance_variable_set(:@conditions, subclass_conditions)
15
17
  subclass.instance_variable_set(:@run_test_suite, nil)
16
18
  subclass.instance_variable_set(:@skip_messages, [])
17
-
18
- # subclass_inputs = prompt_inputs.inject({}) do |memo, (key, value)|
19
- # memo.update(key => (value.dup rescue value))
20
- # end
21
- # subclass.instance_variable_set("@prompt_inputs", subclass_inputs)
22
19
  end
23
20
 
24
- # Experimental -- The idea is to provide a way to prompt once for inputs
25
- # that get used multiple times in a test. Perhaps create accessors
26
- # automatically?
27
-
28
- # def prompt_inputs
29
- # @prompt_inputs ||= {}
30
- # end
31
-
32
- # def require_inputs(*keys, &block)
33
- # if run_subset?("PROMPT")
34
- # puts "\n#{name} requires inputs -- Enter values or 'skip'."
35
-
36
- # argv = ARGV.dup
37
- # begin
38
- # ARGV.clear
39
- # keys.collect do |key|
40
- # print "#{key}: "
41
- # value = gets.strip
42
- # if value =~ /skip/i
43
- # skip_test "missing inputs"
44
- # break
45
- # end
46
- # prompt_inputs[key] = value
47
- # end
48
- # ensure
49
- # ARGV.clear
50
- # ARGV.concat(argv)
51
- # end
52
- # else
53
- # skip_test "prompt test"
54
- # end
55
- # end
56
-
57
- #
58
- # conditions
59
- #
60
-
61
- # A hash of defined conditions
21
+ # A hash of [name, [msg, condition_block]] pairs defined by condition.
62
22
  def conditions
63
23
  @conditions ||= {}
64
24
  end
@@ -66,34 +26,37 @@ module Tap
66
26
  # Defines a condition block and associated message.
67
27
  # Raises an error if no condition block is given.
68
28
  def condition(name, msg=nil, &block)
69
- raise "no condition block given" unless block_given?
70
- conditions[name.to_sym] = [msg, block]
29
+ raise ArgumentError, "no condition block given" unless block_given?
30
+ conditions[name] = [msg, block]
71
31
  end
72
32
 
73
- # Returns true if the all blocks for the named conditions return true.
33
+ # Returns true if the all blocks for the specified conditions return true.
74
34
  #
75
35
  # condition(:is_true) { true }
76
36
  # condition(:is_false) { false }
77
37
  # satisfied?(:is_true) # => true
78
38
  # satisfied?(:is_true, :is_false) # => false
79
39
  #
80
- def satisfied?(*conditions)
81
- unsatisfied_conditions(*conditions).empty?
40
+ def satisfied?(*names)
41
+ unsatisfied_conditions(*names).empty?
82
42
  end
83
43
 
84
44
  # Returns an array of the unsatified conditions. Raises
85
- # an error if the named condition has not been defined.
45
+ # an error if a condition has not been defined.
86
46
  #
87
47
  # condition(:is_true) { true }
88
48
  # condition(:is_false) { false }
89
49
  # unsatisfied_conditions(:is_true, :is_false) # => [:is_false]
90
50
  #
91
- def unsatisfied_conditions(*conditions)
92
- conditions = self.conditions.keys if conditions.empty?
51
+ def unsatisfied_conditions(*condition_names)
52
+ condition_names = conditions.keys if condition_names.empty?
93
53
  unsatified = []
94
- conditions.each do |condition|
95
- raise "Unknown condition: #{condition}" unless self.conditions.has_key?(condition)
96
- unsatified << condition unless (self.conditions[condition.to_sym].last.call() ? true : false)
54
+ condition_names.each do |name|
55
+ unless condition = conditions[name]
56
+ raise ArgumentError, "Unknown condition: #{name}"
57
+ end
58
+
59
+ unsatified << name unless condition.last.call
97
60
  end
98
61
  unsatified
99
62
  end
@@ -162,11 +162,7 @@ module Tap
162
162
 
163
163
  # The configurations used to initialize self.app
164
164
  def app_config
165
- { :root => method_root,
166
- :directories => trs.directories,
167
- :absolute_paths => trs.absolute_paths,
168
- :quiet => true,
169
- :debug => true}
165
+ method_root.config.to_hash.merge(:quiet => true, :debug => true)
170
166
  end
171
167
 
172
168
  # Reconfigures app with the input configurations for the
@@ -1,22 +1,31 @@
1
1
  require 'tap/root'
2
2
  require 'fileutils'
3
+ require 'tempfile'
3
4
 
4
5
  module Tap
6
+ module Support
7
+ autoload(:Templater, 'tap/support/templater')
8
+ end
9
+
5
10
  module Test
6
11
  module Utils
7
12
  module_function
8
13
 
9
14
  # Generates an array of [source, reference] pairs mapping source
10
- # files to reference files under the source_dir and reference_dir,
11
- # respectively. Only files under source dir with the reference_extname
12
- # will be mapped; mappings are either:
15
+ # files to reference files under the source and reference dirs,
16
+ # respectively. Only files under source dir matching the pattern
17
+ # will be mapped. Mappings are either (in this order):
13
18
  #
14
- # - a direct translation from source_dir to reference_dir, minus
15
- # the extname
16
- # - a path under reference_dir with a matching basename, minus
17
- # the extname, so long as the matched path is unique
19
+ # - the path under reference_dir contained in the source file
20
+ # - a direct translation of the source file from the source to
21
+ # the reference dir, minus the extname
18
22
  #
19
- # If a mapped path cannot be found, dereference raises an ArgumentError.
23
+ # Notes:
24
+ # - Source files may contain comments but should otherwise
25
+ # consist only of indentation (which is stripped) and
26
+ # the reference path.
27
+ # - If a mapped path cannot be found, dereference raises
28
+ # a DereferenceError.
20
29
  #
21
30
  # === example
22
31
  #
@@ -33,51 +42,114 @@ module Tap
33
42
  # `- to
34
43
  # `- two.txt
35
44
  #
45
+ # The 'two.txt.ref' file contains a reference path:
46
+ #
47
+ # File.read('/root/input/two.txt.ref') # => 'path/to/two.txt'
48
+ #
49
+ # Now:
50
+ #
36
51
  # reference_map('/root/input', '/root/ref')
37
52
  # # => [
38
53
  # # ['/root/input/dir.ref', '/root/ref/dir'],
39
54
  # # ['/root/input/one.txt.ref', '/root/ref/one.txt'],
40
55
  # # ['/root/input/two.txt.ref', '/root/ref/path/to/two.txt']]
41
56
  #
42
- # reference_map(:input, :ref, ".txt") # !> ArgumentError
57
+ # And since no path matches 'ignored.txt':
43
58
  #
44
- def reference_map(source_dir, reference_dir, reference_extname='.ref')
45
- Dir.glob(File.join(source_dir, "**/*#{reference_extname}")).collect do |path|
46
- relative_path = Tap::Root.relative_filepath(source_dir, path).chomp(reference_extname)
47
- reference_path = File.join(reference_dir, relative_path)
48
-
49
- unless File.exists?(reference_path)
50
- matching_paths = Dir.glob(File.join(reference_dir, "**/#{File.basename(relative_path)}"))
51
-
52
- reference_path = case matching_paths.length
53
- when 0 then raise ArgumentError, "no reference found for: #{path}"
54
- when 1 then matching_paths[0]
55
- else raise ArgumentError, "multiple references found for: #{path} [#{matching_paths.join(', ')}]"
56
- end
59
+ # reference_map('/root/input', '/root/ref', '**/*.txt')
60
+ # # !> DereferenceError
61
+ #
62
+ def reference_map(source_dir, reference_dir, pattern='**/*.ref')
63
+ Dir.glob(File.join(source_dir, pattern)).collect do |source|
64
+ # use the path specified in the source file
65
+ relative_path = File.read(source).gsub(/#.*$/, "").strip
66
+
67
+ # use the relative filepath of the source file to the
68
+ # source dir (minus the extname) if no path is specified
69
+ if relative_path.empty?
70
+ relative_path = Tap::Root.relative_filepath(source_dir, source).chomp(File.extname(source))
71
+ end
72
+
73
+ reference = File.join(reference_dir, relative_path)
74
+
75
+ # raise an error if no reference file is found
76
+ unless File.exists?(reference)
77
+ raise DereferenceError, "no reference found for: #{source}"
57
78
  end
58
79
 
59
- [path, reference_path]
80
+ [source, reference]
60
81
  end
61
82
  end
62
83
 
63
- def dereference(source_dirs, reference_dir, extname='.ref')
84
+ # Dereferences source files with reference files for the duration
85
+ # of the block. The mappings of source to reference files are
86
+ # determined using reference_map; dereferenced files are at the
87
+ # same location as the source files, but with the '.ref' extname
88
+ # removed.
89
+ #
90
+ # Notes:
91
+ # - The reference extname is implicitly specified in pattern;
92
+ # the final extname of the source file is removed during
93
+ # dereferencing regardless of what it is.
94
+ #
95
+ def dereference(source_dirs, reference_dir, pattern='**/*.ref', tempdir=Dir::tmpdir)
64
96
  mapped_paths = []
65
97
  begin
66
98
  [*source_dirs].each do |source_dir|
67
- reference_map(source_dir, reference_dir, extname).each do |path, source|
68
- FileUtils.rm_r(path)
69
- target = path.chomp(extname)
70
- FileUtils.cp_r(source, target)
71
- mapped_paths << target
99
+ reference_map(source_dir, reference_dir, pattern).each do |source, reference|
100
+
101
+ # move the source file to a temporary location
102
+ tempfile = Tempfile.new(File.basename(source), tempdir)
103
+ tempfile.close
104
+ FileUtils.mv(source, tempfile.path)
105
+
106
+ # copy the reference to the target
107
+ target = source.chomp(File.extname(source))
108
+ FileUtils.cp_r(reference, target)
109
+
110
+ mapped_paths << [target, source, tempfile]
72
111
  end
73
112
  end unless reference_dir == nil
74
113
 
75
114
  yield
76
115
 
77
116
  ensure
78
- mapped_paths.each do |path|
79
- FileUtils.rm_r(path) if File.exists?(path)
80
- FileUtils.touch(path + extname)
117
+ mapped_paths.each do |target, source, tempfile|
118
+ # remove the target and restore the original source file
119
+ FileUtils.rm_r(target) if File.exists?(target)
120
+ FileUtils.mv(tempfile.path, source)
121
+ end
122
+ end
123
+ end
124
+
125
+ # Uses a Tap::Support::Templater to template and replace the contents of path,
126
+ # for the duration of the block. The attributes will be available in the
127
+ # template context.
128
+ def template(paths, attributes={}, tempdir=Dir::tmpdir)
129
+ mapped_paths = []
130
+ begin
131
+ [*paths].each do |path|
132
+ # move the source file to a temporary location
133
+ tempfile = Tempfile.new(File.basename(path), tempdir)
134
+ tempfile.close
135
+ FileUtils.cp(path, tempfile.path)
136
+
137
+ # template the source file
138
+ content = File.read(path)
139
+ File.open(path, "wb") do |file|
140
+ file << Support::Templater.new(content, attributes).build
141
+ end
142
+
143
+ mapped_paths << [path, tempfile]
144
+ end
145
+
146
+ yield
147
+
148
+ ensure
149
+ mapped_paths.each do |path, tempfile|
150
+ # restore the original source file
151
+ FileUtils.rm(path) if File.exists?(path)
152
+ FileUtils.mv(tempfile.path, path)
81
153
  end
82
154
  end
83
155
  end
@@ -102,6 +174,13 @@ module Tap
102
174
  end
103
175
  end
104
176
 
177
+ # Attempts to recursively remove the specified method directory and all
178
+ # files within it. Raises an error if the removal does not succeed.
179
+ def clear_dir(dir)
180
+ # clear out the folder if it exists
181
+ FileUtils.rm_r(dir) if File.exists?(dir)
182
+ end
183
+
105
184
  # Attempts to remove the specified directory. The root
106
185
  # will not be removed if the directory does not exist, or
107
186
  # is not empty.
@@ -113,6 +192,37 @@ module Tap
113
192
  # rescue cases where there is a hidden file, for example .svn
114
193
  end
115
194
  end
195
+
196
+ # Sets ARGV to the input argv for the duration of the block.
197
+ def with_argv(argv=[])
198
+ current_argv = ARGV.dup
199
+ begin
200
+ ARGV.clear
201
+ ARGV.concat(argv)
202
+
203
+ yield
204
+
205
+ ensure
206
+ ARGV.clear
207
+ ARGV.concat(current_argv)
208
+ end
209
+ end
210
+
211
+ def whitespace_escape(str)
212
+ str.to_s.gsub(/\s/) do |match|
213
+ case match
214
+ when "\n" then "\\n\n"
215
+ when "\t" then "\\t"
216
+ when "\r" then "\\r"
217
+ when "\f" then "\\f"
218
+ else match
219
+ end
220
+ end
221
+ end
222
+
223
+ # Raised when no reference can be found for a reference path.
224
+ class DereferenceError < StandardError
225
+ end
116
226
  end
117
227
  end
118
228
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bahuvrihi-tap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.4
4
+ version: 0.10.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiang
@@ -17,6 +17,7 @@ description:
17
17
  email: simon.a.chiang@gmail.com
18
18
  executables:
19
19
  - tap
20
+ - rap
20
21
  extensions: []
21
22
 
22
23
  extra_rdoc_files:
@@ -40,6 +41,7 @@ files:
40
41
  - doc/Tutorial
41
42
  - doc/Class Reference
42
43
  - doc/Command Reference
44
+ - bin/rap
43
45
  - bin/tap
44
46
  - lib/tap/app.rb
45
47
  - lib/tap/constants.rb
@@ -60,6 +62,7 @@ files:
60
62
  - lib/tap/generator/generators/file_task/templates/task.erb
61
63
  - lib/tap/generator/generators/file_task/templates/test.erb
62
64
  - lib/tap/generator/generators/root/root_generator.rb
65
+ - lib/tap/generator/generators/root/templates/README
63
66
  - lib/tap/generator/generators/root/templates/Rakefile
64
67
  - lib/tap/generator/generators/root/templates/tapfile
65
68
  - lib/tap/generator/generators/root/templates/gemspec
@@ -71,6 +74,7 @@ files:
71
74
  - lib/tap/generator/generators/task/templates/test.erb
72
75
  - lib/tap/generator/manifest.rb
73
76
  - lib/tap/parser.rb
77
+ - lib/tap/patches/optparse/summarize.rb
74
78
  - lib/tap/patches/rake/rake_test_loader.rb
75
79
  - lib/tap/patches/rake/testtask.rb
76
80
  - lib/tap/patches/ruby19/backtrace_filter.rb
@@ -88,8 +92,6 @@ files:
88
92
  - lib/tap/support/batchable_class.rb
89
93
  - lib/tap/support/class_configuration.rb
90
94
  - lib/tap/support/combinator.rb
91
- - lib/tap/support/command_line.rb
92
- - lib/tap/support/comment.rb
93
95
  - lib/tap/support/configurable.rb
94
96
  - lib/tap/support/configurable_class.rb
95
97
  - lib/tap/support/configuration.rb
@@ -105,6 +107,11 @@ files:
105
107
  - lib/tap/support/instance_configuration.rb
106
108
  - lib/tap/support/lazy_attributes.rb
107
109
  - lib/tap/support/lazydoc.rb
110
+ - lib/tap/support/lazydoc/comment.rb
111
+ - lib/tap/support/lazydoc/config.rb
112
+ - lib/tap/support/lazydoc/declaration.rb
113
+ - lib/tap/support/lazydoc/document.rb
114
+ - lib/tap/support/lazydoc/method.rb
108
115
  - lib/tap/support/manifest.rb
109
116
  - lib/tap/support/parsers/base.rb
110
117
  - lib/tap/support/parsers/server.rb
@@ -118,11 +125,13 @@ files:
118
125
  - lib/tap/support/versions.rb
119
126
  - lib/tap/task.rb
120
127
  - lib/tap/tasks/dump.rb
128
+ - lib/tap/tasks/load.rb
121
129
  - lib/tap/tasks/rake.rb
122
130
  - lib/tap/test/env_vars.rb
123
131
  - lib/tap/test/file_methods.rb
124
132
  - lib/tap/test/file_methods_class.rb
125
133
  - lib/tap/test/script_methods.rb
134
+ - lib/tap/test/script_methods/regexp_escape.rb
126
135
  - lib/tap/test/script_methods/script_test.rb
127
136
  - lib/tap/test/subset_methods.rb
128
137
  - lib/tap/test/subset_methods_class.rb
@@ -1,55 +0,0 @@
1
- require 'optparse'
2
-
3
- module Tap
4
- module Support
5
-
6
- # Under Construction
7
- module CommandLine
8
- module_function
9
-
10
- def usage(path, cols=80)
11
- parse_usage(File.read(path), cols)
12
- end
13
-
14
- def parse_usage(str, cols=80)
15
- scanner = StringScanner.new(str)
16
- scanner.scan(/^#!.*?$/)
17
- Comment.parse(scanner, false).wrap(cols, 2).strip
18
- end
19
-
20
- def configv(config)
21
- desc = config.desc
22
- desc.extend(OptParseComment) if desc.kind_of?(Comment)
23
-
24
- [config.short, argtype(config), desc].compact
25
- end
26
-
27
- def argtype(config)
28
- case config.arg_type
29
- when :optional
30
- "#{config.long} [#{config.arg_name}]"
31
- when :switch
32
- config.long(true)
33
- when :flag
34
- config.long
35
- when :list
36
- "#{config.long} a,b,c"
37
- when :mandatory, nil
38
- "#{config.long} #{config.arg_name}"
39
- else
40
- raise "unknown arg_type: #{config.arg_type}"
41
- end
42
- end
43
-
44
- module OptParseComment
45
- def empty?
46
- to_str.empty?
47
- end
48
-
49
- def to_str
50
- subject.to_s =~ /#(.*)$/ ? $1.strip : ""
51
- end
52
- end
53
- end
54
- end
55
- end