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.
- data/History +4 -0
- data/MIT-LICENSE +1 -1
- data/README +1 -4
- data/lib/tap/generator/base.rb +99 -33
- data/lib/tap/generator/destroy.rb +20 -4
- data/lib/tap/generator/generate.rb +20 -4
- data/lib/tap/generator/generators/config.rb +5 -17
- data/lib/tap/generator/generators/env.rb +106 -0
- data/lib/tap/generator/generators/resource.rb +3 -3
- data/lib/tap/generator/generators/root.rb +25 -38
- data/lib/tap/generator/generators/tap.rb +49 -0
- data/lib/tap/generator/helpers.rb +49 -0
- data/lib/tap/generator/preview.rb +1 -1
- data/lib/tap/generator/version.rb +1 -1
- data/tap-gen.gemspec +67 -0
- data/templates/tap/generator/generators/generator/resource.erb +6 -3
- data/templates/tap/generator/generators/generator/test.erb +3 -3
- data/templates/tap/generator/generators/middleware/test.erb +2 -2
- data/templates/tap/generator/generators/root/README +1 -1
- data/templates/tap/generator/generators/root/gemspec +11 -11
- data/templates/tap/generator/generators/root/tap.yml +0 -0
- data/templates/tap/generator/generators/root/{Rakefile → tapfile} +28 -36
- data/templates/tap/generator/generators/root/test/{tap_test_helper.rb → test_helper.rb} +0 -0
- data/templates/tap/generator/generators/tap/profile.erb +9 -0
- data/templates/tap/generator/generators/tap/tap.erb +3 -0
- data/templates/tap/generator/generators/task/resource.erb +0 -1
- data/templates/tap/generator/generators/task/test.erb +2 -2
- metadata +43 -16
- data/cmd/destroy.rb +0 -27
- data/cmd/generate.rb +0 -27
- data/lib/tap/generator/generators/command.rb +0 -21
- data/templates/tap/generator/generators/command/command.erb +0 -30
- data/templates/tap/generator/generators/root/Rapfile +0 -11
data/History
CHANGED
data/MIT-LICENSE
CHANGED
@@ -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
|
23
|
+
% tap goodnight moon
|
27
24
|
|
28
25
|
Get some help:
|
29
26
|
|
data/lib/tap/generator/base.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
#
|
211
|
+
# template_root. Options are passed onto file.
|
167
212
|
def template(target, source, attributes={}, options={})
|
168
|
-
|
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
|
179
|
-
# a target path of the source relative to
|
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
|
-
|
229
|
+
template_root.glob('**/*').sort.each do |source|
|
185
230
|
next unless File.file?(source)
|
186
231
|
|
187
|
-
target =
|
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
|
253
|
+
# Logs the action with the relative filepath from destination_root to path.
|
209
254
|
def log_relative(action, path)
|
210
|
-
relative_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
|
-
#
|
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 =
|
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
|
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 =
|
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
|
-
#
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
91
|
-
config_name ||=
|
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
|
-
|
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
|
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
|