gena 0.0.7 → 0.1.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.
- 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
|