gena 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/gena +9 -65
- data/lib/cli/cli.rb +138 -0
- data/lib/cli/init.rb +273 -0
- data/lib/codegen/codegen.rb +176 -0
- data/lib/config/config.rb +90 -0
- data/lib/constants.rb +7 -0
- data/lib/gena.rb +25 -6
- data/lib/plugin/plugin.rb +58 -0
- data/lib/utils/utils.rb +77 -0
- data/lib/utils/xcode_utils.rb +122 -0
- metadata +58 -15
- data/lib/base_template.rb +0 -91
- data/lib/config.rb +0 -44
- data/lib/generate_cli.rb +0 -60
- data/lib/ramba_adapter.rb +0 -102
- data/lib/string_utils.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d011b05b5a46e8082c31e35c5937526e60813077
|
4
|
+
data.tar.gz: 8faa576c158597b3a126c55c380aaf9e44e0b266
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2329244fb94233fc4a8c538401a1047470d080c86b2dda958c3f79860f79c5832026d0eb66dfa6900becb34b6bdd17cdec7f50b4dd6213607d7f7321f90ac69a
|
7
|
+
data.tar.gz: 240c13add3eb328b128c9cb5c5a2f4831379e656f3cbcc70f718e9943664c07e76944321d0dbe2018350a2ba9fcaa988c93abae8b927231bd8c0cc8d13dd1cdc
|
data/bin/gena
CHANGED
@@ -1,71 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'gena'
|
3
|
+
# require 'gena'
|
4
|
+
require_relative '../lib/gena'
|
4
5
|
|
5
|
-
|
6
|
-
raise "\nPlease install xc-resave utility first. Run: \n\nbrew install alexgarbarev/core/xc-resave\n\n"
|
7
|
-
end
|
6
|
+
Gena::Application.new.check
|
8
7
|
|
9
|
-
|
10
|
-
TEMPLATES_SYSTEM_FOLDER = File.expand_path('~/.gena/templates')
|
8
|
+
Gena::Application.start(ARGV)
|
11
9
|
|
12
|
-
# Include all template code files
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
require file
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
cli = GenerateCli.new
|
24
|
-
options = cli.parse_arguments
|
25
|
-
|
26
|
-
def cleanup
|
27
|
-
ramba_adapter = RambaAdapter.new(nil, nil)
|
28
|
-
ramba_adapter.delete_default_template
|
29
|
-
ramba_adapter.delete_rambafile
|
30
|
-
end
|
31
|
-
|
32
|
-
if options[:cleanup]
|
33
|
-
cleanup
|
34
|
-
exit
|
35
|
-
end
|
36
|
-
|
37
|
-
at_exit do
|
38
|
-
puts 'Cleaning up..'
|
39
|
-
cleanup
|
40
|
-
end
|
41
|
-
|
42
|
-
config = Generate::Config.new
|
43
|
-
config.load_plist_config
|
44
|
-
|
45
|
-
if options[:fetch]
|
46
|
-
FileUtils.rm_rf File.expand_path(TEMPLATES_SYSTEM_FOLDER)
|
47
|
-
FileUtils.mkdir_p File.expand_path(TEMPLATES_SYSTEM_FOLDER)
|
48
|
-
command = "git clone --depth 1 #{config.config['templates_url']} #{TEMPLATES_SYSTEM_FOLDER}"
|
49
|
-
exec command
|
50
|
-
end
|
51
|
-
|
52
|
-
template = Generate::BaseTemplate.new_from_options(options, config)
|
53
|
-
|
54
|
-
unless template.class.generamba?
|
55
|
-
template.run
|
56
|
-
exit
|
57
|
-
end
|
58
|
-
|
59
|
-
ramba_adapter = RambaAdapter.new(template, config)
|
60
|
-
ramba_adapter.create_rambafile
|
61
|
-
ramba_adapter.regenerate_default_template
|
62
|
-
|
63
|
-
cli_command = ramba_adapter.generamba_gen_command(options)
|
64
|
-
cli_command << " && #{__FILE__} --cleanup"
|
65
|
-
cli_command << " && xc-resave #{config.xcode_project_path}"
|
66
|
-
|
67
|
-
if options[:verbose]
|
68
|
-
puts "#{cli_command}"
|
69
|
-
end
|
70
|
-
|
71
|
-
exec "#{cli_command}"
|
11
|
+
if system "which xc-resave >> /dev/null"
|
12
|
+
# exec "xc-resave #{$config.xcode_project_path}"
|
13
|
+
else
|
14
|
+
puts "\nWarning: xc-resave utility not installed. Run: \n\nbrew install alexgarbarev/core/xc-resave\n\n"
|
15
|
+
end
|
data/lib/cli/cli.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Gena
|
4
|
+
|
5
|
+
class Application < Thor
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# class_for_command - hash to store custom classes (actually Plugin subclasses) for each
|
10
|
+
# command registered with gena
|
11
|
+
def class_for_command
|
12
|
+
@class_for_command ||= Hash.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def class_for_command=(commands)
|
16
|
+
@class_for_command = commands
|
17
|
+
end
|
18
|
+
|
19
|
+
def plugin_classes
|
20
|
+
class_for_command.values.uniq
|
21
|
+
end
|
22
|
+
|
23
|
+
# Override help to forward
|
24
|
+
|
25
|
+
def help(shell, subcommand = false)
|
26
|
+
|
27
|
+
#List plugin commands separately from Gena general commands
|
28
|
+
plugins = []
|
29
|
+
class_for_command.each do |command, klass|
|
30
|
+
plugins += klass.printable_commands(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
plugins.uniq!
|
34
|
+
|
35
|
+
list = printable_commands(true, subcommand)
|
36
|
+
Thor::Util.thor_classes_in(self).each do |klass|
|
37
|
+
list += klass.printable_commands(false)
|
38
|
+
end
|
39
|
+
|
40
|
+
list -= plugins
|
41
|
+
|
42
|
+
# Remove this line to disable alphabetical sorting
|
43
|
+
# list.sort! { |a, b| a[0] <=> b[0] }
|
44
|
+
|
45
|
+
# Add this line to remove the help-command itself from the output
|
46
|
+
# list.reject! {|l| l[0].split[1] == 'help'}
|
47
|
+
|
48
|
+
if defined?(@package_name) && @package_name
|
49
|
+
shell.say "#{@package_name} commands:"
|
50
|
+
else
|
51
|
+
shell.say "General commands:"
|
52
|
+
end
|
53
|
+
|
54
|
+
shell.print_table(list, :indent => 2, :truncate => true)
|
55
|
+
shell.say
|
56
|
+
class_options_help(shell)
|
57
|
+
|
58
|
+
shell.say "Plugins:"
|
59
|
+
shell.print_table(plugins, :indent => 2, :truncate => true)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Override start to do custom dispatch (looking for plugin for unknown command)
|
64
|
+
|
65
|
+
def start(given_args = ARGV, config = {})
|
66
|
+
|
67
|
+
config[:shell] ||= Thor::Base.shell.new
|
68
|
+
|
69
|
+
command_name = normalize_command_name(retrieve_command_name(given_args.dup))
|
70
|
+
clazz = command_name ? class_for_command[command_name] : nil
|
71
|
+
|
72
|
+
if command_name && clazz
|
73
|
+
clazz.dispatch(nil, given_args.dup, nil, config)
|
74
|
+
else
|
75
|
+
dispatch(nil, given_args.dup, nil, config)
|
76
|
+
end
|
77
|
+
|
78
|
+
finish
|
79
|
+
|
80
|
+
rescue Thor::Error => e
|
81
|
+
config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
|
82
|
+
exit(1) if exit_on_failure?
|
83
|
+
rescue Errno::EPIPE
|
84
|
+
# This happens if a thor command is piped to something like `head`,
|
85
|
+
# which closes the pipe when it's done reading. This will also
|
86
|
+
# mean that if the pipe is closed, further unnecessary
|
87
|
+
# computation will not occur.
|
88
|
+
exit(0)
|
89
|
+
end
|
90
|
+
|
91
|
+
def finish
|
92
|
+
XcodeUtils.shared.save_project
|
93
|
+
Application.new.check_gena_version
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
no_tasks do
|
100
|
+
|
101
|
+
|
102
|
+
def check_gena_version
|
103
|
+
# Read cache
|
104
|
+
say "Checking for update.." if $verbose
|
105
|
+
|
106
|
+
version_path = File.expand_path "#{GENA_HOME}/version.plist"
|
107
|
+
plist = File.exists?(version_path) ? Plist::parse_xml(version_path) : Hash.new
|
108
|
+
|
109
|
+
data = nil
|
110
|
+
|
111
|
+
if !plist['timestamp'] || (DateTime.now.to_time.to_i - plist['timestamp'].to_i) > GENA_UPDATE_CHECK_INTERVAL
|
112
|
+
last_release_text = `curl https://api.github.com/repos/alexgarbarev/gena/releases/latest -s`
|
113
|
+
data = JSON.parse(last_release_text)
|
114
|
+
|
115
|
+
plist['data'] = data
|
116
|
+
plist['timestamp'] = DateTime.now.to_time.to_i
|
117
|
+
File.open(version_path, 'w') { |f| f.write plist.to_plist }
|
118
|
+
else
|
119
|
+
data = plist['data']
|
120
|
+
end
|
121
|
+
|
122
|
+
tag_name = data['tag_name']
|
123
|
+
|
124
|
+
if tag_name > VERSION
|
125
|
+
say "New update v#{tag_name} is available for gena.\nSee release notes: #{data['url']}", Color::YELLOW
|
126
|
+
say "Please update by:\n#{set_color('gem install gena', Color::GREEN)}", Color::YELLOW
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
|
data/lib/cli/init.rb
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
module Gena
|
2
|
+
|
3
|
+
class Application < Thor
|
4
|
+
|
5
|
+
desc 'init', 'Initialize gena.plist with default parameters'
|
6
|
+
|
7
|
+
def init
|
8
|
+
|
9
|
+
xcode_project_name = `find . -name *.xcodeproj`
|
10
|
+
xcode_project_name.strip!
|
11
|
+
|
12
|
+
xcode_project_name = ask_with_default("Enter path for #{set_color('project', Color::YELLOW)} or ENTER to continue (#{xcode_project_name}):", xcode_project_name)
|
13
|
+
|
14
|
+
xcode_project = Xcodeproj::Project.open(xcode_project_name)
|
15
|
+
|
16
|
+
|
17
|
+
main_target = nil
|
18
|
+
test_target = nil
|
19
|
+
xcode_project.native_targets.each do |target|
|
20
|
+
if target.product_type == 'com.apple.product-type.application'
|
21
|
+
main_target = target
|
22
|
+
elsif target.product_type == 'com.apple.product-type.bundle.unit-test'
|
23
|
+
test_target = target
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
sources_path = common_path_in_target(main_target, 'main.m')
|
28
|
+
tests_path = common_path_in_target(test_target, "#{sources_path}/")
|
29
|
+
|
30
|
+
sources_path = relative_to_current_dir(sources_path)
|
31
|
+
tests_path = relative_to_current_dir(tests_path)
|
32
|
+
|
33
|
+
hash = Hash.new
|
34
|
+
hash[:plugins_url] = [
|
35
|
+
'https://github.com/alexgarbarev/gena-plugins.git'
|
36
|
+
]
|
37
|
+
|
38
|
+
default_build_configuration = main_target.build_configuration_list.default_configuration_name || 'Debug'
|
39
|
+
info_plist_value = main_target.build_configuration_list.get_setting('INFOPLIST_FILE')[default_build_configuration]
|
40
|
+
if info_plist_value['$(SRCROOT)/']
|
41
|
+
info_plist_value['$(SRCROOT)/'] = ''
|
42
|
+
end
|
43
|
+
|
44
|
+
hash['company'] = xcode_project.root_object.attributes['ORGANIZATIONNAME'].to_s
|
45
|
+
hash['prefix'] = xcode_project.root_object.attributes['CLASSPREFIX'].to_s
|
46
|
+
hash['project_name'] = xcode_project.root_object.name
|
47
|
+
hash['project_target'] = main_target.name
|
48
|
+
hash['test_target'] = test_target.name
|
49
|
+
hash['info_plist'] = info_plist_value
|
50
|
+
hash['sources_dir'] = ask_with_default("Enter path for #{set_color('sources', Color::YELLOW)} or ENTER to continue (#{sources_path}):", sources_path)
|
51
|
+
hash['tests_dir'] = ask_with_default("Enter path for #{set_color('tests', Color::YELLOW)} or ENTER to continue (#{tests_path}):", tests_path)
|
52
|
+
|
53
|
+
say '===============================================================', Color::YELLOW
|
54
|
+
print_table(hash)
|
55
|
+
say '===============================================================', Color::YELLOW
|
56
|
+
|
57
|
+
File.open('gena.plist', 'w') { |f| f.write hash.to_plist }
|
58
|
+
|
59
|
+
|
60
|
+
say "'gena.plist' created..", Color::GREEN
|
61
|
+
end
|
62
|
+
|
63
|
+
no_tasks do
|
64
|
+
|
65
|
+
@downloaded_urls = Hash.new
|
66
|
+
|
67
|
+
|
68
|
+
def check
|
69
|
+
|
70
|
+
$verbose = (ARGV.include? '-v')
|
71
|
+
if $verbose
|
72
|
+
ARGV.reject! { |n| n == '-v' || n == '--verbose' }
|
73
|
+
end
|
74
|
+
|
75
|
+
unless Config.exists?
|
76
|
+
if ARGV == ['init']
|
77
|
+
init
|
78
|
+
ARGV.replace([])
|
79
|
+
else
|
80
|
+
if yes? "'gena.plist' is not exists. Do you want to create new one? (Y/n)", Color::YELLOW
|
81
|
+
init
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
$config = Gena::Config.new
|
87
|
+
$config.load_plist_config
|
88
|
+
|
89
|
+
unless $config.data
|
90
|
+
say '\'gena.plist\' is corrupted! Try recreating', Color::RED
|
91
|
+
abort
|
92
|
+
end
|
93
|
+
|
94
|
+
if !$config.data['plugins_url'] || $config.data['plugins_url'].count == 0
|
95
|
+
say "'plugins_url' key is missing inside 'gena.plist'", Color::RED
|
96
|
+
abort
|
97
|
+
end
|
98
|
+
download_plugins
|
99
|
+
load_plugins
|
100
|
+
save_plugin_configs
|
101
|
+
end
|
102
|
+
|
103
|
+
def download_plugins
|
104
|
+
load_downloaded_urls
|
105
|
+
$config.data['plugins_url'].each do |plugin_url|
|
106
|
+
if remote_url? plugin_url
|
107
|
+
is_old = old_url?(plugin_url)
|
108
|
+
if !downloaded_url?(plugin_url) || is_old
|
109
|
+
message = is_old ? 'not up to date' : 'not downloaded yet'
|
110
|
+
say "Plugin at '#{plugin_url}' #{message}", Color::YELLOW
|
111
|
+
download_plugin_at plugin_url
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
save_downloaded_urls
|
116
|
+
end
|
117
|
+
|
118
|
+
def remote_url?(url)
|
119
|
+
url =~ /(.+@)*([\w\d\.]+):(.*)/
|
120
|
+
end
|
121
|
+
|
122
|
+
def downloaded_url?(url)
|
123
|
+
File.exists? File.expand_path(download_path_for(url))
|
124
|
+
end
|
125
|
+
|
126
|
+
def old_url?(url)
|
127
|
+
entity = @downloaded_urls[key_for_url(url)]
|
128
|
+
return true unless entity
|
129
|
+
elapsed_seconds = DateTime.now.to_time.to_i - entity['timestamp'].to_i
|
130
|
+
if elapsed_seconds > GENA_UPDATE_CHECK_INTERVAL
|
131
|
+
current_hash = `git ls-remote #{url} refs/heads/master | cut -f 1`.strip
|
132
|
+
entity['timestamp'] = DateTime.now.to_time.to_i
|
133
|
+
return current_hash != entity['hash']
|
134
|
+
end
|
135
|
+
false
|
136
|
+
end
|
137
|
+
|
138
|
+
def load_downloaded_urls
|
139
|
+
plist_path = File.expand_path "#{GENA_HOME}/plugins.plist"
|
140
|
+
if File.exists? plist_path
|
141
|
+
@downloaded_urls = Plist::parse_xml(plist_path)
|
142
|
+
else
|
143
|
+
@downloaded_urls = Hash.new
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def save_downloaded_urls
|
148
|
+
File.open(File.expand_path("#{GENA_HOME}/plugins.plist"), 'w') { |f| f.write @downloaded_urls.to_plist }
|
149
|
+
end
|
150
|
+
|
151
|
+
def key_for_url(url)
|
152
|
+
Digest::MD5.hexdigest url
|
153
|
+
end
|
154
|
+
|
155
|
+
def download_path_for(url)
|
156
|
+
hash = Digest::MD5.hexdigest url
|
157
|
+
File.expand_path "#{GENA_HOME}/plugins/#{hash}"
|
158
|
+
end
|
159
|
+
|
160
|
+
def download_plugin_at(url)
|
161
|
+
say "Downloading plugin from '#{url}'..", Color::GREEN, ' '
|
162
|
+
output_path = File.expand_path(download_path_for(url))
|
163
|
+
FileUtils.rmtree output_path
|
164
|
+
FileUtils.mkdir_p output_path
|
165
|
+
result = gena_system "git clone --depth 1 #{url} #{output_path}"
|
166
|
+
if result
|
167
|
+
say 'success!', Color::GREEN
|
168
|
+
@downloaded_urls[key_for_url(url)] = {
|
169
|
+
'hash' => `git ls-remote #{url} refs/heads/master | cut -f 1`.strip,
|
170
|
+
'timestamp' => DateTime.now.to_time.to_i
|
171
|
+
}
|
172
|
+
|
173
|
+
else
|
174
|
+
say 'Failed! Run with \'-v\' to debug', Color::RED
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def load_plugins
|
179
|
+
registered = []
|
180
|
+
$config.data['plugins_url'].each do |plugin_url|
|
181
|
+
path = remote_url?(plugin_url) ? download_path_for(plugin_url) : plugin_url
|
182
|
+
Dir["#{File.expand_path(path)}/**/*.rb"].each do |file|
|
183
|
+
template_name = file.split(File::SEPARATOR)[-2]
|
184
|
+
unless registered.include? template_name
|
185
|
+
registered << template_name
|
186
|
+
say "Loading '#{file}'..", Color::YELLOW if $verbose
|
187
|
+
require file
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
Gena::Plugin.descendants.each do |clazz|
|
192
|
+
clazz.setup_thor_commands
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def save_plugin_configs
|
197
|
+
|
198
|
+
data = $config.data[GENA_PLUGINS_CONFIG_KEY] || Hash.new
|
199
|
+
|
200
|
+
Application.plugin_classes.each do |klass|
|
201
|
+
|
202
|
+
defaults = klass.plugin_config_defaults
|
203
|
+
|
204
|
+
if defaults.count > 0
|
205
|
+
plugin_config_name = klass.plugin_config_name
|
206
|
+
|
207
|
+
if !data[plugin_config_name] || data[plugin_config_name].count == 0
|
208
|
+
say "Writing config defaults for plugin '#{plugin_config_name}'..", Color::GREEN
|
209
|
+
data[plugin_config_name] = defaults
|
210
|
+
elsif !data[plugin_config_name].keys.to_set.eql? defaults.keys.to_set
|
211
|
+
missing_keys = defaults.keys - data[plugin_config_name].keys
|
212
|
+
say "Adding missing config keys #{missing_keys} for plugin '#{plugin_config_name}.'", Color::GREEN
|
213
|
+
missing_keys.each { |key| data[plugin_config_name][key] = defaults[key] }
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
$config.data[GENA_PLUGINS_CONFIG_KEY] = data
|
221
|
+
$config.save!
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def ask_with_default(message, default)
|
228
|
+
value = ask(message)
|
229
|
+
if value.empty?
|
230
|
+
value = default
|
231
|
+
end
|
232
|
+
value
|
233
|
+
end
|
234
|
+
|
235
|
+
def relative_to_current_dir(path)
|
236
|
+
|
237
|
+
if path.empty? || !path["#{Dir.pwd}/"]
|
238
|
+
path
|
239
|
+
else
|
240
|
+
result = path.dup
|
241
|
+
result["#{Dir.pwd}/"] = ''
|
242
|
+
result
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def common_path_in_target(target, except_match)
|
247
|
+
common = ''
|
248
|
+
target.source_build_phase.files.each do |file|
|
249
|
+
unless file.file_ref.real_path.to_s[except_match]
|
250
|
+
path_components = file.file_ref.real_path.to_s #.split('/')
|
251
|
+
if common.empty?
|
252
|
+
common = path_components
|
253
|
+
else
|
254
|
+
common = common.path_intersection path_components
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
if File.file? common
|
260
|
+
common = common.delete_last_path_component
|
261
|
+
end
|
262
|
+
if common[-1] == '/'
|
263
|
+
common = common[0..-2]
|
264
|
+
end
|
265
|
+
common
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Gena
|
4
|
+
|
5
|
+
module Filetype
|
6
|
+
class Context
|
7
|
+
attr_accessor :target_key, :base_dir_key, :is_resource
|
8
|
+
|
9
|
+
def initialize(target, base_dir, is_resource)
|
10
|
+
@target_key = target
|
11
|
+
@base_dir_key = base_dir
|
12
|
+
@is_resource = is_resource
|
13
|
+
end
|
14
|
+
end
|
15
|
+
SOURCE = Context.new('project_target', 'sources_dir', false)
|
16
|
+
RESOURCE = Context.new('project_target', 'sources_dir', true)
|
17
|
+
TEST_SOURCE = Context.new('test_target', 'tests_dir', false)
|
18
|
+
TEST_RESOURCE = Context.new('test_target', 'tests_dir', true)
|
19
|
+
end
|
20
|
+
|
21
|
+
class Codegen < Thor
|
22
|
+
|
23
|
+
no_tasks do
|
24
|
+
|
25
|
+
|
26
|
+
def initialize(output_path, template_params)
|
27
|
+
|
28
|
+
@output_path = output_path
|
29
|
+
@template_params = template_params
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def add_file(template_name, file_name, type, params = nil)
|
35
|
+
|
36
|
+
# Getting path for template
|
37
|
+
plugin_dir = File.dirname(caller.first.scan(/.*rb/).first)
|
38
|
+
template_path = absolute_path_for_template(template_name, plugin_dir)
|
39
|
+
|
40
|
+
# Output path
|
41
|
+
output_path = absolute_path_for_output(file_name, type)
|
42
|
+
|
43
|
+
# Params
|
44
|
+
template_params = @template_params.merge($config.data_without_plugins)
|
45
|
+
template_params = params.merge(template_params) if params
|
46
|
+
|
47
|
+
render_template_to_file(template_path, output_path, template_params)
|
48
|
+
|
49
|
+
add_file_to_project(output_path, type)
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_template(template_name, params)
|
54
|
+
|
55
|
+
plugin_dir = File.dirname(caller.first.scan(/.*rb/).first)
|
56
|
+
template_path = absolute_path_for_template(template_name, plugin_dir)
|
57
|
+
|
58
|
+
render_template_from_path(template_path, params)
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def render_template_to_file(template_name, output_path, params)
|
63
|
+
|
64
|
+
plugin_dir = File.dirname(caller.first.scan(/.*rb/).first)
|
65
|
+
template_path = absolute_path_for_template(template_name, plugin_dir)
|
66
|
+
|
67
|
+
render_template_from_path_to_file(template_path, output_path, params)
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_file_to_project(output_path, type)
|
71
|
+
|
72
|
+
target_name = $config.data[type.target_key]
|
73
|
+
|
74
|
+
target = XcodeUtils.shared.obtain_target(target_name)
|
75
|
+
|
76
|
+
dirname = File.dirname(output_path)
|
77
|
+
|
78
|
+
group = XcodeUtils.shared.make_group(dirname, dirname)
|
79
|
+
|
80
|
+
XcodeUtils.shared.add_file(target, group, output_path, type.is_resource)
|
81
|
+
end
|
82
|
+
|
83
|
+
def remove_from_project(path)
|
84
|
+
|
85
|
+
XcodeUtils.shared.delete_path(path)
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
|
92
|
+
def render_template_from_path(template_path, params)
|
93
|
+
|
94
|
+
if $config.header_dir.empty?
|
95
|
+
say "No 'header' field inside 'gena.plist'. You can specify path to header's liquid template there. Using default header", Color::YELLOW if $verbose
|
96
|
+
Liquid::Template.file_system = GenaStaticHeader.new
|
97
|
+
else
|
98
|
+
Liquid::Template.file_system = Liquid::LocalFileSystem.new($config.header_dir, '%s.liquid')
|
99
|
+
end
|
100
|
+
|
101
|
+
file_source = IO.read(template_path)
|
102
|
+
template = Liquid::Template.parse(file_source)
|
103
|
+
|
104
|
+
template.render(params)
|
105
|
+
end
|
106
|
+
|
107
|
+
def render_template_from_path_to_file(template_path, output_path, params)
|
108
|
+
|
109
|
+
content = render_template(template_path, params)
|
110
|
+
|
111
|
+
FileUtils.mkpath(File.dirname(output_path))
|
112
|
+
|
113
|
+
say "Writing to file: #{output_path}", Color::GREEN
|
114
|
+
File.open(output_path, 'w+') do |f|
|
115
|
+
f.write(content)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def absolute_path_for_output(file_name, type)
|
120
|
+
# Output path
|
121
|
+
base_dir = $config.expand_to_project($config.data[type.base_dir_key])
|
122
|
+
|
123
|
+
if @output_path[0] == '/'
|
124
|
+
puts 'Output path is absolute' if $verbose
|
125
|
+
output_path = File.join(@output_path, file_name)
|
126
|
+
else
|
127
|
+
puts 'Output path is relative' if $verbose
|
128
|
+
output_path = File.join(base_dir, @output_path, file_name)
|
129
|
+
end
|
130
|
+
output_path
|
131
|
+
end
|
132
|
+
|
133
|
+
def absolute_path_for_template(template_path, plugin_dir)
|
134
|
+
result = ''
|
135
|
+
|
136
|
+
expanded = File.expand_path(template_path)
|
137
|
+
if File.exists? expanded
|
138
|
+
result = expanded
|
139
|
+
else
|
140
|
+
joined = File.join(plugin_dir, template_path)
|
141
|
+
if File.exists? joined
|
142
|
+
result = joined
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
if !result.empty?
|
147
|
+
say "Found template at path '#{result}'", Color::YELLOW if $verbose
|
148
|
+
else
|
149
|
+
say "Can't find path for template '#{template_path}'", Color::RED
|
150
|
+
abort
|
151
|
+
end
|
152
|
+
result
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
class GenaStaticHeader < Liquid::BlankFileSystem
|
160
|
+
|
161
|
+
def read_template_file(name)
|
162
|
+
|
163
|
+
if name == 'header'
|
164
|
+
'////////////////////////////////////////////////////////////////////////////////
|
165
|
+
//
|
166
|
+
// Generated by Gena.
|
167
|
+
//
|
168
|
+
////////////////////////////////////////////////////////////////////////////////'
|
169
|
+
else
|
170
|
+
''
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|