viperaptor 2.0.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 +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
|