tap-gen 0.3.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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