bahuvrihi-tap 0.10.7 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/MIT-LICENSE +0 -2
  2. data/README +20 -31
  3. data/bin/rap +18 -8
  4. data/cgi/run.rb +47 -37
  5. data/cmd/console.rb +1 -1
  6. data/cmd/destroy.rb +3 -3
  7. data/cmd/generate.rb +3 -3
  8. data/cmd/manifest.rb +61 -53
  9. data/cmd/run.rb +1 -1
  10. data/doc/Class Reference +119 -110
  11. data/doc/Command Reference +76 -123
  12. data/doc/Syntax Reference +290 -0
  13. data/doc/Tutorial +307 -237
  14. data/lib/tap.rb +1 -12
  15. data/lib/tap/app.rb +46 -71
  16. data/lib/tap/constants.rb +1 -1
  17. data/lib/tap/declarations.rb +110 -100
  18. data/lib/tap/env.rb +141 -173
  19. data/lib/tap/exe.rb +5 -5
  20. data/lib/tap/file_task.rb +2 -2
  21. data/lib/tap/generator/base.rb +0 -4
  22. data/lib/tap/generator/destroy.rb +8 -12
  23. data/lib/tap/generator/generate.rb +19 -14
  24. data/lib/tap/generator/generators/command/command_generator.rb +1 -1
  25. data/lib/tap/generator/generators/config/config_generator.rb +3 -3
  26. data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
  27. data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
  28. data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
  29. data/lib/tap/generator/generators/root/root_generator.rb +12 -12
  30. data/lib/tap/generator/generators/root/templates/Rakefile +1 -2
  31. data/lib/tap/generator/generators/root/templates/tapfile +11 -8
  32. data/lib/tap/generator/generators/task/task_generator.rb +1 -3
  33. data/lib/tap/generator/generators/task/templates/test.erb +1 -3
  34. data/lib/tap/root.rb +4 -2
  35. data/lib/tap/support/aggregator.rb +16 -3
  36. data/lib/tap/support/assignments.rb +10 -9
  37. data/lib/tap/support/audit.rb +58 -62
  38. data/lib/tap/support/class_configuration.rb +32 -43
  39. data/lib/tap/support/combinator.rb +7 -7
  40. data/lib/tap/support/configurable.rb +13 -14
  41. data/lib/tap/support/configurable_class.rb +6 -30
  42. data/lib/tap/support/configuration.rb +36 -9
  43. data/lib/tap/support/constant.rb +75 -13
  44. data/lib/tap/support/constant_manifest.rb +115 -0
  45. data/lib/tap/support/dependencies.rb +27 -67
  46. data/lib/tap/support/dependency.rb +44 -0
  47. data/lib/tap/support/executable.rb +78 -109
  48. data/lib/tap/support/executable_queue.rb +1 -1
  49. data/lib/tap/support/gems.rb +6 -0
  50. data/lib/tap/support/gems/rack.rb +197 -84
  51. data/lib/tap/support/instance_configuration.rb +29 -3
  52. data/lib/tap/support/intern.rb +46 -0
  53. data/lib/tap/support/join.rb +67 -11
  54. data/lib/tap/support/joins.rb +2 -0
  55. data/lib/tap/support/joins/fork.rb +1 -0
  56. data/lib/tap/support/joins/merge.rb +3 -1
  57. data/lib/tap/support/joins/sequence.rb +2 -2
  58. data/lib/tap/support/joins/switch.rb +3 -1
  59. data/lib/tap/support/joins/sync_merge.rb +6 -0
  60. data/lib/tap/support/lazy_attributes.rb +16 -1
  61. data/lib/tap/support/lazydoc.rb +21 -21
  62. data/lib/tap/support/lazydoc/comment.rb +59 -55
  63. data/lib/tap/support/lazydoc/definition.rb +36 -0
  64. data/lib/tap/support/lazydoc/document.rb +37 -13
  65. data/lib/tap/support/manifest.rb +120 -131
  66. data/lib/tap/support/minimap.rb +90 -0
  67. data/lib/tap/support/node.rb +4 -6
  68. data/lib/tap/support/parser.rb +63 -6
  69. data/lib/tap/support/schema.rb +11 -2
  70. data/lib/tap/support/shell_utils.rb +3 -5
  71. data/lib/tap/support/string_ext.rb +60 -0
  72. data/lib/tap/support/tdoc.rb +2 -2
  73. data/lib/tap/support/templater.rb +29 -15
  74. data/lib/tap/support/validation.rb +22 -11
  75. data/lib/tap/task.rb +155 -156
  76. data/lib/tap/tasks/load.rb +95 -8
  77. data/lib/tap/test/extensions.rb +2 -1
  78. data/lib/tap/test/script_tester.rb +7 -1
  79. data/template/index.erb +39 -32
  80. metadata +13 -13
  81. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
  82. data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
  83. data/lib/tap/patches/rake/testtask.rb +0 -57
  84. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
  85. data/lib/tap/patches/ruby19/parsedate.rb +0 -16
  86. data/lib/tap/spec.rb +0 -42
  87. data/lib/tap/spec/adapter.rb +0 -25
  88. data/lib/tap/spec/inheritable_class_test_root.rb +0 -9
  89. data/lib/tap/support/constant_utils.rb +0 -127
  90. data/lib/tap/support/summary.rb +0 -30
@@ -1,6 +1,4 @@
1
- require 'tap/support/manifest'
2
- require 'tap/support/constant'
3
- require 'tap/support/summary'
1
+ require 'tap/support/constant_manifest'
4
2
  require 'tap/support/gems'
5
3
 
6
4
  module Tap
@@ -9,8 +7,9 @@ module Tap
9
7
  # Note that gems and env_paths reset envs -- custom modifications to envs will be lost
10
8
  # whenever these configs are reset.
11
9
  class Env
12
- include Support::Configurable
13
10
  include Enumerable
11
+ include Support::Configurable
12
+ include Support::Minimap
14
13
 
15
14
  class << self
16
15
 
@@ -26,13 +25,6 @@ module Tap
26
25
  @@instances
27
26
  end
28
27
 
29
- # A hash of predefined manifest classes that can be initialized
30
- # from an env. These classes are instantiated by instances
31
- # of Env, as needed.
32
- def manifests
33
- @@manifests
34
- end
35
-
36
28
  # Creates a new Env for the specified path and adds it to Env#instances, or
37
29
  # returns the existing instance for the path. Paths can point to an env config
38
30
  # file, or to a directory. If a directory is provided, instantiate treats
@@ -77,50 +69,11 @@ module Tap
77
69
  File.expand_path(path)
78
70
  end
79
71
 
80
- def manifest(name, pattern, default_paths=[], &block) # :yields: search_path
81
- manifest_class = Class.new(Support::Manifest)
82
- manifest_class.send(:define_method, :entries_for, &block) if block_given?
83
- manifest_class.send(:attr_reader, :env)
84
- manifest_class.send(:define_method, :initialize) do |env|
85
- @env = env
86
- search_paths = default_paths.collect {|path| env.root[path] }
87
- search_paths += env.root.glob(:root, pattern)
88
- super search_paths.sort_by {|p| File.basename(p) }
72
+ def manifest(name, &block) # :yields: env (returns manifest)
73
+ name = name.to_sym
74
+ define_method(name) do
75
+ self.manifests[name] ||= block.call(self).bind(self, name)
89
76
  end
90
-
91
- manifests[name] = manifest_class
92
- end
93
-
94
- #--
95
- # To manifest simply requires an glob_<name> method which
96
- # yields each (key, path) pair for the manifested object in
97
- # a predictable order.
98
- #
99
- #--
100
- # Alternate implementation would create the manifest for each individual
101
- # env, then merge the manifests. On the plus side, each env would then
102
- # carry it's own slice of the manifest without having to recalculate.
103
- # On the down side, the merging would have to occur in some separate
104
- # method that cannot be defined here.
105
- def path_manifest(name, paths_key, pattern, default_paths=[], &block) # :yields: search_path_root, search_path
106
- manifest_class = Class.new(Support::Manifest)
107
- manifest_class.send(:define_method, :entries_for, &block) if block_given?
108
- manifest_class.send(:attr_reader, :env)
109
- manifest_class.send(:define_method, :initialize) do |env|
110
- @env = env
111
- search_paths = default_paths.collect do |path|
112
- [env.root.root, env.root[path]]
113
- end
114
-
115
- env.send(paths_key).each do |search_path_root|
116
- env.root.glob(search_path_root, pattern).each do |search_path|
117
- search_paths << [search_path_root, search_path]
118
- end
119
- end
120
-
121
- super search_paths.sort_by {|pr, p| File.basename(p) }
122
- end
123
- manifests[name] = manifest_class
124
77
  end
125
78
 
126
79
  # Returns the gemspecs for all installed gems with a DEFAULT_CONFIG_FILE.
@@ -134,19 +87,6 @@ module Tap
134
87
 
135
88
  protected
136
89
 
137
- # Defines a config that raises an error if set when the
138
- # instance is active. static_config MUST take a block
139
- # and raises an error if a block is not given.
140
- def static_config(key, value=nil, &block)
141
- raise ArgumentError.new("active config requires block") unless block_given?
142
-
143
- instance_variable = "@#{key}".to_sym
144
- config_attr(key, value) do |input|
145
- check_configurable
146
- instance_variable_set(instance_variable, block.call(input))
147
- end
148
- end
149
-
150
90
  # Defines a config that collects the input into a unique,
151
91
  # compact array where each member has been resolved using
152
92
  # root[]. In short, ['lib', nil, 'lib', 'alt] becomes
@@ -164,17 +104,9 @@ module Tap
164
104
  end
165
105
  end
166
106
 
167
- class Manifest < Support::Manifest
168
- def initialize(env)
169
- super([])
170
- @entries = env.collect {|e| [e.root.root, e] }
171
- end
172
- end
173
-
174
107
  @@instance = nil
175
108
  @@instances = {}
176
- @@manifests = {:envs => Manifest}
177
-
109
+
178
110
  # The default config file path
179
111
  DEFAULT_CONFIG_FILE = "tap.yml"
180
112
 
@@ -184,9 +116,6 @@ module Tap
184
116
  # Gets or sets the logger for self
185
117
  attr_accessor :logger
186
118
 
187
- # A hash of the manifests for self.
188
- attr_reader :manifests
189
-
190
119
  # Specify files to require when self is activated.
191
120
  config :requires, [], &c.array_or_nil
192
121
 
@@ -244,30 +173,37 @@ module Tap
244
173
  # Designate paths for discovering generators.
245
174
  path_config :generator_paths, ["lib"]
246
175
 
247
- path_manifest(:tasks, :load_paths, "**/*.rb") do |load_path, path|
248
- next unless File.file?(path) && document = Support::Lazydoc.scan_doc(path, 'manifest')
249
-
250
- document.default_const_name = env.root.relative_filepath(load_path, path).chomp('.rb').camelize
251
- document.const_names.collect do |const_name|
252
- [const_name.underscore, Support::Constant.new(const_name, path)]
176
+ manifest(:commands) do |env|
177
+ paths = []
178
+ env.command_paths.each do |path_root|
179
+ paths.concat env.root.glob(path_root)
253
180
  end
181
+
182
+ paths = paths.sort_by {|path| File.basename(path) }
183
+ Support::Manifest.new(paths)
254
184
  end
255
185
 
256
- path_manifest(:commands, :command_paths, "**/*.rb") do |command_path, path|
257
- File.file?(path) ? [[path, path]] : nil
186
+ manifest(:tasks) do |env|
187
+ tasks = Support::ConstantManifest.new('manifest')
188
+ env.load_paths.each do |path_root|
189
+ tasks.register(path_root, '**/*.rb')
190
+ end
191
+ # tasks.cache = env.cache[:tasks]
192
+ tasks
258
193
  end
259
-
260
- path_manifest(:generators, :generator_paths, '**/*_generator.rb') do |generator_path, path|
261
- dirname = File.dirname(path)
262
- next unless File.file?(path) && "#{File.basename(dirname)}_generator.rb" == File.basename(path)
194
+
195
+ manifest(:generators) do |env|
196
+ generators = Support::ConstantManifest.intern('generator') do |manifest, const|
197
+ const.name.underscore.chomp('_generator')
198
+ end
263
199
 
264
- next unless document = Support::Lazydoc.scan_doc(path, 'generator')
265
- document.default_const_name = "#{env.root.relative_filepath(generator_path, dirname)}_generator".camelize
266
- document.const_names.collect do |const_name|
267
- [const_name.underscore.chomp('_generator'), Support::Constant.new(const_name, path)]
200
+ env.generator_paths.each do |path_root|
201
+ generators.register(path_root, '**/*_generator.rb')
268
202
  end
203
+ # generators.cache = env.cache[:generators]
204
+ generators
269
205
  end
270
-
206
+
271
207
  def initialize(config={}, root=Tap::Root.new, logger=nil)
272
208
  @root = root
273
209
  @logger = logger
@@ -507,96 +443,128 @@ module Tap
507
443
  @active
508
444
  end
509
445
 
510
- # Returns the manifest in manifests by the specified name. Yields
511
- # each entry in the manifest to the block, if given, or simply
512
- # builds and returns the manifest.
446
+ # Searches each env for the first existing file or directory at
447
+ # env.root.filepath(dir, path). Paths are expanded, and search_path
448
+ # checks to make sure the file is, in fact, relative to env.root[dir].
449
+ # An optional block may be used to check the file; the file will only
450
+ # be returned if the block returns true.
513
451
  #
514
- # If the specified manifest does not exists, the manifest class
515
- # in self.class.manifests will be instatiated with self to make
516
- # the manifest. Raises an error if no manifest could be found
517
- # or instantiated.
518
- def manifest(name, build=false)
519
- manifest = manifests[name] ||= case
520
- when manifests_class = self.class.manifests[name]
521
- manifests_class.new(self)
522
- else
523
- raise "unknown manifest: #{name}"
524
- end
525
-
526
- manifest.build if build
527
- manifest
452
+ # Returns nil if no file can be found.
453
+ # def search_path(dir, path)
454
+ # each do |env|
455
+ # directory = env.root.filepath(dir)
456
+ # file = env.root.filepath(dir, path)
457
+ #
458
+ # # check the file is relative to the
459
+ # # directory, and that the file exists.
460
+ # if file.rindex(directory, 0) == 0 &&
461
+ # File.exists?(file) &&
462
+ # (!block_given? || yield(file))
463
+ # return file
464
+ # end
465
+ # end
466
+ #
467
+ # nil
468
+ # end
469
+
470
+ # def reset(name, &block)
471
+ # each do |env|
472
+ # env.manifests[name].each(&block)
473
+ # env.manifests[name] = nil
474
+ # end
475
+ # end
476
+
477
+ TEMPLATES = {
478
+ :commands => %Q{<% if count > 1 %>
479
+ <%= env_name %>:
480
+ <% end %>
481
+ <% entries.each do |name, const| %>
482
+ <%= name.ljust(width) %>
483
+ <% end %>},
484
+
485
+ :tasks => %Q{<% if count > 1 %>
486
+ <%= env_name %>:
487
+ <% end %>
488
+ <% entries.each do |name, const| %>
489
+ <% desc = const.document[const.name]['manifest'] %>
490
+ <%= name.ljust(width) %><%= desc.empty? ? '' : ' # ' %><%= desc %>
491
+ <% end %>},
492
+
493
+ :generators => %Q{<% if count > 1 %>
494
+ <%= env_name %>:
495
+ <% end %>
496
+ <% entries.each do |name, const| %>
497
+ <% desc = const.document[const.name]['generator'] %>
498
+ <%= name.ljust(width) %><%= desc.empty? ? '' : ' # ' %><%= desc %>
499
+ <% end %>}
500
+ }
501
+
502
+ def summarize(name, template=TEMPLATES[name])
503
+ count = 0
504
+ width = 10
505
+
506
+ env_names = {}
507
+ minimap.each do |env_name, env|
508
+ env_names[env] = env_name
509
+ end
510
+
511
+ inspect(template) do |templater, share|
512
+ env = templater.env
513
+ entries = env.send(name).minimap
514
+ next(false) if entries.empty?
515
+
516
+ templater.env_name = env_names[env]
517
+ templater.entries = entries
518
+
519
+ count += 1
520
+ entries.each do |entry_name, entry|
521
+ width = entry_name.length if width < entry_name.length
522
+ end
523
+
524
+ share[:count] = count
525
+ share[:width] = width
526
+ true
527
+ end
528
528
  end
529
529
 
530
- # Returns the first value in the specified manifest where the key
531
- # mini-matches the input pattern. See Tap::Root.minimal_match?
532
- # for details on mini-matching.
533
- def find(name, pattern, value_only=true)
534
- return nil unless entry = manifest(name)[pattern]
535
- value_only ? entry[1] : entry
530
+ def inspect(template=nil) # :yields: templater, attrs
531
+ return "#<#{self.class}:#{object_id} root='#{root.root}'>" if template == nil
532
+
533
+ attrs = {}
534
+ collect do |env|
535
+ templater = Support::Templater.new(template, :env => env)
536
+ block_given? ? (yield(templater, attrs) ? templater : nil) : templater
537
+ end.compact.collect do |templater|
538
+ templater.build(attrs)
539
+ end.join
536
540
  end
537
541
 
538
- # Like find, but searches across all envs for the matching value.
539
- # An env pattern can be provided in pattern, to select a single
540
- # env to search.
541
- #
542
- # The :envs manifest cannot be searched; use find instead.
543
- def search(name, pattern, value_only=true)
544
- if name == :envs
545
- raise ArgumentError, "cannot search the :envs manifest; use find instead"
546
- end
542
+ def recursive_inspect(template=nil, *args) # :yields: templater, attrs
543
+ return "#<#{self.class}:#{object_id} root='#{root.root}'>" if template == nil
547
544
 
548
- envs = case pattern
549
- when /^(.*):([^:]+)$/
550
- env_pattern = $1
551
- pattern = $2
552
- find(:envs, env_pattern)
553
- else manifest(:envs).values
545
+ attrs = {}
546
+ templaters = []
547
+ recursive_each(*args) do |env, *argv|
548
+ templater = Support::Templater.new(template, :env => env)
549
+ next_args = block_given? ? yield(templater, attrs, *argv) : argv
550
+ templaters << templater if next_args
551
+
552
+ next_args
554
553
  end
555
554
 
556
- envs.each do |env|
557
- if result = env.find(name, pattern, value_only)
558
- return result
559
- end
560
- end if envs
561
-
562
- nil
563
- end
564
-
565
- def reset(name, &block)
566
- each do |env|
567
- env.manifests[name].each(&block)
568
- env.manifests[name] = nil
569
- end
555
+ templaters.collect do |templater|
556
+ templater.build(attrs)
557
+ end.join
570
558
  end
571
559
 
572
- def constantize(name, *patterns)
573
- patterns.collect do |pattern|
574
- case const = search(name, pattern)
575
- when Support::Constant then const.constantize
576
- else raise "could not constantize: #{pattern} (#{name})"
577
- end
578
- end
579
- end
560
+ protected
580
561
 
581
- def summary(name)
582
- summary = Support::Summary.new
583
- manifest(:envs, true).minimize.each do |(key, env)|
584
- summary.add(key, env, env.manifest(name, true).minimize)
585
- end
586
- summary
587
- end
562
+ # A hash of the manifests for self.
563
+ attr_reader :manifests
588
564
 
589
- def summarize(name, &block)
590
- lines = summary(name).lines(&block)
591
- lines << "=== no #{name} found" if lines.empty?
592
- lines.join("\n")
565
+ def minikey(env)
566
+ env.root.root
593
567
  end
594
-
595
- def inspect
596
- "#<#{self.class}:#{object_id} root='#{root.root}'>"
597
- end
598
-
599
- protected
600
568
 
601
569
  # Raises an error if self is already active (and hence, configurations
602
570
  # should not be modified)
@@ -17,9 +17,9 @@ module Tap
17
17
 
18
18
  # add the default tap instance
19
19
  tap = instance_for("#{File.dirname(__FILE__)}/../..")
20
- tap.manifest(:tasks).search_paths = tap.root.glob(:lib, "tap/tasks/*").collect do |task_path|
21
- [tap.root[:lib], task_path]
22
- end
20
+ # tap.tasks.paths = tap.root.glob(:lib, "tap/tasks/*").collect do |task_path|
21
+ # [tap.root[:lib], task_path]
22
+ # end
23
23
  exe.push(tap)
24
24
  exe
25
25
  end
@@ -64,7 +64,7 @@ module Tap
64
64
  when '', '--help'
65
65
  yield
66
66
  else
67
- if path = search(:commands, command)
67
+ if path = commands.search(command)
68
68
  load path # run the command, if it exists
69
69
  else
70
70
  puts "Unknown command: '#{command}'"
@@ -76,7 +76,7 @@ module Tap
76
76
  def build(argv=ARGV)
77
77
  Support::Schema.parse(argv).compact.build(app) do |args|
78
78
  task = args.shift
79
- const = search(:tasks, task)
79
+ const = tasks.search(task)
80
80
 
81
81
  task_class = case
82
82
  when const then const.constantize
@@ -21,7 +21,7 @@ module Tap
21
21
  # # this file will be backed up and restored
22
22
  # File.open("file.txt", "w") {|f| f << "original content"}
23
23
  #
24
- # t = FileTask.new do |task|
24
+ # t = FileTask.intern do |task|
25
25
  # task.mkdir("some/dir") # marked for rollback
26
26
  # task.prepare("file.txt", "path/to/file.txt") # marked for rollback
27
27
  #
@@ -66,7 +66,7 @@ module Tap
66
66
  # error, defaults to the class rollback_on_error
67
67
  config :rollback_on_error, true, &c.switch # rollback changes on error
68
68
 
69
- def initialize(config={}, name=nil, app=App.instance, &task_block)
69
+ def initialize(config={}, name=nil, app=App.instance)
70
70
  super
71
71
 
72
72
  @backed_up_files = {}
@@ -60,10 +60,6 @@ module Tap
60
60
  raise NotImplementedError
61
61
  end
62
62
 
63
- def prepare(target, options={})
64
- raise NotImplementedError
65
- end
66
-
67
63
  def directories(root, targets, options={})
68
64
  directory(root)
69
65
  targets.each do |target|