tap-gen 0.3.1 → 0.7.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.
Files changed (33) hide show
  1. data/History +4 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README +1 -4
  4. data/lib/tap/generator/base.rb +99 -33
  5. data/lib/tap/generator/destroy.rb +20 -4
  6. data/lib/tap/generator/generate.rb +20 -4
  7. data/lib/tap/generator/generators/config.rb +5 -17
  8. data/lib/tap/generator/generators/env.rb +106 -0
  9. data/lib/tap/generator/generators/resource.rb +3 -3
  10. data/lib/tap/generator/generators/root.rb +25 -38
  11. data/lib/tap/generator/generators/tap.rb +49 -0
  12. data/lib/tap/generator/helpers.rb +49 -0
  13. data/lib/tap/generator/preview.rb +1 -1
  14. data/lib/tap/generator/version.rb +1 -1
  15. data/tap-gen.gemspec +67 -0
  16. data/templates/tap/generator/generators/generator/resource.erb +6 -3
  17. data/templates/tap/generator/generators/generator/test.erb +3 -3
  18. data/templates/tap/generator/generators/middleware/test.erb +2 -2
  19. data/templates/tap/generator/generators/root/README +1 -1
  20. data/templates/tap/generator/generators/root/gemspec +11 -11
  21. data/templates/tap/generator/generators/root/tap.yml +0 -0
  22. data/templates/tap/generator/generators/root/{Rakefile → tapfile} +28 -36
  23. data/templates/tap/generator/generators/root/test/{tap_test_helper.rb → test_helper.rb} +0 -0
  24. data/templates/tap/generator/generators/tap/profile.erb +9 -0
  25. data/templates/tap/generator/generators/tap/tap.erb +3 -0
  26. data/templates/tap/generator/generators/task/resource.erb +0 -1
  27. data/templates/tap/generator/generators/task/test.erb +2 -2
  28. metadata +43 -16
  29. data/cmd/destroy.rb +0 -27
  30. data/cmd/generate.rb +0 -27
  31. data/lib/tap/generator/generators/command.rb +0 -21
  32. data/templates/tap/generator/generators/command/command.erb +0 -30
  33. data/templates/tap/generator/generators/root/Rapfile +0 -11
data/History CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.7.0 / 2010-05-02
2
+
3
+ Updated to Tap-1.3.0. Reworked generate/destroy as task proxies.
4
+
1
5
  == 0.3.1 / 2009-12-09
2
6
 
3
7
  * updated Base to determine template directory from
@@ -1,6 +1,6 @@
1
1
  Copyright (c) 2009, Regents of the University of Colorado.
2
2
 
3
- Copyright (c) 2009, Simon Chiang.
3
+ Copyright (c) 2009-2010, Simon Chiang.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -8,9 +8,6 @@ Generators for Tap.
8
8
 
9
9
  Provides generators for Tap. Generators are subclasses of Task are therefore
10
10
  easy to configure, subclass, and distribute.
11
- {Tap-Generator}[http://tap.rubyforge.org/tap-gen] is a part of the
12
- {Tap-Suite}[http://tap.rubyforge.org/tap-suite]. Check out these links for
13
- documentation, development, and bug tracking.
14
11
 
15
12
  * Website[http://tap.rubyforge.org]
16
13
  * Github[http://github.com/bahuvrihi/tap/tree/master]
@@ -23,7 +20,7 @@ Get started:
23
20
  % tap generate root sample
24
21
  % cd sample
25
22
  % tap generate task goodnight
26
- % tap run -- goodnight moon
23
+ % tap goodnight moon
27
24
 
28
25
  Get some help:
29
26
 
@@ -1,8 +1,11 @@
1
- require 'tap'
1
+ require 'tap/task'
2
+ require 'tap/templater'
2
3
  require 'tap/generator/manifest'
3
4
  require 'tap/generator/arguments'
4
5
  require 'tap/generator/generate'
5
6
  require 'tap/generator/destroy'
7
+ require 'tap/generator/helpers'
8
+ require 'tap/tasks/list'
6
9
 
7
10
  module Tap
8
11
  module Generator
@@ -71,40 +74,82 @@ module Tap
71
74
  #
72
75
  # :startdoc:::+
73
76
  class Base < Tap::Task
74
- lazy_attr :manifest, 'generator'
77
+ class << self
78
+ def parse_as(mixin, argv=ARGV, app=Tap::App.current, &block)
79
+ if argv.empty?
80
+ raise "no generator specified"
81
+ end
82
+
83
+ if argv[0] == '--help'
84
+ desc = mixin.desc
85
+ lines = ["#{mixin}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"]
86
+ lines << '-' * 80
87
+ lines.concat desc.wrap(77, 2, nil).collect {|line| " #{line}"}
88
+ lines << '-' * 80
89
+ lines << "usage: tap #{mixin.to_s.underscore} generator *args"
90
+ lines << ''
91
+ lines.concat Tasks::List.new(:types => ['generator']).manifest
92
+ raise lines.join("\n")
93
+ end
94
+
95
+ argv = argv.dup
96
+ generator = argv.shift
97
+ argv.unshift mixin
98
+ app.env.constant(generator, 'generator').parse(argv, app, &block)
99
+ end
100
+
101
+ def build(spec={}, app=Tap::App.current)
102
+ obj = new(spec['config'] || {}, app)
103
+
104
+ if mixin = spec['mixin']
105
+ obj.extend app.env.constant(mixin)
106
+ end
107
+
108
+ obj
109
+ end
110
+
111
+ def convert_to_spec(parser, args)
112
+ {
113
+ 'config' => parser.nested_config,
114
+ 'mixin' => args.shift
115
+ }
116
+ end
117
+ end
118
+
119
+ extend Helpers
120
+
121
+ lazy_attr :desc, 'generator'
75
122
  lazy_attr :args, :manifest
76
123
  lazy_register :manifest, Arguments
77
124
 
78
- config :destination_root, Dir.pwd, # The destination root directory
125
+ config_attr :destination_root, nil, # The destination root directory
79
126
  :long => :destination,
80
- :short => :d
127
+ :short => :d do |root|
128
+ root ||= default_destination_root
129
+ @destination_root = root.kind_of?(Root) ? root : Root.new(root)
130
+ end
131
+
132
+ config_attr :template_root, nil, # The template root directory
133
+ :long => :template,
134
+ :short => :t do |root|
135
+ root ||= default_template_root
136
+ @template_root = root.kind_of?(Root) ? root : Root.new(root)
137
+ end
138
+
81
139
  config :pretend, false, &c.flag # Run but rollback any changes.
82
140
  config :force, false, &c.flag # Overwrite files that already exist.
83
141
  config :skip, false, &c.flag # Skip files that already exist.
84
142
 
85
- signal :set # Set this generator to generate or destroy
86
-
87
- # The generator-specific templates directory. By default:
88
- # 'templates/path/to/name' for 'lib/path/to/name.rb'
89
- attr_accessor :template_dir
90
-
91
143
  # The IO used to pull prompt inputs (default: $stdin)
92
144
  attr_accessor :prompt_in
93
145
 
94
146
  # The IO used to prompt users for input (default: $stdout)
95
147
  attr_accessor :prompt_out
96
148
 
97
- def initialize(config={}, app=Tap::App.instance)
149
+ def initialize(config={}, app=Tap::App.current)
98
150
  super
99
151
  @prompt_in = $stdin
100
152
  @prompt_out = $stdout
101
- @template_dir = app.env.path(:templates, self.class.to_s.underscore) {|dir| File.directory?(dir) } || File.expand_path("templates/#{self.class.to_s.underscore}")
102
- end
103
-
104
- def set(mod)
105
- mod = app.env[mod] unless mod.class == Module
106
- extend(mod)
107
- self
108
153
  end
109
154
 
110
155
  # Builds the manifest, then executes the actions of the manifest.
@@ -116,7 +161,7 @@ module Tap
116
161
 
117
162
  iterate(actions) do |action, args, block|
118
163
  send(action, *args, &block)
119
- end
164
+ end.compact
120
165
  end
121
166
 
122
167
  # Overridden in subclasses to add actions to the input Manifest.
@@ -134,7 +179,7 @@ module Tap
134
179
 
135
180
  # Constructs a path relative to destination_root.
136
181
  def path(*paths)
137
- File.expand_path(File.join(*paths), destination_root)
182
+ destination_root.path(*paths)
138
183
  end
139
184
 
140
185
  # Peforms a directory action (ex generate or destroy). Must be
@@ -163,28 +208,28 @@ module Tap
163
208
 
164
209
  # Makes (or destroys) the target by templating the source using
165
210
  # the specified attributes. Source is expanded relative to
166
- # template_dir. Options are passed onto file.
211
+ # template_root. Options are passed onto file.
167
212
  def template(target, source, attributes={}, options={})
168
- raise "no template dir is set" unless template_dir
169
-
170
- template_path = File.expand_path(source, template_dir)
213
+ template_path = template_root.path(source)
171
214
  templater = Templater.new(File.read(template_path), attributes)
172
215
 
216
+ (options[:helpers] || self.class.helpers).each do |helper|
217
+ templater.extend(helper)
218
+ end
219
+
173
220
  file(target, options) do |file|
174
221
  file << templater.build(nil, template_path)
175
222
  end
176
223
  end
177
224
 
178
- # Yields each source file under template_dir to the block, with
179
- # a target path of the source relative to template_dir.
225
+ # Yields each source file under template_root to the block, with
226
+ # a target path of the source relative to template_root.
180
227
  def template_files
181
- raise "no template dir is set" unless template_dir
182
-
183
228
  targets = []
184
- Dir.glob(template_dir + "/**/*").sort.each do |source|
229
+ template_root.glob('**/*').sort.each do |source|
185
230
  next unless File.file?(source)
186
231
 
187
- target = Tap::Root::Utils.relative_path(template_dir, source)
232
+ target = template_root.relative_path(source)
188
233
  yield(source, target)
189
234
  targets << target
190
235
  end
@@ -205,10 +250,31 @@ module Tap
205
250
  raise NotImplementedError
206
251
  end
207
252
 
208
- # Logs the action with the relative filepath from Dir.pwd to path.
253
+ # Logs the action with the relative filepath from destination_root to path.
209
254
  def log_relative(action, path)
210
- relative_path = Tap::Root::Utils.relative_path(Dir.pwd, path)
211
- log(action, relative_path || path)
255
+ relative_path = destination_root.relative_path(path)
256
+ app.log(action, relative_path || path)
257
+ end
258
+
259
+ protected
260
+
261
+ def default_destination_root
262
+ Root.new
263
+ end
264
+
265
+ def default_template_root
266
+ class_path = self.class.to_s.underscore
267
+
268
+ template_dir = nil
269
+ app.env.path(:templates).each do |dir|
270
+ path = File.join(dir, class_path)
271
+ if File.directory?(path)
272
+ template_dir = path
273
+ break
274
+ end
275
+ end
276
+
277
+ Root.new(template_dir || "templates/#{class_path}")
212
278
  end
213
279
  end
214
280
  end
@@ -1,8 +1,18 @@
1
+ require 'tap/generator/base'
2
+
1
3
  module Tap
2
4
  module Generator
3
5
 
4
- # :startdoc::module A mixin defining how to run manifest actions in reverse.
6
+ # ::mixin run generators in reverse
7
+ #
8
+ # A mixin defining how to run manifest actions in reverse.
5
9
  module Destroy
10
+ extend Lazydoc::Attributes
11
+ lazy_attr(:desc, 'mixin')
12
+
13
+ def self.parse(argv=ARGV, app=Tap::App.current, &block)
14
+ Base.parse_as(self, argv, app, &block)
15
+ end
6
16
 
7
17
  # Iterates over the actions in reverse, and collects the results.
8
18
  def iterate(actions)
@@ -17,14 +27,15 @@ module Tap
17
27
  #
18
28
  # No options currently affect the behavior of this method.
19
29
  def directory(target, options={})
20
- target = File.expand_path(target)
30
+ target = path(target)
21
31
 
22
32
  case
23
33
  when !File.exists?(target)
24
34
  log_relative :missing, target
25
35
  when !File.directory?(target)
26
36
  log_relative 'not a directory', target
27
- when !Root::Utils.empty?(target)
37
+ when target == Dir.pwd
38
+ when !Root.empty?(target)
28
39
  log_relative 'not empty', target
29
40
  else
30
41
  log_relative :rm, target
@@ -40,7 +51,7 @@ module Tap
40
51
  #
41
52
  # No options currently affect the behavior of this method.
42
53
  def file(target, options={})
43
- target = File.expand_path(target)
54
+ target = path(target)
44
55
 
45
56
  case
46
57
  when File.file?(target)
@@ -60,6 +71,11 @@ module Tap
60
71
  :destroy
61
72
  end
62
73
 
74
+ def to_spec
75
+ spec = super
76
+ spec['mixin'] = 'Tap::Generator::Destroy'
77
+ spec
78
+ end
63
79
  end
64
80
  end
65
81
  end
@@ -1,19 +1,29 @@
1
1
  require 'tempfile'
2
+ require 'tap/generator/base'
2
3
 
3
4
  module Tap
4
5
  module Generator
5
6
 
6
- # :startdoc::module A mixin defining how to run manifest actions.
7
+ # ::mixin run generators
8
+ #
9
+ # A mixin defining how to run manifest actions.
7
10
  module Generate
11
+ extend Lazydoc::Attributes
12
+ lazy_attr(:desc, 'mixin')
13
+
14
+ def self.parse(argv=ARGV, app=Tap::App.current, &block)
15
+ Base.parse_as(self, argv, app, &block)
16
+ end
8
17
 
9
18
  # Creates the target directory if it doesn't exist. When pretend is
10
19
  # true, creation is logged but does not actually happen.
11
20
  #
12
21
  # No options currently affect the behavior of this method.
13
22
  def directory(target, options={})
14
- target = File.expand_path(target)
23
+ target = path(target)
15
24
 
16
25
  case
26
+ when target == Dir.pwd
17
27
  when File.exists?(target)
18
28
  log_relative :exists, target
19
29
  else
@@ -37,7 +47,7 @@ module Tap
37
47
  source_file.close
38
48
 
39
49
  source = source_file.path
40
- target = File.expand_path(target)
50
+ target = path(target)
41
51
 
42
52
  copy_file = true
43
53
  msg = case
@@ -67,6 +77,12 @@ module Tap
67
77
  :generate
68
78
  end
69
79
 
80
+ def to_spec
81
+ spec = super
82
+ spec['mixin'] = 'Tap::Generator::Generate'
83
+ spec
84
+ end
85
+
70
86
  protected
71
87
 
72
88
  # Ask the user interactively whether to force collision.
@@ -77,7 +93,7 @@ module Tap
77
93
  prompt_out.print "overwrite #{target}? [Ynaiq] "
78
94
  prompt_out.flush
79
95
  case prompt_in.gets.strip
80
- when /^y(es)?$/i
96
+ when /^y(es)?$/i, ''
81
97
  true
82
98
  when /^n(o)?$/i
83
99
  false
@@ -72,36 +72,24 @@ module Tap::Generator::Generators
72
72
  config :doc, true, &c.switch # Include documentation in the config
73
73
  config :nest, false, &c.switch # Generate nested config files
74
74
  config :blanks, true, &c.switch # Allow generation of empty config files
75
- config :type, 'task' # Specify the resource type
76
-
77
- # Lookup the named resource. Lookup happens through the active Env
78
- # instance, specifically using:
79
- #
80
- # Env.instance[type][name]
81
- #
82
- # Raises an error if the name cannot be resolved to a resource.
83
- def lookup(name)
84
- env = Tap::Env.instance
85
- env[type][name] or raise "unknown #{type}: #{name}"
86
- end
87
-
75
+
88
76
  def manifest(m, name, config_name=nil)
89
77
  # setup
90
- tasc = lookup(name)
91
- config_name ||= tasc.to_s.underscore
78
+ clas = app.env.constant(name)
79
+ config_name ||= clas.to_s.underscore
92
80
  config_file = path('config', config_name)
93
81
  config_file += ".yml" if File.extname(config_file).empty?
94
82
 
95
83
  # generate the dumps
96
84
  dumps = Configurable::Utils.dump_file(
97
- tasc.configurations,
85
+ clas.configurations,
98
86
  config_file,
99
87
  nest,
100
88
  true,
101
89
  &format_block)
102
90
 
103
91
  # now put the dumps to the manifest
104
- m.directory(path('config'))
92
+ m.directory 'config'
105
93
 
106
94
  dumps.each do |path, content|
107
95
  next if content.empty? && !blanks
@@ -0,0 +1,106 @@
1
+ require 'tap/generator/base'
2
+
3
+ module Tap
4
+ module Generator
5
+ module Generators
6
+ # :startdoc::generator generate a tapenv file
7
+ class Env < Tap::Generator::Base
8
+
9
+ config :pattern, '**/*.rb', &c.string # the glob pattern under each path
10
+ config :lib, 'lib', &c.string # the lib dir
11
+ config :pathfile, 'tap.yml', &c.string # the pathfile
12
+ config :register, true, &c.switch # register resource paths
13
+ config :load_paths, true, &c.switch # set load paths
14
+ config :set, true, &c.switch # set constants
15
+ config :gems, [],
16
+ :long => :gem,
17
+ &c.list # gems to add
18
+ config :tapenv, 'tapenv', &c.string # the tapenv file name
19
+ config :use_organize, true,
20
+ :long => :organize,
21
+ &c.switch # organize results a bit
22
+
23
+ def manifest(m, *paths)
24
+ lines = []
25
+ paths.each do |path|
26
+ lines.concat Tap::Env.generate(options(path))
27
+ end
28
+
29
+ gem_options.each do |options|
30
+ lines.concat Tap::Env.generate(options)
31
+ end
32
+
33
+ lines.uniq!
34
+
35
+ if use_organize
36
+ lines = organize(lines)
37
+ end
38
+
39
+ m.file(tapenv) do |io|
40
+ lines.each {|line| io.puts line }
41
+ end
42
+ end
43
+
44
+ def options(path)
45
+ config.to_hash.merge(:dir => path)
46
+ end
47
+
48
+ def gem_options
49
+ specs = []
50
+ gems.each do |gem_name|
51
+ gem_name =~ /\A(.*?)([\s<>=~].+)?\z/
52
+ dependency = Gem::Dependency.new($1, $2)
53
+ collect_specs(dependency, specs)
54
+ end
55
+
56
+ most_recent_specs = {}
57
+ specs.sort_by do |spec|
58
+ spec.version
59
+ end.reverse_each do |spec|
60
+ most_recent_specs[spec.name] ||= spec
61
+ end
62
+
63
+ most_recent_specs.values.collect do |spec|
64
+ pathfile = File.join(spec.full_gem_path, 'tap.yml')
65
+ map = Tap::Env::Path.load(pathfile)
66
+ map.merge!('lib' => spec.require_paths)
67
+
68
+ {
69
+ :dir => spec.full_gem_path,
70
+ :lib => 'lib',
71
+ :map => map,
72
+ :set => File.exists?(pathfile)
73
+ }
74
+ end
75
+ end
76
+
77
+ def organize(lines)
78
+ sets, everything_else = lines.partition {|line| line.index('set ') == 0 }
79
+ sets.collect! {|set| set.split(' ', 4) }
80
+
81
+ cmax = sets.collect {|set| set[1].length }.max
82
+ rmax = sets.collect {|set| set[2].length }.max
83
+ format = "%s %-#{cmax}s %-#{rmax}s %s"
84
+ sets.collect! {|set| format % set }
85
+
86
+ lines = everything_else + sets
87
+ lines.sort!
88
+ lines
89
+ end
90
+
91
+ protected
92
+
93
+ def collect_specs(dependency, specs) # :nodoc:
94
+ Gem.source_index.search(dependency).each do |spec|
95
+ unless specs.include?(spec)
96
+ specs << spec
97
+ spec.runtime_dependencies.each do |dep|
98
+ collect_specs(dep, specs)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end