viperaptor 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +10 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +64 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/viperaptor +8 -0
- data/lib/viperaptor/cli/cli.rb +16 -0
- data/lib/viperaptor/cli/gen_command.rb +132 -0
- data/lib/viperaptor/cli/setup_command.rb +122 -0
- data/lib/viperaptor/cli/setup_username_command.rb +21 -0
- data/lib/viperaptor/cli/template/template_create_command.rb +40 -0
- data/lib/viperaptor/cli/template/template_group.rb +14 -0
- data/lib/viperaptor/cli/template/template_install_command.rb +21 -0
- data/lib/viperaptor/cli/template/template_list_command.rb +16 -0
- data/lib/viperaptor/cli/template/template_search_command.rb +30 -0
- data/lib/viperaptor/cli/thor_extension.rb +47 -0
- data/lib/viperaptor/cli/version_command.rb +25 -0
- data/lib/viperaptor/code_generation/Rambafile.liquid +54 -0
- data/lib/viperaptor/code_generation/code_module.rb +104 -0
- data/lib/viperaptor/code_generation/content_generator.rb +43 -0
- data/lib/viperaptor/code_generation/module_template.rb +28 -0
- data/lib/viperaptor/code_generation/rambafile_generator.rb +23 -0
- data/lib/viperaptor/configuration/user_preferences.rb +87 -0
- data/lib/viperaptor/constants/constants.rb +13 -0
- data/lib/viperaptor/constants/rambafile_constants.rb +34 -0
- data/lib/viperaptor/constants/rambaspec_constants.rb +18 -0
- data/lib/viperaptor/constants/user_preferences_constants.rb +7 -0
- data/lib/viperaptor/helpers/dependency_checker.rb +54 -0
- data/lib/viperaptor/helpers/gen_command_table_parameters_formatter.rb +33 -0
- data/lib/viperaptor/helpers/module_info_generator.rb +33 -0
- data/lib/viperaptor/helpers/module_validator.rb +85 -0
- data/lib/viperaptor/helpers/print_table.rb +17 -0
- data/lib/viperaptor/helpers/rambafile.rb +75 -0
- data/lib/viperaptor/helpers/template_helper.rb +76 -0
- data/lib/viperaptor/helpers/xcodeproj_helper.rb +256 -0
- data/lib/viperaptor/module_generator.rb +104 -0
- data/lib/viperaptor/template/creator/new_template/Code/Service/service.h.liquid +11 -0
- data/lib/viperaptor/template/creator/new_template/Code/Service/service.m.liquid +13 -0
- data/lib/viperaptor/template/creator/new_template/Tests/Service/service_tests.m.liquid +35 -0
- data/lib/viperaptor/template/creator/new_template/template.rambaspec.liquid +20 -0
- data/lib/viperaptor/template/creator/template_creator.rb +39 -0
- data/lib/viperaptor/template/helpers/catalog_downloader.rb +107 -0
- data/lib/viperaptor/template/helpers/catalog_template_list_helper.rb +55 -0
- data/lib/viperaptor/template/helpers/catalog_template_search_helper.rb +27 -0
- data/lib/viperaptor/template/helpers/catalog_terminator.rb +21 -0
- data/lib/viperaptor/template/helpers/rambaspec_validator.rb +52 -0
- data/lib/viperaptor/template/installer/abstract_installer.rb +9 -0
- data/lib/viperaptor/template/installer/catalog_installer.rb +78 -0
- data/lib/viperaptor/template/installer/local_installer.rb +32 -0
- data/lib/viperaptor/template/installer/remote_installer.rb +51 -0
- data/lib/viperaptor/template/installer/template_installer_factory.rb +22 -0
- data/lib/viperaptor/template/processor/template_declaration.rb +36 -0
- data/lib/viperaptor/template/processor/template_processor.rb +73 -0
- data/lib/viperaptor/tools/string-colorize.rb +23 -0
- data/lib/viperaptor/version.rb +5 -0
- data/lib/viperaptor.rb +16 -0
- data/viperaptor.gemspec +36 -0
- metadata +274 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require "tty-prompt"
|
2
|
+
|
3
|
+
module Viperaptor
|
4
|
+
|
5
|
+
# Provides methods for validating Rambafile contents
|
6
|
+
class RambafileValidator
|
7
|
+
# Method validates Rambafile contents
|
8
|
+
# @param path [String] The path to a Rambafile
|
9
|
+
#
|
10
|
+
# @return [Void]
|
11
|
+
def validate(path)
|
12
|
+
file_contents = open(path).read
|
13
|
+
preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Rambafile
|
18
|
+
|
19
|
+
def self.exist
|
20
|
+
Dir[RAMBAFILE_NAME + "*"].count > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.suffix(name)
|
24
|
+
self.rambafile
|
25
|
+
name + @@rambafile_name_suffix
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.rambafile
|
29
|
+
|
30
|
+
if @@rambafile == nil
|
31
|
+
|
32
|
+
files = Dir[RAMBAFILE_NAME + "*"]
|
33
|
+
|
34
|
+
if files.count == 0
|
35
|
+
puts("No Rambafile found".red)
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
if files.count == 1
|
40
|
+
@@rambafile_name = files[0]
|
41
|
+
else
|
42
|
+
prompt = TTY::Prompt.new
|
43
|
+
choices = files.sort
|
44
|
+
@@rambafile_name = prompt.select("Select Rambafile?", choices, per_page: choices.count)
|
45
|
+
end
|
46
|
+
|
47
|
+
@@rambafile_name_suffix = @@rambafile_name[RAMBAFILE_NAME.length..-1]
|
48
|
+
|
49
|
+
self.validate
|
50
|
+
@@rambafile = YAML.load_file(@@rambafile_name)
|
51
|
+
self.load_defaults
|
52
|
+
end
|
53
|
+
|
54
|
+
@@rambafile
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def self.validate
|
60
|
+
rambafile_validator = Viperaptor::RambafileValidator.new
|
61
|
+
rambafile_validator.validate(@@rambafile_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.load_defaults
|
65
|
+
@@rambafile[CATALOGS_KEY] = rambafile[CATALOGS_KEY] || []
|
66
|
+
@@rambafile[TEMPLATES_KEY] = rambafile[TEMPLATES_KEY] || []
|
67
|
+
@@rambafile[COMPANY_KEY] = @@rambafile[COMPANY_KEY] || ''
|
68
|
+
end
|
69
|
+
|
70
|
+
@@rambafile_name = nil
|
71
|
+
@@rambafile = nil
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Viperaptor
|
2
|
+
# Provides a number of helper methods for manipulating Viperaptor template files
|
3
|
+
class TemplateHelper
|
4
|
+
|
5
|
+
def self.detect_template_location(template_name)
|
6
|
+
|
7
|
+
catalogs_path = Pathname.new(ENV['HOME'])
|
8
|
+
.join(APP_HOME_DIR)
|
9
|
+
.join(CATALOGS_DIR)
|
10
|
+
|
11
|
+
catalog_template_list_helper = CatalogTemplateListHelper.new
|
12
|
+
|
13
|
+
catalogs = catalogs_path.children.select { |child|
|
14
|
+
child.directory? && child.split.last.to_s[0] != '.'
|
15
|
+
}
|
16
|
+
|
17
|
+
catalog = ([
|
18
|
+
Pathname.new(Dir.getwd).join(Rambafile.suffix(TEMPLATES_FOLDER)),
|
19
|
+
] + catalogs)
|
20
|
+
.detect do |catalog_path|
|
21
|
+
next if !catalog_path.exist?
|
22
|
+
templates = catalog_template_list_helper.obtain_all_templates_from_a_catalog(catalog_path)
|
23
|
+
templates.include?(template_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
return nil if catalog == nil
|
27
|
+
|
28
|
+
path = catalog_template_list_helper.template_path(catalog, template_name)
|
29
|
+
|
30
|
+
error_description = "Cannot find template named '#{template_name}'! Add it to the Rambafile and run *viperaptor template install*".red
|
31
|
+
raise StandardError, error_description if path.nil?
|
32
|
+
|
33
|
+
path
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a file path for a specific template .rambaspec file
|
37
|
+
# @param template_name [String] The Viperaptor template name
|
38
|
+
#
|
39
|
+
# @return [Pathname]
|
40
|
+
def self.obtain_spec(template_name)
|
41
|
+
template_path = self.obtain_path(template_name)
|
42
|
+
spec_path = template_path.join(template_name + RAMBASPEC_EXTENSION)
|
43
|
+
|
44
|
+
spec_path
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns a file path for a specific template folder
|
48
|
+
# @param template_name [String] The Viperaptor template name
|
49
|
+
#
|
50
|
+
# @return [Pathname]
|
51
|
+
def self.obtain_path(template_name)
|
52
|
+
path = self.detect_template_location(template_name)
|
53
|
+
|
54
|
+
error_description = "Cannot find template named #{template_name}! Add it to the Rambafile and run *viperaptor template install*".red
|
55
|
+
raise StandardError, error_description unless path != nil && path.exist?
|
56
|
+
|
57
|
+
path
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.global_templates
|
61
|
+
|
62
|
+
downloader = CatalogDownloader.new
|
63
|
+
catalog_template_list_helper = CatalogTemplateListHelper.new
|
64
|
+
|
65
|
+
templates = []
|
66
|
+
catalog_paths = downloader.update_all_catalogs_and_return_filepaths(true)
|
67
|
+
catalog_paths.each do |path|
|
68
|
+
templates += catalog_template_list_helper.obtain_all_templates_from_a_catalog(path)
|
69
|
+
templates = templates.uniq
|
70
|
+
end
|
71
|
+
|
72
|
+
templates.sort
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Viperaptor
|
2
|
+
# Provides a number of helper methods for working with xcodeproj gem
|
3
|
+
class XcodeprojHelper
|
4
|
+
# Returns a PBXProject class for a given name
|
5
|
+
# @param project_name [String] The name of the project file
|
6
|
+
#
|
7
|
+
# @return [Xcodeproj::Project]
|
8
|
+
def self.obtain_project(project_name)
|
9
|
+
Xcodeproj::Project.open(project_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Adds a provided file to a specific Project and Target
|
13
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
14
|
+
# @param targets_name [String] Array of targets name
|
15
|
+
# @param group_path [Pathname] The Xcode group path for current file
|
16
|
+
# @param dir_path [Pathname] The directory path for current file
|
17
|
+
# @param file_group_path [String] Directory path
|
18
|
+
# @param file_name [String] Current file name
|
19
|
+
# @param file_is_resource [TrueClass or FalseClass] If true then file is resource
|
20
|
+
#
|
21
|
+
# @return [void]
|
22
|
+
def self.add_file_to_project_and_targets(project, targets_name, group_path, dir_path, file_group_path, file_name, file_is_resource = false)
|
23
|
+
file_path = dir_path
|
24
|
+
file_path = file_path.join(file_group_path) if file_group_path
|
25
|
+
file_path = file_path.join(file_name) if file_name
|
26
|
+
|
27
|
+
module_group = self.retrieve_group_or_create_if_needed(group_path, dir_path, file_group_path, project, true)
|
28
|
+
xcode_file = module_group.new_file(File.absolute_path(file_path))
|
29
|
+
|
30
|
+
targets_name.each do |target|
|
31
|
+
xcode_target = obtain_target(target, project)
|
32
|
+
|
33
|
+
if file_is_resource || self.is_bundle_resource?(file_name)
|
34
|
+
xcode_target.add_resources([xcode_file])
|
35
|
+
elsif self.is_compile_source?(file_name)
|
36
|
+
xcode_target.add_file_references([xcode_file])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Adds a provided directory to a specific Project
|
42
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
43
|
+
# @param group_path [Pathname] The Xcode group path for current directory
|
44
|
+
# @param dir_path [Pathname] The directory path for current directory
|
45
|
+
# @param directory_name [String] Current directory name
|
46
|
+
#
|
47
|
+
# @return [void]
|
48
|
+
def self.add_group_to_project(project, group_path, dir_path, directory_name)
|
49
|
+
self.retrieve_group_or_create_if_needed(group_path, dir_path, directory_name, project, true)
|
50
|
+
end
|
51
|
+
|
52
|
+
# File is a compiled source
|
53
|
+
# @param file_name [String] String of file name
|
54
|
+
#
|
55
|
+
# @return [TrueClass or FalseClass]
|
56
|
+
def self.is_compile_source?(file_name)
|
57
|
+
File.extname(file_name) == '.m' || File.extname(file_name) == '.swift' || File.extname(file_name) == '.mm'
|
58
|
+
end
|
59
|
+
|
60
|
+
# File is a resource
|
61
|
+
# @param resource_name [String] String of resource name
|
62
|
+
#
|
63
|
+
# @return [TrueClass or FalseClass]
|
64
|
+
def self.is_bundle_resource?(resource_name)
|
65
|
+
File.extname(resource_name) == '.xib' || File.extname(resource_name) == '.storyboard'
|
66
|
+
end
|
67
|
+
|
68
|
+
# Recursively clears children of the given group
|
69
|
+
# @param project [Xcodeproj::Project] The working Xcode project file
|
70
|
+
# @param group_path [Pathname] The full group path
|
71
|
+
#
|
72
|
+
# @return [Void]
|
73
|
+
def self.clear_group(project, targets_name, group_path)
|
74
|
+
module_group = self.retrieve_group_or_create_if_needed(group_path, nil, nil, project, false)
|
75
|
+
return unless module_group
|
76
|
+
|
77
|
+
files_path = self.files_path_from_group(module_group, project)
|
78
|
+
return unless files_path
|
79
|
+
|
80
|
+
files_path.each do |file_path|
|
81
|
+
self.remove_file_by_file_path(file_path, targets_name, project)
|
82
|
+
end
|
83
|
+
|
84
|
+
module_group.clear
|
85
|
+
end
|
86
|
+
|
87
|
+
# Finds a group in a xcodeproj file with a given path
|
88
|
+
# @param project [Xcodeproj::Project] The working Xcode project file
|
89
|
+
# @param group_path [Pathname] The full group path
|
90
|
+
#
|
91
|
+
# @return [TrueClass or FalseClass]
|
92
|
+
def self.module_with_group_path_already_exists(project, group_path)
|
93
|
+
module_group = self.retrieve_group_or_create_if_needed(group_path, nil, nil, project, false)
|
94
|
+
module_group.nil? ? false : true
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
# Finds or creates a group in a xcodeproj file with a given path
|
100
|
+
# @param group_path [Pathname] The Xcode group path for module
|
101
|
+
# @param dir_path [Pathname] The directory path for module
|
102
|
+
# @param file_group_path [String] Directory path
|
103
|
+
# @param project [Xcodeproj::Project] The working Xcode project file
|
104
|
+
# @param create_group_if_not_exists [TrueClass or FalseClass] If true nonexistent group will be created
|
105
|
+
#
|
106
|
+
# @return [PBXGroup]
|
107
|
+
def self.retrieve_group_or_create_if_needed(group_path, dir_path, file_group_path, project, create_group_if_not_exists)
|
108
|
+
group_names = path_names_from_path(group_path)
|
109
|
+
group_components_count = group_names.count
|
110
|
+
group_names += path_names_from_path(file_group_path) if file_group_path
|
111
|
+
|
112
|
+
final_group = project
|
113
|
+
|
114
|
+
group_names.each_with_index do |group_name, index|
|
115
|
+
next_group = final_group[group_name]
|
116
|
+
|
117
|
+
unless next_group
|
118
|
+
return nil unless create_group_if_not_exists
|
119
|
+
|
120
|
+
if group_path != dir_path && index == group_components_count-1
|
121
|
+
next_group = final_group.new_group(group_name, dir_path, :project)
|
122
|
+
else
|
123
|
+
next_group = final_group.new_group(group_name, group_name)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
final_group = next_group
|
128
|
+
end
|
129
|
+
|
130
|
+
final_group
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns an AbstractTarget class for a given name
|
134
|
+
# @param target_name [String] The name of the target
|
135
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
136
|
+
#
|
137
|
+
# @return [Xcodeproj::AbstractTarget]
|
138
|
+
def self.obtain_target(target_name, project)
|
139
|
+
project.targets.each do |target|
|
140
|
+
return target if target.name == target_name
|
141
|
+
end
|
142
|
+
|
143
|
+
error_description = "Cannot find a target with name #{target_name} in Xcode project".red
|
144
|
+
raise StandardError, error_description
|
145
|
+
end
|
146
|
+
|
147
|
+
# Splits the provided Xcode path to an array of separate paths
|
148
|
+
# @param path The full group or file path
|
149
|
+
#
|
150
|
+
# @return [[String]]
|
151
|
+
def self.path_names_from_path(path)
|
152
|
+
path.to_s.split('/')
|
153
|
+
end
|
154
|
+
|
155
|
+
# Remove build file from target build phase
|
156
|
+
# @param file_path [String] The path of the file
|
157
|
+
# @param targets_name [String] Array of targets
|
158
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
159
|
+
#
|
160
|
+
# @return [Void]
|
161
|
+
def self.remove_file_by_file_path(file_path, targets_name, project)
|
162
|
+
file_names = path_names_from_path(file_path)
|
163
|
+
|
164
|
+
build_phases = nil
|
165
|
+
|
166
|
+
if self.is_compile_source?(file_names.last)
|
167
|
+
build_phases = self.build_phases_from_targets(targets_name, project)
|
168
|
+
elsif self.is_bundle_resource?(file_names.last)
|
169
|
+
build_phases = self.resources_build_phase_from_targets(targets_name, project)
|
170
|
+
end
|
171
|
+
|
172
|
+
self.remove_file_from_build_phases(file_path, build_phases)
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.remove_file_from_build_phases(file_path, build_phases)
|
176
|
+
return if build_phases.nil?
|
177
|
+
|
178
|
+
build_phases.each do |build_phase|
|
179
|
+
build_phase.files.each do |build_file|
|
180
|
+
next if build_file.nil? || build_file.file_ref.nil?
|
181
|
+
|
182
|
+
build_file_path = self.configure_file_ref_path(build_file.file_ref)
|
183
|
+
|
184
|
+
if build_file_path == file_path
|
185
|
+
build_phase.remove_build_file(build_file)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Find and return target build phases
|
192
|
+
# @param targets_name [String] Array of targets
|
193
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
194
|
+
#
|
195
|
+
# @return [[PBXSourcesBuildPhase]]
|
196
|
+
def self.build_phases_from_targets(targets_name, project)
|
197
|
+
build_phases = []
|
198
|
+
|
199
|
+
targets_name.each do |target_name|
|
200
|
+
xcode_target = self.obtain_target(target_name, project)
|
201
|
+
xcode_target.build_phases.each do |build_phase|
|
202
|
+
if build_phase.isa == 'PBXSourcesBuildPhase'
|
203
|
+
build_phases.push(build_phase)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
build_phases
|
209
|
+
end
|
210
|
+
|
211
|
+
# Find and return target resources build phase
|
212
|
+
# @param targets_name [String] Array of targets
|
213
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
214
|
+
#
|
215
|
+
# @return [[PBXResourcesBuildPhase]]
|
216
|
+
def self.resources_build_phase_from_targets(targets_name, project)
|
217
|
+
resource_build_phase = []
|
218
|
+
|
219
|
+
targets_name.each do |target_name|
|
220
|
+
xcode_target = self.obtain_target(target_name, project)
|
221
|
+
resource_build_phase.push(xcode_target.resources_build_phase)
|
222
|
+
end
|
223
|
+
|
224
|
+
resource_build_phase
|
225
|
+
end
|
226
|
+
|
227
|
+
# Get configure file full path
|
228
|
+
# @param file_ref [PBXFileReference] Build file
|
229
|
+
#
|
230
|
+
# @return [String]
|
231
|
+
def self.configure_file_ref_path(file_ref)
|
232
|
+
build_file_ref_path = file_ref.hierarchy_path.to_s
|
233
|
+
build_file_ref_path[0] = ''
|
234
|
+
|
235
|
+
build_file_ref_path
|
236
|
+
end
|
237
|
+
|
238
|
+
# Get all files path from group path
|
239
|
+
# @param module_group [PBXGroup] The module group
|
240
|
+
# @param project [Xcodeproj::Project] The target xcodeproj file
|
241
|
+
#
|
242
|
+
# @return [[String]]
|
243
|
+
def self.files_path_from_group(module_group, _project)
|
244
|
+
files_path = []
|
245
|
+
|
246
|
+
module_group.recursive_children.each do |file_ref|
|
247
|
+
if file_ref.isa == 'PBXFileReference'
|
248
|
+
file_ref_path = configure_file_ref_path(file_ref)
|
249
|
+
files_path.push(file_ref_path)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
files_path
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'viperaptor/helpers/xcodeproj_helper.rb'
|
4
|
+
require 'viperaptor/helpers/module_info_generator.rb'
|
5
|
+
|
6
|
+
module Viperaptor
|
7
|
+
|
8
|
+
# Responsible for creating the whole code module using information from the CLI
|
9
|
+
class ModuleGenerator
|
10
|
+
|
11
|
+
def generate_module(name, code_module, template)
|
12
|
+
# Setting up Xcode objects
|
13
|
+
project = XcodeprojHelper.obtain_project(code_module.xcodeproj_path)
|
14
|
+
|
15
|
+
# Configuring file paths
|
16
|
+
FileUtils.mkdir_p code_module.project_file_path if code_module.project_file_path
|
17
|
+
FileUtils.mkdir_p code_module.test_file_path if code_module.test_file_path
|
18
|
+
|
19
|
+
# Creating code files
|
20
|
+
if code_module.project_targets && code_module.project_group_path && code_module.project_file_path
|
21
|
+
puts('Creating code files...')
|
22
|
+
process_files_if_needed(template.code_files,
|
23
|
+
code_module,
|
24
|
+
template,
|
25
|
+
project,
|
26
|
+
code_module.project_targets,
|
27
|
+
code_module.project_group_path,
|
28
|
+
code_module.project_file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Creating test files
|
32
|
+
if code_module.test_targets && code_module.test_group_path && code_module.test_file_path
|
33
|
+
puts('Creating test files...')
|
34
|
+
process_files_if_needed(template.test_files,
|
35
|
+
code_module,
|
36
|
+
template,
|
37
|
+
project,
|
38
|
+
code_module.test_targets,
|
39
|
+
code_module.test_group_path,
|
40
|
+
code_module.test_file_path,
|
41
|
+
[code_module.project_group_path])
|
42
|
+
end
|
43
|
+
|
44
|
+
# Saving the current changes in the Xcode project
|
45
|
+
project.save
|
46
|
+
|
47
|
+
puts 'Module successfully created!'
|
48
|
+
puts "Name: #{name}".green
|
49
|
+
puts "Project file path: #{code_module.project_file_path}".green if code_module.project_file_path
|
50
|
+
puts "Project group path: #{code_module.project_group_path}".green if code_module.project_group_path
|
51
|
+
puts "Test file path: #{code_module.test_file_path}".green if code_module.test_file_path
|
52
|
+
puts "Test group path: #{code_module.test_group_path}".green if code_module.test_group_path
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_files_if_needed(files, code_module, template, project, targets, group_path, dir_path, processed_groups = [])
|
56
|
+
# It's possible that current project doesn't test targets configured, so it doesn't need to generate tests.
|
57
|
+
# The same is for files property - a template can have only test or project files
|
58
|
+
if targets.count == 0 || files == nil || files.count == 0 || dir_path == nil || group_path == nil
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
XcodeprojHelper.clear_group(project, targets, group_path) unless processed_groups.include? group_path
|
63
|
+
files.each do |file|
|
64
|
+
unless file[TEMPLATE_FILE_PATH_KEY]
|
65
|
+
directory_name = file[TEMPLATE_NAME_KEY].gsub(/^\/|\/$/, '')
|
66
|
+
file_group = dir_path.join(directory_name)
|
67
|
+
|
68
|
+
FileUtils.mkdir_p file_group
|
69
|
+
XcodeprojHelper.add_group_to_project(project, group_path, dir_path, directory_name)
|
70
|
+
|
71
|
+
next
|
72
|
+
end
|
73
|
+
|
74
|
+
file_group = File.dirname(file[TEMPLATE_NAME_KEY])
|
75
|
+
file_group = nil if file_group == '.'
|
76
|
+
|
77
|
+
module_info = ModuleInfoGenerator.new(code_module)
|
78
|
+
|
79
|
+
# Generating the content of the code file and it's name
|
80
|
+
file_name, file_content = ContentGenerator.create_file(file, module_info.scope, template)
|
81
|
+
file_path = dir_path
|
82
|
+
file_path = file_path.join(file_group) if file_group
|
83
|
+
file_path = file_path.join(file_name) if file_name
|
84
|
+
|
85
|
+
# Creating the file in the filesystem
|
86
|
+
FileUtils.mkdir_p File.dirname(file_path)
|
87
|
+
File.open(file_path, 'w+') do |f|
|
88
|
+
f.write(file_content)
|
89
|
+
end
|
90
|
+
|
91
|
+
file_is_resource = file[TEMPLATE_FILE_IS_RESOURCE_KEY]
|
92
|
+
|
93
|
+
# Creating the file in the Xcode project
|
94
|
+
XcodeprojHelper.add_file_to_project_and_targets(project,
|
95
|
+
targets,
|
96
|
+
group_path,
|
97
|
+
dir_path,
|
98
|
+
file_group,
|
99
|
+
file_name,
|
100
|
+
file_is_resource)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
//
|
2
|
+
// {{ prefix }}{{ module_info.name }}{{ module_info.file_name }}
|
3
|
+
// {{ module_info.project_name }}
|
4
|
+
//
|
5
|
+
// Created by {{ developer.name }} on {{ date }}.
|
6
|
+
// Copyright {{ year }} {{ developer.company }}. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
@interface {{ prefix }}{{ module_info.name }}Service : NSObject
|
10
|
+
|
11
|
+
@end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
//
|
2
|
+
// {{ prefix }}{{ module_info.name }}{{ module_info.file_name }}
|
3
|
+
// {{ module_info.project_name }}
|
4
|
+
//
|
5
|
+
// Created by {{ developer.name }} on {{ date }}.
|
6
|
+
// Copyright {{ year }} {{ developer.company }}. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#import "{{ prefix }}{{ module_info.name }}Service.h"
|
10
|
+
|
11
|
+
@implementation {{ prefix }}{{ module_info.name }}Service
|
12
|
+
|
13
|
+
@end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
//
|
2
|
+
// {{ prefix }}{{ module_info.name }}{{ module_info.file_name }}
|
3
|
+
// {{ module_info.project_name }}
|
4
|
+
//
|
5
|
+
// Created by {{ developer.name }} on {{ date }}.
|
6
|
+
// Copyright {{ year }} {{ developer.company }}. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#import <XCTest/XCTest.h>
|
10
|
+
|
11
|
+
#import "{{ prefix }}{{ module_info.name }}Service.h"
|
12
|
+
|
13
|
+
@interface {{ prefix }}{{ module_info.name }}ServiceTests : XCTestCase
|
14
|
+
|
15
|
+
@property (strong, nonatomic) {{ prefix }}{{ module_info.name }}Service *service;
|
16
|
+
|
17
|
+
@end
|
18
|
+
|
19
|
+
@implementation {{ prefix }}{{ module_info.name }}ServiceTests
|
20
|
+
|
21
|
+
#pragma mark - Test environment setup
|
22
|
+
|
23
|
+
- (void)setUp {
|
24
|
+
[super setUp];
|
25
|
+
|
26
|
+
self.service = [[{{ prefix }}{{ module_info.name }}Service alloc] init];
|
27
|
+
}
|
28
|
+
|
29
|
+
- (void)tearDown {
|
30
|
+
self.service = nil;
|
31
|
+
|
32
|
+
[super tearDown];
|
33
|
+
}
|
34
|
+
|
35
|
+
@end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Template information section
|
2
|
+
name: {{ name }}
|
3
|
+
summary: {{ summary }}
|
4
|
+
author: {{ author }}
|
5
|
+
version: 1.0.0
|
6
|
+
license: {{ license }}
|
7
|
+
|
8
|
+
# The declarations for code files
|
9
|
+
code_files:
|
10
|
+
- {name: Service/Service.h, path: Code/Service/service.h.liquid}
|
11
|
+
- {name: Service/Service.m, path: Code/Service/service.m.liquid}
|
12
|
+
|
13
|
+
# The declarations for test files
|
14
|
+
test_files:
|
15
|
+
- {name: Service/ServiceTests.m, path: Tests/Service/service_tests.m.liquid}
|
16
|
+
|
17
|
+
# Template dependencies
|
18
|
+
dependencies:
|
19
|
+
{% for dependency in dependencies %}- {{ dependency }}
|
20
|
+
{% endfor %}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Viperaptor
|
2
|
+
|
3
|
+
# Responsible for generating new .rambaspec files
|
4
|
+
class TemplateCreator
|
5
|
+
|
6
|
+
NEW_TEMPLATE_FOLDER = 'new_template'
|
7
|
+
RAMBASPEC_TEMPLATE_NAME = 'template.rambaspec.liquid'
|
8
|
+
CODE_FOLDER = 'Code'
|
9
|
+
TESTS_FOLDER = 'Tests'
|
10
|
+
|
11
|
+
# Generates and saves to filesystem a new template with a .rambaspec file and sample code and tests files
|
12
|
+
# @param properties [Hash] User-inputted template properties
|
13
|
+
#
|
14
|
+
# @return [Void]
|
15
|
+
def create_template(properties)
|
16
|
+
template_dir_path = Pathname.new(File.dirname(__FILE__)).join(NEW_TEMPLATE_FOLDER)
|
17
|
+
rambaspec_template_file_path = template_dir_path.join(RAMBASPEC_TEMPLATE_NAME)
|
18
|
+
code_file_path = template_dir_path.join(CODE_FOLDER)
|
19
|
+
tests_file_path = template_dir_path.join(TESTS_FOLDER)
|
20
|
+
|
21
|
+
file_source = IO.read(rambaspec_template_file_path)
|
22
|
+
|
23
|
+
template = Liquid::Template.parse(file_source)
|
24
|
+
output = template.render(properties)
|
25
|
+
|
26
|
+
result_name = properties[TEMPLATE_NAME_KEY] + RAMBASPEC_EXTENSION
|
27
|
+
result_dir_path = Pathname.new(properties[TEMPLATE_NAME_KEY])
|
28
|
+
|
29
|
+
FileUtils.mkdir_p result_dir_path
|
30
|
+
FileUtils.cp_r(code_file_path, result_dir_path)
|
31
|
+
FileUtils.cp_r(tests_file_path, result_dir_path)
|
32
|
+
|
33
|
+
File.open(result_dir_path.join(result_name), 'w+') {|f|
|
34
|
+
f.write(output)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|