generamba-mp 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +10 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +17 -0
  6. data/CHANGELOG.md +180 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +62 -0
  10. data/Rakefile +6 -0
  11. data/VISION.md +41 -0
  12. data/bin/console +14 -0
  13. data/bin/generamba +5 -0
  14. data/bin/setup +7 -0
  15. data/docs/2.x/roadmap.md +365 -0
  16. data/generamba.gemspec +38 -0
  17. data/lib/generamba.rb +16 -0
  18. data/lib/generamba/cli/cli.rb +16 -0
  19. data/lib/generamba/cli/gen_command.rb +76 -0
  20. data/lib/generamba/cli/setup_command.rb +122 -0
  21. data/lib/generamba/cli/setup_username_command.rb +21 -0
  22. data/lib/generamba/cli/template/template_create_command.rb +40 -0
  23. data/lib/generamba/cli/template/template_group.rb +14 -0
  24. data/lib/generamba/cli/template/template_install_command.rb +21 -0
  25. data/lib/generamba/cli/template/template_list_command.rb +25 -0
  26. data/lib/generamba/cli/template/template_search_command.rb +30 -0
  27. data/lib/generamba/cli/thor_extension.rb +47 -0
  28. data/lib/generamba/cli/version_command.rb +25 -0
  29. data/lib/generamba/code_generation/Rambafile.liquid +41 -0
  30. data/lib/generamba/code_generation/code_module.rb +100 -0
  31. data/lib/generamba/code_generation/content_generator.rb +43 -0
  32. data/lib/generamba/code_generation/module_template.rb +28 -0
  33. data/lib/generamba/code_generation/rambafile_generator.rb +23 -0
  34. data/lib/generamba/configuration/user_preferences.rb +50 -0
  35. data/lib/generamba/constants/constants.rb +12 -0
  36. data/lib/generamba/constants/rambafile_constants.rb +31 -0
  37. data/lib/generamba/constants/rambaspec_constants.rb +18 -0
  38. data/lib/generamba/constants/user_preferences_constants.rb +5 -0
  39. data/lib/generamba/helpers/dependency_checker.rb +54 -0
  40. data/lib/generamba/helpers/gen_command_table_parameters_formatter.rb +33 -0
  41. data/lib/generamba/helpers/module_info_generator.rb +33 -0
  42. data/lib/generamba/helpers/module_validator.rb +85 -0
  43. data/lib/generamba/helpers/print_table.rb +17 -0
  44. data/lib/generamba/helpers/rambafile_validator.rb +18 -0
  45. data/lib/generamba/helpers/template_helper.rb +30 -0
  46. data/lib/generamba/helpers/xcodeproj_helper.rb +256 -0
  47. data/lib/generamba/module_generator.rb +104 -0
  48. data/lib/generamba/template/creator/new_template/Code/Service/service.h.liquid +11 -0
  49. data/lib/generamba/template/creator/new_template/Code/Service/service.m.liquid +13 -0
  50. data/lib/generamba/template/creator/new_template/Tests/Service/service_tests.m.liquid +35 -0
  51. data/lib/generamba/template/creator/new_template/template.rambaspec.liquid +20 -0
  52. data/lib/generamba/template/creator/template_creator.rb +39 -0
  53. data/lib/generamba/template/helpers/catalog_downloader.rb +58 -0
  54. data/lib/generamba/template/helpers/catalog_template_list_helper.rb +23 -0
  55. data/lib/generamba/template/helpers/catalog_template_search_helper.rb +27 -0
  56. data/lib/generamba/template/helpers/catalog_terminator.rb +21 -0
  57. data/lib/generamba/template/helpers/rambaspec_validator.rb +52 -0
  58. data/lib/generamba/template/installer/abstract_installer.rb +9 -0
  59. data/lib/generamba/template/installer/catalog_installer.rb +73 -0
  60. data/lib/generamba/template/installer/local_installer.rb +32 -0
  61. data/lib/generamba/template/installer/remote_installer.rb +50 -0
  62. data/lib/generamba/template/installer/template_installer_factory.rb +22 -0
  63. data/lib/generamba/template/processor/template_declaration.rb +36 -0
  64. data/lib/generamba/template/processor/template_processor.rb +75 -0
  65. data/lib/generamba/tools/string-colorize.rb +23 -0
  66. data/lib/generamba/version.rb +5 -0
  67. metadata +271 -0
@@ -0,0 +1,33 @@
1
+ module Generamba
2
+ # Provides methods for prepare parameters for displaying in table.
3
+ class GenCommandTableParametersFormatter
4
+ require 'json'
5
+
6
+ # This method prepared parameter for displaying
7
+ def self.prepare_parameters_for_displaying(code_module, template_name)
8
+ params = {}
9
+
10
+ params['Targets'] = code_module.project_targets.join(',') if code_module.project_targets
11
+ params['Module path'] = code_module.project_file_path if code_module.project_file_path
12
+
13
+ if code_module.project_file_path != code_module.project_group_path
14
+ params['Module group path'] = code_module.project_group_path
15
+ end
16
+
17
+ params['Test targets'] = code_module.test_targets.join(',') if code_module.test_targets
18
+ params['Test file path'] = code_module.test_file_path if code_module.test_file_path
19
+
20
+ if code_module.test_file_path != code_module.test_group_path
21
+ params['Test group path'] = code_module.test_group_path
22
+ end
23
+
24
+ params['Template'] = template_name
25
+
26
+ unless code_module.custom_parameters.empty?
27
+ params['Custom parameters'] = code_module.custom_parameters.to_json
28
+ end
29
+
30
+ params
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Generamba
2
+
3
+ class ModuleInfoGenerator
4
+ attr_reader :scope
5
+
6
+ def initialize(code_module)
7
+ module_info = {
8
+ 'name' => code_module.name,
9
+ 'description' => code_module.description,
10
+ 'project_name' => code_module.project_name,
11
+ 'product_module_name' => code_module.product_module_name,
12
+ 'project_targets' => code_module.project_targets,
13
+ 'test_targets' => code_module.test_targets
14
+ }
15
+
16
+ developer = {
17
+ 'name' => code_module.author,
18
+ 'company' => code_module.company
19
+ }
20
+
21
+ @scope = {
22
+ 'year' => code_module.year,
23
+ 'date' => Time.now.strftime('%d/%m/%Y'),
24
+ 'developer' => developer,
25
+ 'module_info' => module_info,
26
+ 'prefix' => code_module.prefix,
27
+ 'custom_parameters' => code_module.custom_parameters
28
+ }
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,85 @@
1
+ module Generamba
2
+ # Provides methods for validating module
3
+ class ModuleValidator
4
+
5
+ TARGET_TYPE_PROJECT = 'project'
6
+ TARGET_TYPE_TEST = 'test'
7
+
8
+ # Method validates module
9
+ # @param code_module [CodeModule] The instance of CodeModule
10
+ #
11
+ # @return [Void]
12
+ def validate(code_module)
13
+ mandatory_fields = [COMPANY_KEY,
14
+ PROJECT_NAME_KEY,
15
+ XCODEPROJ_PATH_KEY]
16
+
17
+ mandatory_fields.each do |field|
18
+ unless code_module.instance_variable_get("@#{field}")
19
+ puts "Module is broken! *#{field}* field cannot be empty, because it is mandatory.".red
20
+ exit
21
+ end
22
+ end
23
+
24
+ project_failure_fields = all_project_failure_fields(code_module)
25
+ test_failure_fields = all_test_failure_fields(code_module)
26
+ failure_fields = project_failure_fields + test_failure_fields
27
+
28
+ if failure_fields.count > 0
29
+ puts "Module is broken! *#{failure_fields}* field cannot be empty, because it is mandatory.".red
30
+ exit
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # Method which return all project failure fields
37
+ # @param code_module [CodeModule] The instance of CodeModule
38
+ #
39
+ # @return [Array]
40
+ def all_project_failure_fields(code_module)
41
+ return [] if !code_module.project_targets && !code_module.project_file_path && !code_module.project_group_path
42
+
43
+ all_nil_mandatory_fields_for_target_type(TARGET_TYPE_PROJECT, code_module)
44
+ end
45
+
46
+ # Method which return all test failure fields
47
+ # @param code_module [CodeModule] The instance of CodeModule
48
+ #
49
+ # @return [Array]
50
+ def all_test_failure_fields(code_module)
51
+ return [] if !code_module.test_targets && !code_module.test_file_path && !code_module.test_group_path
52
+
53
+ all_nil_mandatory_fields_for_target_type(TARGET_TYPE_TEST, code_module)
54
+ end
55
+
56
+ # Method which return all failure fields for target_type
57
+ # @param target_type [String] "project" or "test"
58
+ # @param code_module [CodeModule] The instance of CodeModule
59
+ #
60
+ # @return [Array]
61
+ def all_nil_mandatory_fields_for_target_type(target_type, code_module)
62
+ fields = []
63
+
64
+ variable_name = "#{target_type}_targets"
65
+
66
+ unless code_module.instance_variable_get("@#{variable_name}")
67
+ target_const_value = Generamba.const_get(target_type.upcase + '_TARGET_KEY')
68
+ targets_const_value = Generamba.const_get(target_type.upcase + '_TARGETS_KEY')
69
+ fields.push(target_const_value)
70
+ fields.push(targets_const_value)
71
+ end
72
+
73
+ variable_name = "#{target_type}_file_path"
74
+ file_path_const_value = Generamba.const_get(target_type.upcase + '_FILE_PATH_KEY')
75
+ fields.push(file_path_const_value) unless code_module.instance_variable_get("@#{variable_name}")
76
+
77
+ variable_name = "#{target_type}_group_path"
78
+ group_path_const_value = Generamba.const_get(target_type.upcase + '_GROUP_PATH_KEY')
79
+ fields.push(group_path_const_value) unless code_module.instance_variable_get("@#{variable_name}")
80
+
81
+ fields
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ module Generamba
2
+ # Provides methods for print parameters in nice table.
3
+ class PrintTable
4
+ # This method prints out all the user inputs in a nice table.
5
+ def self.print_values(values: nil, title: nil)
6
+ require 'terminal-table'
7
+
8
+ params = {}
9
+ params[:rows] = values
10
+ params[:title] = title.green if title
11
+
12
+ puts ''
13
+ puts Terminal::Table.new(params)
14
+ puts ''
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Generamba
2
+ # Provides methods for validating Rambafile contents
3
+ class RambafileValidator
4
+ # Method validates Rambafile contents
5
+ # @param path [String] The path to a Rambafile
6
+ #
7
+ # @return [Void]
8
+ def validate(path)
9
+ file_contents = open(path).read
10
+ preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
11
+
12
+ unless preferences[TEMPLATES_KEY]
13
+ puts "You can't run *generamba gen* without any templates installed. Add their declarations to a Rambafile and run *generamba template install*.".red
14
+ exit
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ module Generamba
2
+ # Provides a number of helper methods for manipulating Generamba template files
3
+ class TemplateHelper
4
+ # Returns a file path for a specific template .rambaspec file
5
+ # @param template_name [String] The Generamba template name
6
+ #
7
+ # @return [Pathname]
8
+ def self.obtain_spec(template_name)
9
+ template_path = self.obtain_path(template_name)
10
+ spec_path = template_path.join(template_name + RAMBASPEC_EXTENSION)
11
+
12
+ spec_path
13
+ end
14
+
15
+ # Returns a file path for a specific template folder
16
+ # @param template_name [String] The Generamba template name
17
+ #
18
+ # @return [Pathname]
19
+ def self.obtain_path(template_name)
20
+ path = Pathname.new(Dir.getwd)
21
+ .join(TEMPLATES_FOLDER)
22
+ .join(template_name)
23
+
24
+ error_description = "Cannot find template named #{template_name}! Add it to the Rambafile and run *generamba template install*".red
25
+ raise StandardError, error_description unless path.exist?
26
+
27
+ path
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,256 @@
1
+ module Generamba
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